aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--.circleci/config.yml6
-rw-r--r--.gitlab-ci.yml6
-rw-r--r--.travis.yml3
-rw-r--r--CHANGES10
-rw-r--r--CONTRIBUTING.md2
-rw-r--r--Makefile.ci1
-rw-r--r--checker/subtyping.ml8
-rw-r--r--checker/univ.ml7
-rw-r--r--checker/univ.mli2
-rw-r--r--clib/cList.ml14
-rw-r--r--clib/cList.mli8
-rw-r--r--configure.ml16
-rw-r--r--dev/ci/ci-basic-overlay.sh6
-rwxr-xr-xdev/ci/ci-elpi.sh10
-rw-r--r--dev/ci/user-overlays/06745-ejgallego-located+vernac.sh13
-rw-r--r--dev/doc/changes.md8
-rwxr-xr-xdev/tools/check-eof-newline.sh31
-rwxr-xr-xdev/tools/pre-commit73
-rw-r--r--doc/common/macros.tex1
-rw-r--r--doc/refman/RefMan-lib.tex1
-rw-r--r--doc/refman/RefMan-syn.tex398
-rw-r--r--engine/evd.ml2
-rw-r--r--engine/evd.mli2
-rw-r--r--engine/uState.ml6
-rw-r--r--engine/uState.mli2
-rw-r--r--engine/universes.ml4
-rw-r--r--engine/universes.mli2
-rw-r--r--interp/constrexpr_ops.ml251
-rw-r--r--interp/constrexpr_ops.mli24
-rw-r--r--interp/constrextern.ml149
-rw-r--r--interp/constrintern.ml686
-rw-r--r--interp/constrintern.mli5
-rw-r--r--interp/declare.ml2
-rw-r--r--interp/declare.mli2
-rw-r--r--interp/dumpglob.ml6
-rw-r--r--interp/dumpglob.mli2
-rw-r--r--interp/implicit_quantifiers.ml36
-rw-r--r--interp/implicit_quantifiers.mli9
-rw-r--r--interp/notation.ml110
-rw-r--r--interp/notation.mli12
-rw-r--r--interp/notation_ops.ml841
-rw-r--r--interp/notation_ops.mli8
-rw-r--r--interp/ppextend.ml1
-rw-r--r--interp/ppextend.mli1
-rw-r--r--interp/reserve.ml4
-rw-r--r--interp/reserve.mli3
-rw-r--r--interp/stdarg.mli6
-rw-r--r--interp/topconstr.mli3
-rw-r--r--intf/constrexpr.ml38
-rw-r--r--intf/extend.ml49
-rw-r--r--intf/genredexpr.ml4
-rw-r--r--intf/glob_term.ml2
-rw-r--r--intf/intf.mllib2
-rw-r--r--intf/misctypes.ml14
-rw-r--r--intf/notation_term.ml24
-rw-r--r--intf/vernacexpr.ml43
-rw-r--r--kernel/subtyping.ml9
-rw-r--r--kernel/univ.ml7
-rw-r--r--kernel/univ.mli3
-rw-r--r--library/declaremods.ml5
-rw-r--r--library/declaremods.mli2
-rw-r--r--parsing/egramcoq.ml68
-rw-r--r--parsing/g_constr.ml472
-rw-r--r--parsing/g_prim.ml414
-rw-r--r--parsing/g_proofs.ml42
-rw-r--r--parsing/g_vernac.ml451
-rw-r--r--parsing/pcoq.ml12
-rw-r--r--parsing/pcoq.mli25
-rw-r--r--plugins/funind/glob_term_to_relation.ml20
-rw-r--r--plugins/funind/glob_termops.ml2
-rw-r--r--plugins/funind/indfun.ml86
-rw-r--r--plugins/ltac/coretactics.ml42
-rw-r--r--plugins/ltac/extraargs.ml414
-rw-r--r--plugins/ltac/extraargs.mli8
-rw-r--r--plugins/ltac/extratactics.ml42
-rw-r--r--plugins/ltac/g_ltac.ml422
-rw-r--r--plugins/ltac/g_tactic.ml465
-rw-r--r--plugins/ltac/pltac.mli7
-rw-r--r--plugins/ltac/pptactic.ml35
-rw-r--r--plugins/ltac/rewrite.ml4
-rw-r--r--plugins/ltac/tacentries.ml9
-rw-r--r--plugins/ltac/tacexpr.mli16
-rw-r--r--plugins/ltac/tacintern.ml44
-rw-r--r--plugins/ltac/tacintern.mli2
-rw-r--r--plugins/ltac/tacinterp.ml73
-rw-r--r--plugins/ltac/tacinterp.mli6
-rw-r--r--plugins/ltac/tactic_debug.mli2
-rw-r--r--plugins/ltac/tactic_matching.ml4
-rw-r--r--plugins/ltac/tauto.ml6
-rw-r--r--plugins/omega/PreOmega.v6
-rw-r--r--plugins/quote/g_quote.ml42
-rw-r--r--plugins/setoid_ring/newring.ml6
-rw-r--r--plugins/ssr/ssrcommon.ml8
-rw-r--r--plugins/ssr/ssrparser.ml478
-rw-r--r--plugins/ssr/ssrvernac.ml428
-rw-r--r--plugins/ssrmatching/ssrmatching.ml412
-rw-r--r--pretyping/cases.ml5
-rw-r--r--pretyping/glob_ops.ml38
-rw-r--r--pretyping/glob_ops.mli10
-rw-r--r--pretyping/pretyping.ml30
-rw-r--r--pretyping/pretyping.mli7
-rw-r--r--pretyping/univdecls.ml7
-rw-r--r--pretyping/univdecls.mli2
-rw-r--r--printing/ppconstr.ml146
-rw-r--r--printing/ppconstr.mli15
-rw-r--r--printing/pputils.ml4
-rw-r--r--printing/pputils.mli1
-rw-r--r--printing/ppvernac.ml86
-rw-r--r--printing/ppvernac.mli2
-rw-r--r--printing/prettyp.mli4
-rw-r--r--printing/printmod.mli2
-rw-r--r--proofs/proof_global.ml2
-rw-r--r--proofs/proof_global.mli2
-rw-r--r--stm/stm.ml12
-rw-r--r--stm/vernac_classifier.ml44
-rw-r--r--tactics/equality.ml2
-rw-r--r--tactics/tactics.ml4
-rw-r--r--test-suite/bugs/closed/5532.v15
-rw-r--r--test-suite/bugs/closed/6529.v16
-rw-r--r--test-suite/bugs/opened/6602.v17
-rw-r--r--test-suite/modules/cumpoly.v19
-rw-r--r--test-suite/output/Notations.out2
-rw-r--r--test-suite/output/Notations2.out7
-rw-r--r--test-suite/output/Notations2.v5
-rw-r--r--test-suite/output/Notations3.out97
-rw-r--r--test-suite/output/Notations3.v167
-rw-r--r--test-suite/output/PatternsInBinders.out8
-rw-r--r--test-suite/output/PatternsInBinders.v5
-rw-r--r--test-suite/success/Notations2.v29
-rw-r--r--theories/Arith/Lt.v5
-rw-r--r--theories/Init/Logic.v7
-rw-r--r--theories/Init/Notations.v27
-rw-r--r--theories/Init/Specif.v9
-rw-r--r--theories/Unicode/Utf8_core.v15
-rw-r--r--toplevel/vernac.ml2
-rw-r--r--vernac/classes.ml4
-rw-r--r--vernac/comAssumption.ml12
-rw-r--r--vernac/comAssumption.mli2
-rw-r--r--vernac/comFixpoint.ml8
-rw-r--r--vernac/comFixpoint.mli2
-rw-r--r--vernac/comInductive.ml10
-rw-r--r--vernac/comProgramFixpoint.ml8
-rw-r--r--vernac/indschemes.ml24
-rw-r--r--vernac/indschemes.mli7
-rw-r--r--vernac/lemmas.ml6
-rw-r--r--vernac/metasyntax.ml382
-rw-r--r--vernac/metasyntax.mli5
-rw-r--r--vernac/obligations.ml6
-rw-r--r--vernac/obligations.mli4
-rw-r--r--vernac/proof_using.ml2
-rw-r--r--vernac/record.ml17
-rw-r--r--vernac/record.mli11
-rw-r--r--vernac/vernacentries.ml71
-rw-r--r--vernac/vernacprop.ml12
154 files changed, 3272 insertions, 2016 deletions
diff --git a/.circleci/config.yml b/.circleci/config.yml
index 9b0cc2119..441d89d42 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -191,7 +191,7 @@ jobs:
environment:
<<: *envvars
EXTRA_PACKAGES: *coqide-packages
- EXTRA_OPAM: "ocamlgraph"
+ EXTRA_OPAM: "ocamlgraph ppx_tools_versioned ppx_deriving ocaml-migrate-parsetree"
opam-boot-32bit:
<<: *opam-boot-template
@@ -286,6 +286,9 @@ jobs:
<<: *ci-template-vars
EXTRA_PACKAGES: "time python autoconf automake"
+ elpi:
+ <<: *ci-template
+
equations:
<<: *ci-template
@@ -369,6 +372,7 @@ workflows:
- compcert: *req-main
- coq-dpdgraph: *req-main
- coquelicot: *req-main
+ - elpi: *req-main
- equations: *req-main
- geocoq: *req-main
- fiat-crypto: *req-main
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 6b52870ce..5dd376079 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -285,6 +285,12 @@ ci-coquelicot:
<<: *ci-template-vars
EXTRA_PACKAGES: "$TIMING_PACKAGES autoconf"
+ci-elpi:
+ <<: *ci-template
+ variables:
+ <<: *ci-template-vars
+ EXTRA_OPAM: "ppx_tools_versioned ppx_deriving ocaml-migrate-parsetree"
+
ci-equations:
<<: *ci-template
diff --git a/.travis.yml b/.travis.yml
index 19e7075f2..f4f01d2f0 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -76,6 +76,9 @@ matrix:
- TEST_TARGET="ci-coquelicot"
- if: NOT (type = pull_request)
env:
+ - TEST_TARGET="ci-elpi" EXTRA_OPAM="ppx_tools_versioned ppx_deriving ocaml-migrate-parsetree"
+ - if: NOT (type = pull_request)
+ env:
- TEST_TARGET="ci-equations"
- if: NOT (type = pull_request)
env:
diff --git a/CHANGES b/CHANGES
index 05337dc6c..2040c1b57 100644
--- a/CHANGES
+++ b/CHANGES
@@ -11,6 +11,15 @@ Notations
priority is given to latest notations defined in the scopes being
opened rather than to the latest notations defined independently of
whether they are in an opened scope or not.
+- 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
@@ -32,6 +41,7 @@ Tactics
such as "x := 5 : Z" (see BZ#148). 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)
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 1a769333c..74a138f14 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -32,6 +32,8 @@ If your pull request fixes a bug, please consider adding a regression test as we
Don't be alarmed if the pull request process takes some time. It can take a few days to get feedback, approval on the final changes, and then a merge. Coq doesn't release new versions very frequently so it can take a few months for your change to land in a released version. That said, you can start using the latest Coq `master` branch to take advantage of all the new features, improvements, and fixes.
+Whitespace discipline (do not indent using tabs, no trailing spaces, text files end with newlines) is checked by Travis (using `git diff --check`). We ship a [`dev/tools/pre-commit`](/dev/tools/pre-commit) git hook which fixes these errors at commit time. `configure` automatically sets you up to use it, unless you already have a hook at `.git/hooks/pre-commit`.
+
Here are a few tags Coq developers may add to your PR and what they mean. In general feedback and requests for you as the pull request author will be in the comments and tags are only used to organize pull requests.
- [needs: rebase](https://github.com/coq/coq/pulls?utf8=%E2%9C%93&q=is%3Aopen%20is%3Apr%20label%3A%22needs%3A%20rebase%22%20) indicates the PR should be rebased on top of the latest `master` branch. See the [GitHub documentation](https://help.github.com/articles/about-git-rebase/) for a brief introduction to using `git rebase`.
diff --git a/Makefile.ci b/Makefile.ci
index 80fbd7bbe..4e92264d6 100644
--- a/Makefile.ci
+++ b/Makefile.ci
@@ -5,6 +5,7 @@ CI_TARGETS=ci-bignums \
ci-coquelicot \
ci-corn \
ci-cpdt \
+ ci-elpi \
ci-equations \
ci-fiat-crypto \
ci-fiat-parsers \
diff --git a/checker/subtyping.ml b/checker/subtyping.ml
index 98a9c8250..77201c25b 100644
--- a/checker/subtyping.ml
+++ b/checker/subtyping.ml
@@ -108,6 +108,14 @@ let check_inductive env mp1 l info1 mib2 spec2 subst1 subst2=
let env = check_polymorphic_instance error env auctx auctx' in
env, Univ.make_abstract_instance auctx'
| Cumulative_ind cumi, Cumulative_ind cumi' ->
+ (** Currently there is no way to control variance of inductive types, but
+ just in case we require that they are in a subtyping relation. *)
+ let () =
+ let v = Univ.ACumulativityInfo.variance cumi in
+ let v' = Univ.ACumulativityInfo.variance cumi' in
+ if not (Array.for_all2 Univ.Variance.check_subtype v' v) then
+ CErrors.anomaly Pp.(str "Variance mismatch for " ++ MutInd.print kn)
+ in
let auctx = Univ.ACumulativityInfo.univ_context cumi in
let auctx' = Univ.ACumulativityInfo.univ_context cumi' in
let env = check_polymorphic_instance error env auctx auctx' in
diff --git a/checker/univ.ml b/checker/univ.ml
index 46b3ce680..ebc37bc10 100644
--- a/checker/univ.ml
+++ b/checker/univ.ml
@@ -1011,6 +1011,13 @@ struct
A'] as opposed to [A' <= A]. *)
type t = Irrelevant | Covariant | Invariant
+ let check_subtype x y = match x, y with
+ | (Irrelevant | Covariant | Invariant), Irrelevant -> true
+ | Irrelevant, Covariant -> false
+ | (Covariant | Invariant), Covariant -> true
+ | (Irrelevant | Covariant), Invariant -> false
+ | Invariant, Invariant -> true
+
let leq_constraint csts variance u u' =
match variance with
| Irrelevant -> csts
diff --git a/checker/univ.mli b/checker/univ.mli
index 8c0685e0b..32e48f593 100644
--- a/checker/univ.mli
+++ b/checker/univ.mli
@@ -225,7 +225,7 @@ sig
case because [forall x : A, B <= forall x : A', B'] requires [A =
A'] as opposed to [A' <= A]. *)
type t = Irrelevant | Covariant | Invariant
-
+ val check_subtype : t -> t -> bool
val leq_constraints : t array -> Instance.t constraint_function
val eq_constraints : t array -> Instance.t constraint_function
end
diff --git a/clib/cList.ml b/clib/cList.ml
index 0ef7c3d8b..627a3e3e0 100644
--- a/clib/cList.ml
+++ b/clib/cList.ml
@@ -62,6 +62,7 @@ sig
val fold_right_and_left :
('a -> 'b -> 'b list -> 'a) -> 'b list -> 'a -> 'a
val fold_left3 : ('a -> 'b -> 'c -> 'd -> 'a) -> 'a -> 'b list -> 'c list -> 'd list -> 'a
+ val fold_left2_set : exn -> ('a -> 'b -> 'c -> 'b list -> 'c list -> 'a) -> 'a -> 'b list -> 'c list -> 'a
val for_all_i : (int -> 'a -> bool) -> int -> 'a list -> bool
val except : 'a eq -> 'a -> 'a list -> 'a list
val remove : 'a eq -> 'a -> 'a list -> 'a list
@@ -472,6 +473,19 @@ let fold_right_and_left f l 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
+
let iteri f l = fold_left_i (fun i _ x -> f i x) 0 () l
let for_all_i p =
diff --git a/clib/cList.mli b/clib/cList.mli
index f87db04cf..b3ee28548 100644
--- a/clib/cList.mli
+++ b/clib/cList.mli
@@ -121,6 +121,14 @@ sig
val fold_right_and_left :
('a -> 'b -> 'b list -> 'a) -> 'b list -> 'a -> 'a
val fold_left3 : ('a -> 'b -> 'c -> 'd -> 'a) -> 'a -> 'b list -> 'c list -> 'd 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_left2_set : exn -> ('a -> 'b -> 'c -> 'b list -> 'c list -> 'a) -> 'a -> 'b list -> 'c list -> 'a
+
val for_all_i : (int -> 'a -> bool) -> int -> 'a list -> bool
val except : 'a eq -> 'a -> 'a list -> 'a list
val remove : 'a eq -> 'a -> 'a list -> 'a list
diff --git a/configure.ml b/configure.ml
index 9992e03b8..69db9407a 100644
--- a/configure.ml
+++ b/configure.ml
@@ -451,6 +451,22 @@ let vcs =
else if dir_exists "{arch}" then "gnuarch"
else "none"
+(** * Git Precommit Hook *)
+let _ =
+ let f = ".git/hooks/pre-commit" in
+ if vcs = "git" && dir_exists ".git/hooks" && not (Sys.file_exists f) then begin
+ printf "Creating pre-commit hook in %s\n" f;
+ let o = open_out f in
+ let pr s = fprintf o s in
+ pr "#!/bin/sh\n";
+ pr "\n";
+ pr "if [ -x dev/tools/pre-commit ]; then\n";
+ pr " exec dev/tools/pre-commit\n";
+ pr "fi\n";
+ close_out o;
+ Unix.chmod f 0o775
+ end
+
(** * Browser command *)
let browser =
diff --git a/dev/ci/ci-basic-overlay.sh b/dev/ci/ci-basic-overlay.sh
index 784da6f97..48e01e9e9 100644
--- a/dev/ci/ci-basic-overlay.sh
+++ b/dev/ci/ci-basic-overlay.sh
@@ -144,3 +144,9 @@
########################################################################
: "${Equations_CI_BRANCH:=8.8+alpha}"
: "${Equations_CI_GITURL:=https://github.com/mattam82/Coq-Equations.git}"
+
+########################################################################
+# Elpi
+########################################################################
+: "${Elpi_CI_BRANCH:=coq-master}"
+: "${Elpi_CI_GITURL:=https://github.com/LPCIC/coq-elpi.git}"
diff --git a/dev/ci/ci-elpi.sh b/dev/ci/ci-elpi.sh
new file mode 100755
index 000000000..c44e0a655
--- /dev/null
+++ b/dev/ci/ci-elpi.sh
@@ -0,0 +1,10 @@
+#!/usr/bin/env bash
+
+ci_dir="$(dirname "$0")"
+source ${ci_dir}/ci-common.sh
+
+Elpi_CI_DIR=${CI_BUILD_DIR}/elpi
+
+git_checkout ${Elpi_CI_BRANCH} ${Elpi_CI_GITURL} ${Elpi_CI_DIR}
+
+( cd ${Elpi_CI_DIR} && make && make install )
diff --git a/dev/ci/user-overlays/06745-ejgallego-located+vernac.sh b/dev/ci/user-overlays/06745-ejgallego-located+vernac.sh
new file mode 100644
index 000000000..d1d61fec2
--- /dev/null
+++ b/dev/ci/user-overlays/06745-ejgallego-located+vernac.sh
@@ -0,0 +1,13 @@
+if [ "$CI_PULL_REQUEST" = "6745" ] || [ "$CI_BRANCH" = "located+vernac" ]; then
+ ltac2_CI_BRANCH=located+vernac
+ ltac2_CI_GITURL=https://github.com/ejgallego/ltac2
+
+ Equations_CI_BRANCH=located+vernac
+ Equations_CI_GITURL=https://github.com/ejgallego/Coq-Equations
+
+ fiat_parsers_CI_BRANCH=located+vernac
+ fiat_parsers_CI_GITURL=https://github.com/ejgallego/fiat
+
+ Elpi_CI_BRANCH=located+vernac
+ Elpi_CI_GITURL=https://github.com/ejgallego/coq-elpi.git
+fi
diff --git a/dev/doc/changes.md b/dev/doc/changes.md
index 16a31790a..ab78b0956 100644
--- a/dev/doc/changes.md
+++ b/dev/doc/changes.md
@@ -49,6 +49,14 @@ We changed the type of the following functions:
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.
diff --git a/dev/tools/check-eof-newline.sh b/dev/tools/check-eof-newline.sh
index 9e4c8661d..e244d9ab8 100755
--- a/dev/tools/check-eof-newline.sh
+++ b/dev/tools/check-eof-newline.sh
@@ -1,13 +1,40 @@
#!/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
+
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
- echo "No newline at end of file $f!"
- CODE=1
+ if [ -n "$FIX" ];
+ then
+ if [ -w "$f" ];
+ then
+ echo >> "$f"
+ echo "Newline appended to file $f!"
+ else
+ echo "File $f is missing a newline and not writable!"
+ CODE=1
+ fi
+ else
+ echo "No newline at end of file $f!"
+ CODE=1
+ fi
fi
done
diff --git a/dev/tools/pre-commit b/dev/tools/pre-commit
new file mode 100755
index 000000000..c9cdee84a
--- /dev/null
+++ b/dev/tools/pre-commit
@@ -0,0 +1,73 @@
+#!/bin/sh
+
+# configure automatically sets up a wrapper at .git/hooks/pre-commit
+# which calls this script (if it exists).
+
+set -e
+
+if ! git diff --cached --name-only -z | xargs -0 dev/tools/check-eof-newline.sh ||
+ ! git diff-index --check --cached HEAD >/dev/null 2>&1 ;
+then
+ 1>&2 echo "Auto fixing whitespace issues..."
+
+ # We fix whitespace in the index and in the working tree
+ # separately to preserve non-added changes.
+ index=$(mktemp "git-fix-ws-index.XXXXX")
+ fixed_index=$(mktemp "git-fix-ws-index-fixed.XXXXX")
+ tree=$(mktemp "git-fix-ws-tree.XXXXX")
+ 1>&2 echo "Patches are saved in '$index', '$fixed_index' and '$tree'."
+ 1>&2 echo "If an error destroys your changes you can recover using them."
+ 1>&2 echo "(The files are cleaned up on success.)"
+ 1>&2 echo #newline
+
+ git diff-index -p --cached HEAD > "$index"
+ git diff-index -p HEAD > "$tree"
+
+ # reset work tree and index
+ # NB: untracked files which were not added are untouched
+ git apply --cached -R "$index"
+ git apply -R "$tree"
+
+ # Fix index
+ # For end of file newlines we must go through the worktree
+ 1>&2 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
+ 1>&2 echo #newline
+
+ # reset work tree
+ git diff-index -p --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 -R "$fixed_index"
+ fi
+
+ # Fix worktree
+ 1>&2 echo "Fixing unstaged changes..."
+ git apply --whitespace=fix "$tree"
+ git diff --name-only -z | xargs -0 dev/tools/check-eof-newline.sh --fix
+ 1>&2 echo #newline
+
+ if ! [ -s "$fixed_index" ]
+ then
+ 1>&2 echo "No changes after fixing whitespace issues!"
+ exit 1
+ fi
+
+ # Check that we did fix whitespace
+ if ! git diff-index --check --cached HEAD;
+ then
+ 1>&2 echo "Auto-fixing whitespace failed: errors remain."
+ 1>&2 echo "This may fix itself if you try again."
+ 1>&2 echo "(Consider whether the number of errors decreases after each run.)"
+ exit 1
+ fi
+ 1>&2 echo "Whitespace issues fixed!"
+
+ # clean up temporary files
+ rm "$index" "$tree" "$fixed_index"
+fi
diff --git a/doc/common/macros.tex b/doc/common/macros.tex
index 81def1674..6a28c5b3d 100644
--- a/doc/common/macros.tex
+++ b/doc/common/macros.tex
@@ -182,6 +182,7 @@
\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}}
diff --git a/doc/refman/RefMan-lib.tex b/doc/refman/RefMan-lib.tex
index c8e844302..89f5be843 100644
--- a/doc/refman/RefMan-lib.tex
+++ b/doc/refman/RefMan-lib.tex
@@ -55,6 +55,7 @@ Figure~\ref{init-notations}.
\hline
Notation & Precedence & Associativity \\
\hline
+\verb!_ -> _! & 99 & right \\
\verb!_ <-> _! & 95 & no \\
\verb!_ \/ _! & 85 & right \\
\verb!_ /\ _! & 80 & right \\
diff --git a/doc/refman/RefMan-syn.tex b/doc/refman/RefMan-syn.tex
index eecb5ac7c..a4ed2134e 100644
--- a/doc/refman/RefMan-syn.tex
+++ b/doc/refman/RefMan-syn.tex
@@ -3,25 +3,32 @@
In this chapter, we introduce advanced commands to modify the way
{\Coq} parses and prints objects, i.e. the translations between the
-concrete and internal representations of terms and commands. The main
-commands are {\tt Notation} and {\tt Infix} which are described in
-section \ref{Notation}. It also happens that the same symbolic
-notation is expected in different contexts. To achieve this form of
-overloading, {\Coq} offers a notion of interpretation scope. This is
-described in Section~\ref{scopes}.
-
-\Rem The commands {\tt Grammar}, {\tt Syntax} and {\tt Distfix} which
-were present for a while in {\Coq} are no longer available from {\Coq}
-version 8.0. The underlying AST structure is also no longer available.
-The functionalities of the command {\tt Syntactic Definition} are
-still available; see Section~\ref{Abbreviations}.
+concrete and internal representations of terms and commands.
+
+The main commands to provide custom symbolic notations for terms are
+{\tt Notation} and {\tt Infix}. They are described in Section
+\ref{Notation}. There is also a variant of {\tt Notation} which does
+not modify the parser. This provides with a form of abbreviation and
+it is described in Section~\ref{Abbreviations}. It is sometimes
+expected that the same symbolic notation has different meanings in
+different contexts. To achieve this form of overloading, {\Coq} offers
+a notion of interpretation scope. This is described in
+Section~\ref{scopes}.
+
+The main command to provide custom notations for tactics is {\tt
+ Tactic Notation}. It is described in Section~\ref{Tactic-Notation}.
+
+% No need any more to remind this
+%% \Rem The commands {\tt Grammar}, {\tt Syntax} and {\tt Distfix} which
+%% were present for a while in {\Coq} are no longer available from {\Coq}
+%% version 8.0. The underlying AST structure is also no longer available.
\section[Notations]{Notations\label{Notation}
\comindex{Notation}}
\subsection{Basic notations}
-A {\em notation} is a symbolic abbreviation denoting some term
+A {\em notation} is a symbolic expression denoting some term
or term pattern.
A typical notation is the use of the infix symbol \verb=/\= to denote
@@ -37,7 +44,7 @@ string \verb="A /\ B"= (called a {\em notation}) tells how it is
symbolically written.
A notation is always surrounded by double quotes (except when the
-abbreviation is a single identifier; see \ref{Abbreviations}). The
+abbreviation has the form of an ordinary applicative expression; see \ref{Abbreviations}). The
notation is composed of {\em tokens} separated by spaces. Identifiers
in the string (such as \texttt{A} and \texttt{B}) are the {\em
parameters} of the notation. They must occur at least once each in the
@@ -61,7 +68,7 @@ syntactic expression (see \ref{ReservedNotation}), explicit precedences and
associativity rules have to be given.
\Rem The right-hand side of a notation is interpreted at the time the
-notation is given. In particular, implicit arguments (see
+notation is given. In particular, disambiguation of constants, implicit arguments (see
Section~\ref{Implicit Arguments}), coercions (see
Section~\ref{Coercions}), etc. are resolved at the time of the
declaration of the notation.
@@ -105,8 +112,8 @@ parentheses are mandatory (this is a ``no associativity'')\footnote{
which {\Coq} is built, namely {\camlpppp}, currently does not implement the
no-associativity and replaces it by a left associativity; hence it is
the same for {\Coq}: no-associativity is in fact left associativity}.
-We don't know of a special convention of the associativity of
-disjunction and conjunction, so let's apply for instance a right
+We do not know of a special convention of the associativity of
+disjunction and conjunction, so let us apply for instance a right
associativity (which is the choice of {\Coq}).
Precedence levels and associativity rules of notations have to be
@@ -142,7 +149,8 @@ Notation "x = y" := (@eq _ x y) (at level 70, no associativity).
\end{coq_example*}
One can define {\em closed} notations whose both sides are symbols. In
-this case, the default precedence level for inner subexpression is 200.
+this case, the default precedence level for inner subexpression is
+200, and the default level for the notation itself is 0.
\begin{coq_eval}
Set Printing Depth 50.
@@ -150,7 +158,7 @@ Set Printing Depth 50.
(**** an incompatibility with the reserved notation ********)
\end{coq_eval}
\begin{coq_example*}
-Notation "( x , y )" := (@pair _ _ x y) (at level 0).
+Notation "( x , y )" := (@pair _ _ x y).
\end{coq_example*}
One can also define notations for binders.
@@ -161,17 +169,17 @@ Set Printing Depth 50.
(**** an incompatibility with the reserved notation ********)
\end{coq_eval}
\begin{coq_example*}
-Notation "{ x : A | P }" := (sig A (fun x => P)) (at level 0).
+Notation "{ x : A | P }" := (sig A (fun x => P)).
\end{coq_example*}
In the last case though, there is a conflict with the notation for
-type casts. This last notation, as shown by the command {\tt Print Grammar
+type casts. The notation for type casts, as shown by the command {\tt Print Grammar
constr} is at level 100. To avoid \verb=x : A= being parsed as a type cast,
it is necessary to put {\tt x} at a level below 100, typically 99. Hence, a
-correct definition is
+correct definition is the following.
\begin{coq_example*}
-Notation "{ x : A | P }" := (sig A (fun x => P)) (at level 0, x at level 99).
+Notation "{ x : A | P }" := (sig A (fun x => P)) (x at level 99).
\end{coq_example*}
%This change has retrospectively an effect on the notation for notation
@@ -182,14 +190,17 @@ Notation "{ x : A | P }" := (sig A (fun x => P)) (at level 0, x at level 99).
%Notation "{ A } + { B }" := (sumbool A B) (at level 0, A at level 99).
%\end{coq_example*}
-See the next section for more about factorization.
+More generally, it is required that notations are explicitly
+factorized on the left. See the next section for more about
+factorization.
\subsection{Simple factorization rules}
-{\Coq} extensible parsing is performed by Camlp5 which is essentially a
-LL1 parser. Hence, some care has to be taken not to hide already
-existing rules by new rules. Some simple left factorization work has
-to be done. Here is an example.
+{\Coq} extensible parsing is performed by {\camlpppp} which is
+essentially a LL1 parser: it decides which notation to parse by
+looking tokens from left to right. Hence, some care has to be taken
+not to hide already existing rules by new rules. Some simple left
+factorization work has to be done. Here is an example.
\begin{coq_eval}
(********** The next rule for notation _ < _ < _ produces **********)
@@ -242,17 +253,19 @@ on the {\Coq} printer. For example:
Check (and True True).
\end{coq_example}
-However, printing, especially pretty-printing, requires
-more care than parsing. We may want specific indentations,
-line breaks, alignment if on several lines, etc.
+However, printing, especially pretty-printing, also requires some
+care. We may want specific indentations, line breaks, alignment if on
+several lines, etc. For pretty-printing, {\Coq} relies on {\ocaml}
+formatting library, which provides indentation and automatic line
+breaks depending on page width by means of {\em formatting boxes}.
-The default printing of notations is very rudimentary. For printing a
-notation, a {\em formatting box} is opened in such a way that if the
+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
+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
@@ -277,6 +290,13 @@ Notation "'If' c1 'then' c2 'else' c3" := (IF_then_else c1 c2 c3)
\end{coq_example}
\end{small}
+\begin{coq_example}
+Check
+ (IF_then_else (IF_then_else True False True)
+ (IF_then_else True False True)
+ (IF_then_else True False True)).
+\end{coq_example}
+
A {\em format} is an extension of the string denoting the notation with
the possible following elements delimited by single quotes:
@@ -313,22 +333,15 @@ Notations do not survive the end of sections. No typing of the denoted
expression is performed at definition time. Type-checking is done only
at the time of use of the notation.
-\begin{coq_example}
-Check
- (IF_then_else (IF_then_else True False True)
- (IF_then_else True False True)
- (IF_then_else True False True)).
-\end{coq_example}
-
\Rem
Sometimes, a notation is expected only for the parser.
%(e.g. because
%the underlying parser of {\Coq}, namely {\camlpppp}, is LL1 and some extra
%rules are needed to circumvent the absence of factorization).
-To do so, the option {\em only parsing} is allowed in the list of modifiers of
+To do so, the option {\tt only parsing} is allowed in the list of modifiers of
\texttt{Notation}.
-Conversely, the {\em only printing} can be used to declare
+Conversely, the {\tt only printing} can be used to declare
that a notation should only be used for printing and should not declare a
parsing rule. In particular, such notations do not modify the parser.
@@ -339,16 +352,16 @@ The \texttt{Infix} command is a shortening for declaring notations of
infix symbols. Its syntax is
\begin{quote}
-\noindent\texttt{Infix "{\symbolentry}" :=} {\qualid} {\tt (} \nelist{\em modifier}{,} {\tt )}.
+\noindent\texttt{Infix "{\symbolentry}" :=} {\term} {\tt (} \nelist{\em modifier}{,} {\tt )}.
\end{quote}
and it is equivalent to
\begin{quote}
-\noindent\texttt{Notation "x {\symbolentry} y" := ({\qualid} x y) (} \nelist{\em modifier}{,} {\tt )}.
+\noindent\texttt{Notation "x {\symbolentry} y" := ({\term} x y) (} \nelist{\em modifier}{,} {\tt )}.
\end{quote}
-where {\tt x} and {\tt y} are fresh names distinct from {\qualid}. Here is an example.
+where {\tt x} and {\tt y} are fresh names. Here is an example.
\begin{coq_example*}
Infix "/\" := and (at level 80, right associativity).
@@ -380,12 +393,14 @@ reserved. Hence their precedence and associativity cannot be changed.
\comindex{CoFixpoint {\ldots} where {\ldots}}
\comindex{Inductive {\ldots} where {\ldots}}}
-Thanks to reserved notations, the inductive, co-inductive, recursive
-and corecursive definitions can benefit of customized notations. To do
-this, insert a {\tt where} notation clause after the definition of the
-(co)inductive type or (co)recursive term (or after the definition of
-each of them in case of mutual definitions). The exact syntax is given
-on Figure~\ref{notation-syntax}. Here are examples:
+Thanks to reserved notations, the inductive, co-inductive, record,
+recursive and corecursive definitions can benefit of customized
+notations. To do this, insert a {\tt where} notation clause after the
+definition of the (co)inductive type or (co)recursive term (or after
+the definition of each of them in case of mutual definitions). The
+exact syntax is given on Figure~\ref{notation-syntax} for inductive,
+co-inductive, recursive and corecursive definitions and on
+Figure~\ref{record-syntax} for records. Here are examples:
\begin{coq_eval}
Set Printing Depth 50.
@@ -479,20 +494,28 @@ Locate "exists _ .. _ , _".
\\
\\
{\modifiers}
- & ::= & \nelist{\ident}{,} {\tt at level} {\naturalnumber} \\
- & $|$ & \nelist{\ident}{,} {\tt at next level} \\
- & $|$ & {\tt at level} {\naturalnumber} \\
- & $|$ & {\tt left associativity} \\
- & $|$ & {\tt right associativity} \\
- & $|$ & {\tt no associativity} \\
+ & ::= & {\tt at level} {\naturalnumber} \\
+ & $|$ & \nelist{\ident}{,} {\tt at level} {\naturalnumber} \zeroone{\binderinterp}\\
+ & $|$ & \nelist{\ident}{,} {\tt at next level} \zeroone{\binderinterp}\\
+ & $|$ & {\ident} {\binderinterp} \\
& $|$ & {\ident} {\tt ident} \\
- & $|$ & {\ident} {\tt binder} \\
- & $|$ & {\ident} {\tt closed binder} \\
& $|$ & {\ident} {\tt global} \\
& $|$ & {\ident} {\tt bigint} \\
+ & $|$ & {\ident} \zeroone{{\tt strict}} {\tt pattern} \zeroone{{\tt at level} {\naturalnumber}}\\
+ & $|$ & {\ident} {\tt binder} \\
+ & $|$ & {\ident} {\tt closed binder} \\
+ & $|$ & {\tt left associativity} \\
+ & $|$ & {\tt right associativity} \\
+ & $|$ & {\tt no associativity} \\
& $|$ & {\tt only parsing} \\
& $|$ & {\tt only printing} \\
- & $|$ & {\tt format} {\str}
+ & $|$ & {\tt format} {\str} \\
+\\
+\\
+{\binderinterp}
+ & ::= & {\tt as ident} \\
+ & $|$ & {\tt as pattern} \\
+ & $|$ & {\tt as strict pattern} \\
\end{tabular}
\end{centerframe}
\end{small}
@@ -500,9 +523,93 @@ Locate "exists _ .. _ , _".
\label{notation-syntax}
\end{figure}
-\subsection{Notations and simple binders}
+\subsection{Notations and binders}
+
+Notations can include binders. This section lists
+different ways to deal with binders. For further examples, see also
+Section~\ref{RecursiveNotationsWithBinders}.
-Notations can be defined for binders as in the example:
+\subsubsection{Binders bound in the notation and parsed as identifiers}
+
+Here is the basic example of a notation using a binder:
+
+\begin{coq_example*}
+Notation "'sigma' x : A , B" := (sigT (fun x : A => B))
+ (at level 200, x ident, A at level 200, right associativity).
+\end{coq_example*}
+
+The binding variables in the right-hand side that occur as a parameter
+of the notation (here {\tt 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 {\tt B} can
+refer to the variable name bound to {\tt x} as shown in the following
+application of the notation:
+
+\begin{coq_example}
+Check sigma z : nat, z = 0.
+\end{coq_example}
+
+Notice the modifier {\tt x ident} in the declaration of the
+notation. It tells to parse {\tt x} as a single identifier.
+
+\subsubsection{Binders bound in the notation and parsed as patterns}
+
+In the same way as patterns can be used as binders, as in {\tt fun
+ '(x,y) => x+y} or {\tt fun '(existT \_ x \_) => x}, notations can be
+defined so that any pattern (in the sense of the entry {\pattern} of
+Figure~\ref{term-syntax-aux}) can be used in place of the
+binder. Here is an example:
+
+\begin{coq_eval}
+Reset Initial.
+\end{coq_eval}
+
+\begin{coq_example*}
+Notation "'subset' ' p , P " := (sig (fun p => P))
+ (at level 200, p pattern, format "'subset' ' p , P").
+\end{coq_example*}
+
+\begin{coq_example}
+Check subset '(x,y), x+y=0.
+\end{coq_example}
+
+The modifier {\tt p pattern} in the declaration of the notation
+tells to parse $p$ as a pattern. Note that a single
+variable is both an identifier and a pattern, so, e.g., the following
+also works:
+
+% Note: we rely on the notation of the standard library which does not
+% print the expected output, so we hide the output.
+\begin{coq_example}
+Check subset 'x, x=0.
+\end{coq_example}
+
+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 modifier {\tt p strict pattern}. For parsing, however, a {\tt
+ strict pattern} will continue to include the case of a
+variable. Here is an example showing the difference:
+
+\begin{coq_example*}
+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 ident).
+\end{coq_example*}
+
+\begin{coq_example}
+Check subset_bis 'x, x=0.
+\end{coq_example}
+
+The default level for a {\tt pattern} is 0. One can use a different level by
+using {\tt pattern at level} $n$ where the scale is the same as the one for
+terms (Figure~\ref{init-notations}).
+
+\subsubsection{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:
\begin{coq_eval}
Set Printing Depth 50.
@@ -510,18 +617,53 @@ Set Printing Depth 50.
(**** an incompatibility with the reserved notation ********)
\end{coq_eval}
\begin{coq_example*}
-Notation "{ x : A | P }" := (sig (fun x : A => P)) (at level 0).
+Notation "{ x : A | P }" := (sig (fun x : A => P))
+ (at level 0, x at level 99 as ident).
+\end{coq_example*}
+
+This is so because the grammar also contains rules starting with
+{\tt \{} and followed by a term, such as the rule for the notation
+ {\tt \{ A \} + \{ B \}} for the constant {\tt
+ sumbool}~(see Section~\ref{sumbool}).
+
+Then, in the rule, {\tt x ident} is replaced by {\tt x at level 99 as
+ ident} meaning that {\tt x} is parsed as a term at level 99 (as done
+in the notation for {\tt sumbool}), but that this term has actually to
+be an identifier.
+
+The notation {\tt \{ x | P \}} is already defined in the standard
+library with the {\tt as ident} modifier. We cannot redefine it but
+one can define an alternative notation, say {\tt \{ p such that P }\},
+using instead {\tt as pattern}.
+
+% Note, this conflicts with the default rule in the standard library, so
+% we don't show the
+\begin{coq_example*}
+Notation "{ p 'such' 'that' P }" := (sig (fun p => P))
+ (at level 0, p at level 99 as pattern).
\end{coq_example*}
-The binding variables in the left-hand-side that occur as a parameter
-of the notation naturally bind all their occurrences appearing in
-their respective scope after instantiation of the parameters of the
-notation.
+Then, the following works:
+\begin{coq_example}
+Check {(x,y) such that x+y=0}.
+\end{coq_example}
+
+To enforce that the pattern should not be used for printing when it
+is just an identifier, one could have said {\tt p at level
+ 99 as strict pattern}.
+
+Note also that in the absence of a {\tt as ident}, {\tt as strict
+ pattern} or {\tt as pattern} modifiers, the default is to consider
+subexpressions occurring in binding position and parsed as terms to be
+{\tt as ident}.
-Contrastingly, the binding variables that are not a parameter of the
-notation do not capture the variables of same name that
-could appear in their scope after instantiation of the
-notation. E.g., for the notation
+\subsubsection{Binders not bound in the notation}
+\label{NotationsWithBinders}
+
+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
\begin{coq_example*}
Notation "'exists_different' n" := (exists p:nat, p<>n) (at level 200).
@@ -537,14 +679,6 @@ Set Printing Depth 50.
Fail Check (exists_different p).
\end{coq_example}
-\Rem Binding variables must not necessarily be parsed using the
-{\tt ident} entry. For factorization purposes, they can be said to be
-parsed at another level (e.g. {\tt x} in \verb="{ x : A | P }"= must be
-parsed at level 99 to be factorized with the notation
-\verb="{ A } + { B }"= for which {\tt A} can be any term).
-However, even if parsed as a term, this term must at the end be effectively
-a single identifier.
-
\subsection{Notations with recursive patterns}
\label{RecursiveNotations}
@@ -565,24 +699,22 @@ notation parses any number of time (but at least one time) a sequence
of expressions separated by the sequence of tokens $s$ (in the
example, $s$ is just ``{\tt ;}'').
-In the right-hand side, the term enclosed within {\tt ..} must be a
-pattern with two holes of the form $\phi([~]_E,[~]_I)$ where the first
-hole is occupied either by $x$ or by $y$ and the second hole is
-occupied by an arbitrary term $t$ called the {\it terminating}
-expression of the recursive notation. The subterm {\tt ..} $\phi(x,t)$
-{\tt ..} (or {\tt ..} $\phi(y,t)$ {\tt ..}) must itself occur at
-second position of the same pattern where the first hole is occupied
-by the other variable, $y$ or $x$. Otherwise said, the right-hand side
-must contain a subterm of the form either $\phi(x,${\tt ..}
-$\phi(y,t)$ {\tt ..}$)$ or $\phi(y,${\tt ..} $\phi(x,t)$ {\tt ..}$)$.
-The pattern $\phi$ is the {\em iterator} of the recursive notation
-and, of course, the name $x$ and $y$ can be chosen arbitrarily.
-
-The parsing phase produces a list of expressions which are used to
-fill in order the first hole of the iterating pattern which is
+The right-hand side must contain a subterm of the form either
+$\phi(x,${\tt ..} $\phi(y,t)$ {\tt ..}$)$ or $\phi(y,${\tt ..}
+$\phi(x,t)$ {\tt ..}$)$ where $\phi([~]_E,[~]_I)$, called the {\em
+ iterator} of the recursive notation is an arbitrary expression with
+distinguished placeholders and
+where $t$ is called the {\tt terminating expression} of the recursive
+notation. In the example, we choose the name s$x$ and $y$ but in
+practice they can of course be chosen arbitrarily. Note that the
+placeholder $[~]_I$ has to occur only once but the $[~]_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
-hole being the nesting point. In the innermost occurrence of the
-nested iterating pattern, the second hole is finally filled with the
+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 $\phi([~]_E,[~]_I)$ is {\tt cons
@@ -609,24 +741,26 @@ notations, they can also be declared within interpretation scopes (see
section \ref{scopes}).
\subsection{Notations with recursive patterns involving binders}
+\label{RecursiveNotationsWithBinders}
Recursive notations can also be used with binders. The basic example is:
\begin{coq_example*}
-Notation "'exists' x .. y , p" := (ex (fun x => .. (ex (fun y => p)) ..))
+Notation "'exists' x .. y , p" :=
+ (ex (fun x => .. (ex (fun y => p)) ..))
(at level 200, x binder, y binder, right associativity).
\end{coq_example*}
The principle is the same as in Section~\ref{RecursiveNotations}
-except that in the iterator $\phi([~]_E,[~]_I)$, the first hole is a
-placeholder occurring at the position of the binding variable of a {\tt
+except that in the iterator $\phi([~]_E,[~]_I)$, the placeholder $[~]_E$ can
+also occur in position of the binding variable of a {\tt
fun} or a {\tt forall}.
To specify that the part ``$x$ {\tt ..} $y$'' of the notation
parses a sequence of binders, $x$ and $y$ must be marked as {\tt
- binder} in the list of modifiers of the notation. Then, the list of
-binders produced at the parsing phase are used to fill in the first
-hole of the iterating pattern which is repeatedly nested as many times
+ binder} in the list of modifiers of the notation. The
+binders of the parsed sequence are used to fill the occurrences of the first
+placeholder of the iterating pattern which is repeatedly nested as many times
as the number of binders generated. If ever the generalization
operator {\tt `} (see Section~\ref{implicit-generalization}) is used
in the binding list, the added binders are taken into account too.
@@ -635,14 +769,14 @@ Binders parsing exist in two flavors. If $x$ and $y$ are marked as
{\tt binder}, then a sequence such as {\tt a b c : T} will be accepted
and interpreted as the sequence of binders {\tt (a:T) (b:T)
(c:T)}. For instance, in the notation above, the syntax {\tt exists
- a b : nat, a = b} is provided.
+ a b : nat, a = b} is valid.
The variables $x$ and $y$ can also be marked as {\tt closed binder} in
which case only well-bracketed binders of the form {\tt (a b c:T)} or
{\tt \{a b c:T\}} etc. are accepted.
With closed binders, the recursive sequence in the left-hand side can
-be of the general form $x$ $s$ {\tt ..} $s$ $y$ where $s$ is an
+be of the more general form $x$ $s$ {\tt ..} $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:
@@ -661,6 +795,40 @@ Notation "'FUNAPP' x .. y , f" :=
(at level 200, x binder, y binder, right associativity).
\end{coq_example*}
+If an occurrence of the $[~]_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:
+
+\begin{coq_example*}
+Notation "'exists_non_null' x .. y , P" :=
+ (ex (fun x => x <> 0 /\ .. (ex (fun y => y <> 0 /\ P)) ..))
+ (at level 200, x binder).
+\end{coq_example*}
+
+\subsection{Predefined entries}
+
+By default, sub-expressions are parsed as terms and the corresponding
+grammar entry is called {\tt 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 {\tt x}:
+
+\begin{coq_example*}
+Notation "'apply' f a1 .. an" := (.. (f a1) .. an)
+ (at level 10, f global, a1, an at level 9).
+\end{coq_example*}
+
+In addition to {\tt global}, one can restrict the syntax of a
+sub-expression by using the entry names {\tt ident} or {\tt pattern}
+already seen in Section~\ref{NotationsWithBinders}, even when the
+corresponding expression is not used as a binder in the right-hand
+side. E.g.:
+
+\begin{coq_example*}
+Notation "'apply_id' f a1 .. an" := (.. (f a1) .. an)
+ (at level 10, f ident, a1, an at level 9).
+\end{coq_example*}
+
\subsection{Summary}
\paragraph{Syntax of notations}
@@ -754,7 +922,7 @@ stack by using the command
{\tt Close Scope} {\scope}.
\end{quote}
Notice that this command does not only cancel the last {\tt Open Scope
-{\scope}} but all the invocation of it.
+{\scope}} but all the invocations of it.
\Rem {\tt Open Scope} and {\tt Close Scope} do not survive the end of
sections where they occur. When defined outside of a section, they are
@@ -1108,7 +1276,7 @@ Check reflexive iff.
\end{coq_example}
An abbreviation expects no precedence nor associativity, since it
-follows the usual syntax of application. Abbreviations are used as
+is parsed as usual application. Abbreviations are used as
much as possible by the {\Coq} printers unless the modifier
\verb=(only parsing)= is given.
@@ -1121,7 +1289,7 @@ abbreviation but at the time it is used. Especially, abbreviations can
be bound to terms with holes (i.e. with ``\_''). The general syntax
for abbreviations is
\begin{quote}
-\zeroone{{\tt Local}} \texttt{Notation} {\ident} \sequence{\ident} {\ident} \texttt{:=} {\term}
+\zeroone{{\tt Local}} \texttt{Notation} {\ident} \sequence{\ident}{} \texttt{:=} {\term}
\zeroone{{\tt (only parsing)}}~\verb=.=
\end{quote}
@@ -1147,13 +1315,15 @@ at the time of use of the abbreviation.
%\verb=(only parsing)= is given) while syntactic definitions were not.
\section{Tactic Notations
+\label{Tactic-Notation}
\comindex{Tactic Notation}}
Tactic notations allow to customize the syntax of the tactics of the
-tactic language\footnote{Tactic notations are just a simplification of
-the {\tt Grammar tactic simple\_tactic} command that existed in
-versions prior to version 8.0.}. Tactic notations obey the following
-syntax
+tactic language.
+%% \footnote{Tactic notations are just a simplification of
+%% the {\tt Grammar tactic simple\_tactic} command that existed in
+%% versions prior to version 8.0.}
+Tactic notations obey the following syntax:
\medskip
\noindent
@@ -1196,7 +1366,9 @@ level indicates the parsing precedence of the tactic notation. This
information is particularly relevant for notations of tacticals.
Levels 0 to 5 are available (default is 0).
To know the parsing precedences of the
-existing tacticals, use the command {\tt Print Grammar tactic.}
+existing tacticals, use the command
+\comindex{Print Grammar tactic}
+ {\tt Print Grammar tactic.}
Each type of tactic argument has a specific semantic regarding how it
is parsed and how it is interpreted. The semantic is described in the
diff --git a/engine/evd.ml b/engine/evd.ml
index 0e9472158..2142cee37 100644
--- a/engine/evd.ml
+++ b/engine/evd.ml
@@ -802,7 +802,7 @@ let make_evar_universe_context e l =
| None -> uctx
| Some us ->
List.fold_left
- (fun uctx (loc,id) ->
+ (fun uctx { CAst.loc; v = id } ->
fst (UState.new_univ_variable ?loc univ_rigid (Some id) uctx))
uctx us
diff --git a/engine/evd.mli b/engine/evd.mli
index b28ce2a62..84fa70ef2 100644
--- a/engine/evd.mli
+++ b/engine/evd.mli
@@ -506,7 +506,7 @@ val constrain_variables : Univ.LSet.t -> UState.t -> UState.t
val evar_universe_context_of_binders :
Universes.universe_binders -> UState.t
-val make_evar_universe_context : env -> (Id.t located) list option -> UState.t
+val make_evar_universe_context : env -> Misctypes.lident list option -> UState.t
val restrict_universe_context : evar_map -> Univ.LSet.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
diff --git a/engine/uState.ml b/engine/uState.ml
index 4b650c9c9..625495866 100644
--- a/engine/uState.ml
+++ b/engine/uState.ml
@@ -282,7 +282,7 @@ let pr_uctx_level uctx l =
Libnames.pr_reference (reference_of_level uctx l)
type universe_decl =
- (Names.Id.t Loc.located list, Univ.Constraint.t) Misctypes.gen_universe_decl
+ (Misctypes.lident list, Univ.Constraint.t) Misctypes.gen_universe_decl
let error_unbound_universes left uctx =
let open Univ in
@@ -305,7 +305,7 @@ let universe_context ~names ~extensible uctx =
let levels = ContextSet.levels uctx.uctx_local in
let newinst, left =
List.fold_right
- (fun (loc,id) (newinst, acc) ->
+ (fun { CAst.loc; v = id } (newinst, acc) ->
let l =
try UNameMap.find id (fst uctx.uctx_names)
with Not_found -> assert false
@@ -325,7 +325,7 @@ let check_universe_context_set ~names ~extensible uctx =
if extensible then ()
else
let open Univ in
- let left = List.fold_left (fun left (loc,id) ->
+ let left = List.fold_left (fun left { CAst.loc; v = id } ->
let l =
try UNameMap.find id (fst uctx.uctx_names)
with Not_found -> assert false
diff --git a/engine/uState.mli b/engine/uState.mli
index 6657d6047..5c85b2b84 100644
--- a/engine/uState.mli
+++ b/engine/uState.mli
@@ -132,7 +132,7 @@ val refresh_undefined_univ_variables : t -> t * Univ.universe_level_subst
val normalize : t -> t
type universe_decl =
- (Names.Id.t Loc.located list, Univ.Constraint.t) Misctypes.gen_universe_decl
+ (Misctypes.lident list, Univ.Constraint.t) Misctypes.gen_universe_decl
(** [check_univ_decl ctx decl]
diff --git a/engine/universes.ml b/engine/universes.ml
index 3a00f0fd1..f3660a559 100644
--- a/engine/universes.ml
+++ b/engine/universes.ml
@@ -92,14 +92,14 @@ let register_universe_binders ref ubinders =
if not (Id.Map.is_empty ubinders)
then Lib.add_anonymous_leaf (ubinder_obj (ref,ubinders))
-type univ_name_list = Name.t Loc.located list
+type univ_name_list = Misctypes.lname list
let universe_binders_with_opt_names ref levels = function
| None -> universe_binders_of_global ref
| Some udecl ->
if Int.equal(List.length levels) (List.length udecl)
then
- List.fold_left2 (fun acc (_,na) lvl -> match na with
+ List.fold_left2 (fun acc { CAst.v = na} lvl -> match na with
| Anonymous -> acc
| Name na -> Names.Id.Map.add na lvl acc)
empty_binders udecl levels
diff --git a/engine/universes.mli b/engine/universes.mli
index cb6e2ba1b..04586a6f8 100644
--- a/engine/universes.mli
+++ b/engine/universes.mli
@@ -35,7 +35,7 @@ val empty_binders : universe_binders
val register_universe_binders : Globnames.global_reference -> universe_binders -> unit
val universe_binders_of_global : Globnames.global_reference -> universe_binders
-type univ_name_list = Name.t Loc.located list
+type univ_name_list = Misctypes.lname list
(** [universe_binders_with_opt_names ref u l]
diff --git a/interp/constrexpr_ops.ml b/interp/constrexpr_ops.ml
index da04d8786..d05e7d909 100644
--- a/interp/constrexpr_ops.ml
+++ b/interp/constrexpr_ops.ml
@@ -61,13 +61,13 @@ let explicitation_eq ex1 ex2 = match ex1, ex2 with
Id.equal id1 id2
| _ -> false
-let eq_located f (_, x) (_, y) = f x y
+let eq_ast f { CAst.v = x } { CAst.v = y } = f x y
let rec cases_pattern_expr_eq p1 p2 =
if CAst.(p1.v == p2.v) then true
else match CAst.(p1.v, p2.v) with
| CPatAlias(a1,i1), CPatAlias(a2,i2) ->
- Id.equal i1 i2 && cases_pattern_expr_eq a1 a2
+ eq_ast Name.equal i1 i2 && cases_pattern_expr_eq a1 a2
| CPatCstr(c1,a1,b1), CPatCstr(c2,a2,b2) ->
eq_reference c1 c2 &&
Option.equal (List.equal cases_pattern_expr_eq) a1 a2 &&
@@ -106,19 +106,19 @@ let rec constr_expr_eq e1 e2 =
else match CAst.(e1.v, e2.v) with
| CRef (r1,u1), CRef (r2,u2) -> eq_reference r1 r2 && eq_universes u1 u2
| CFix(id1,fl1), CFix(id2,fl2) ->
- eq_located Id.equal id1 id2 &&
+ eq_ast Id.equal id1 id2 &&
List.equal fix_expr_eq fl1 fl2
| CCoFix(id1,fl1), CCoFix(id2,fl2) ->
- eq_located Id.equal id1 id2 &&
+ eq_ast Id.equal id1 id2 &&
List.equal cofix_expr_eq fl1 fl2
| CProdN(bl1,a1), CProdN(bl2,a2) ->
- List.equal binder_expr_eq bl1 bl2 &&
+ List.equal local_binder_eq bl1 bl2 &&
constr_expr_eq a1 a2
| CLambdaN(bl1,a1), CLambdaN(bl2,a2) ->
- List.equal binder_expr_eq bl1 bl2 &&
+ List.equal local_binder_eq bl1 bl2 &&
constr_expr_eq a1 a2
- | CLetIn((_,na1),a1,t1,b1), CLetIn((_,na2),a2,t2,b2) ->
- Name.equal na1 na2 &&
+ | CLetIn(na1,a1,t1,b1), CLetIn(na2,a2,t2,b2) ->
+ eq_ast Name.equal na1 na2 &&
constr_expr_eq a1 a2 &&
Option.equal constr_expr_eq t1 t2 &&
constr_expr_eq b1 b2
@@ -141,14 +141,14 @@ let rec constr_expr_eq e1 e2 =
List.equal case_expr_eq a1 a2 &&
List.equal branch_expr_eq brl1 brl2
| CLetTuple (n1, (m1, e1), t1, b1), CLetTuple (n2, (m2, e2), t2, b2) ->
- List.equal (eq_located Name.equal) n1 n2 &&
- Option.equal (eq_located Name.equal) m1 m2 &&
+ List.equal (eq_ast Name.equal) n1 n2 &&
+ Option.equal (eq_ast Name.equal) m1 m2 &&
Option.equal constr_expr_eq e1 e2 &&
constr_expr_eq t1 t2 &&
constr_expr_eq b1 b2
| CIf (e1, (n1, r1), t1, f1), CIf (e2, (n2, r2), t2, f2) ->
constr_expr_eq e1 e2 &&
- Option.equal (eq_located Name.equal) n1 n2 &&
+ Option.equal (eq_ast Name.equal) n1 n2 &&
Option.equal constr_expr_eq r1 r2 &&
constr_expr_eq t1 t2 &&
constr_expr_eq f1 f2
@@ -181,32 +181,28 @@ let rec constr_expr_eq e1 e2 =
| CGeneralization _ | CDelimiters _ | CProj _), _ -> false
and args_eq (a1,e1) (a2,e2) =
- Option.equal (eq_located explicitation_eq) e1 e2 &&
+ Option.equal (eq_ast explicitation_eq) e1 e2 &&
constr_expr_eq a1 a2
and case_expr_eq (e1, n1, p1) (e2, n2, p2) =
constr_expr_eq e1 e2 &&
- Option.equal (eq_located Name.equal) n1 n2 &&
+ Option.equal (eq_ast Name.equal) n1 n2 &&
Option.equal cases_pattern_expr_eq p1 p2
-and branch_expr_eq (_, (p1, e1)) (_, (p2, e2)) =
+and branch_expr_eq {CAst.v=(p1, e1)} {CAst.v=(p2, e2)} =
List.equal (List.equal cases_pattern_expr_eq) p1 p2 &&
constr_expr_eq e1 e2
-and binder_expr_eq ((n1, _, e1) : binder_expr) (n2, _, e2) =
- (** Don't care about the [binder_kind] *)
- List.equal (eq_located Name.equal) n1 n2 && constr_expr_eq e1 e2
-
and fix_expr_eq (id1,(j1, r1),bl1,a1,b1) (id2,(j2, r2),bl2,a2,b2) =
- (eq_located Id.equal id1 id2) &&
- Option.equal (eq_located Id.equal) j1 j2 &&
+ (eq_ast Id.equal id1 id2) &&
+ Option.equal (eq_ast Id.equal) j1 j2 &&
recursion_order_expr_eq r1 r2 &&
List.equal local_binder_eq bl1 bl2 &&
constr_expr_eq a1 a2 &&
constr_expr_eq b1 b2
and cofix_expr_eq (id1,bl1,a1,b1) (id2,bl2,a2,b2) =
- (eq_located Id.equal id1 id2) &&
+ (eq_ast Id.equal id1 id2) &&
List.equal local_binder_eq bl1 bl2 &&
constr_expr_eq a1 a2 &&
constr_expr_eq b1 b2
@@ -220,15 +216,16 @@ and recursion_order_expr_eq r1 r2 = match r1, r2 with
and local_binder_eq l1 l2 = match l1, l2 with
| CLocalDef (n1, e1, t1), CLocalDef (n2, e2, t2) ->
- eq_located Name.equal n1 n2 && constr_expr_eq e1 e2 && Option.equal constr_expr_eq t1 t2
+ eq_ast Name.equal n1 n2 && constr_expr_eq e1 e2 && Option.equal constr_expr_eq t1 t2
| CLocalAssum (n1, _, e1), CLocalAssum (n2, _, e2) ->
(** Don't care about the [binder_kind] *)
- List.equal (eq_located Name.equal) n1 n2 && constr_expr_eq e1 e2
+ List.equal (eq_ast Name.equal) n1 n2 && constr_expr_eq e1 e2
| _ -> false
-and constr_notation_substitution_eq (e1, el1, bl1) (e2, el2, bl2) =
+and constr_notation_substitution_eq (e1, el1, b1, bl1) (e2, el2, b2, bl2) =
List.equal constr_expr_eq e1 e2 &&
List.equal (List.equal constr_expr_eq) el1 el2 &&
+ List.equal cases_pattern_expr_eq b1 b2 &&
List.equal (List.equal local_binder_eq) bl1 bl2
and instance_eq (x1,c1) (x2,c2) =
@@ -247,12 +244,12 @@ and cast_expr_eq c1 c2 = match c1, c2 with
let constr_loc c = CAst.(c.loc)
let cases_pattern_expr_loc cp = CAst.(cp.loc)
-let local_binder_loc = function
- | CLocalAssum ((loc,_)::_,_,t)
- | CLocalDef ((loc,_),t,None) -> Loc.merge_opt loc (constr_loc t)
- | CLocalDef ((loc,_),b,Some t) -> Loc.merge_opt loc (Loc.merge_opt (constr_loc b) (constr_loc t))
+let local_binder_loc = let open CAst in function
+ | CLocalAssum ({ loc } ::_,_,t)
+ | CLocalDef ( { loc },t,None) -> Loc.merge_opt loc (constr_loc t)
+ | CLocalDef ( { loc },b,Some t) -> Loc.merge_opt loc (Loc.merge_opt (constr_loc b) (constr_loc t))
| CLocalAssum ([],_,_) -> assert false
- | CLocalPattern (loc,_) -> loc
+ | CLocalPattern { loc } -> loc
let local_binders_loc bll = match bll with
| [] -> None
@@ -260,9 +257,6 @@ let local_binders_loc bll = match bll with
(** Folds and maps *)
-(* Legacy functions *)
-let down_located f (_l, x) = f x
-
let is_constructor id =
try Globnames.isConstructRef
(Smartlocate.global_of_extended_global
@@ -272,7 +266,7 @@ let is_constructor id =
let rec cases_pattern_fold_names f a pt = match CAst.(pt.v) with
| CPatRecord l ->
List.fold_left (fun acc (r, cp) -> cases_pattern_fold_names f acc cp) a l
- | CPatAlias (pat,id) -> f id a
+ | CPatAlias (pat,{CAst.v=na}) -> Name.fold_right f na (cases_pattern_fold_names f a pat)
| CPatOr (patl) ->
List.fold_left (cases_pattern_fold_names f) a patl
| CPatCstr (_,patl1,patl2) ->
@@ -304,25 +298,17 @@ let ids_of_cases_tomatch tms =
(fun (_, ona, indnal) l ->
Option.fold_right (fun t ids -> cases_pattern_fold_names Id.Set.add ids t)
indnal
- (Option.fold_right (down_located (Name.fold_right Id.Set.add)) ona l))
+ (Option.fold_right (CAst.with_val (Name.fold_right Id.Set.add)) ona l))
tms Id.Set.empty
-let rec fold_constr_expr_binders g f n acc b = function
- | (nal,bk,t)::l ->
- let nal = snd (List.split nal) in
- let n' = List.fold_right (Name.fold_right g) nal n in
- f n (fold_constr_expr_binders g f n' acc b l) t
- | [] ->
- f n acc b
-
-let rec fold_local_binders g f n acc b = function
+let rec fold_local_binders g f n acc b = let open CAst in function
| CLocalAssum (nal,bk,t)::l ->
- let nal = snd (List.split nal) in
+ let nal = List.(map (fun {v} -> v) nal) in
let n' = List.fold_right (Name.fold_right g) nal n in
f n (fold_local_binders g f n' acc b l) t
- | CLocalDef ((_,na),c,t)::l ->
+ | CLocalDef ( { v = na },c,t)::l ->
Option.fold_left (f n) (f n (fold_local_binders g f (Name.fold_right g na n) acc b l) c) t
- | CLocalPattern (_,(pat,t))::l ->
+ | CLocalPattern { v = pat,t }::l ->
let acc = fold_local_binders g f (cases_pattern_fold_names g n pat) acc b l in
Option.fold_left (f n) acc t
| [] ->
@@ -331,12 +317,12 @@ let rec fold_local_binders g f n acc b = function
let fold_constr_expr_with_binders g f n acc = CAst.with_val (function
| CAppExpl ((_,_,_),l) -> List.fold_left (f n) acc l
| CApp ((_,t),l) -> List.fold_left (f n) (f n acc t) (List.map fst l)
- | CProdN (l,b) | CLambdaN (l,b) -> fold_constr_expr_binders g f n acc b l
+ | CProdN (l,b) | CLambdaN (l,b) -> fold_local_binders g f n acc b l
| CLetIn (na,a,t,b) ->
- f (Name.fold_right g (snd na) n) (Option.fold_left (f n) (f n acc a) t) b
+ f (Name.fold_right g (na.CAst.v) n) (Option.fold_left (f n) (f n acc a) t) b
| CCast (a,(CastConv b|CastVM b|CastNative b)) -> f n (f n acc a) b
| CCast (a,CastCoerce) -> f n acc a
- | CNotation (_,(l,ll,bll)) ->
+ | CNotation (_,(l,ll,bl,bll)) ->
(* The following is an approximation: we don't know exactly if
an ident is binding nor to which subterms bindings apply *)
let acc = List.fold_left (f n) acc (l@List.flatten ll) in
@@ -350,18 +336,18 @@ let fold_constr_expr_with_binders g f n acc = CAst.with_val (function
let ids = ids_of_cases_tomatch al in
let acc = Option.fold_left (f (Id.Set.fold g ids n)) acc rtnpo in
let acc = List.fold_left (f n) acc (List.map (fun (fst,_,_) -> fst) al) in
- List.fold_right (fun (loc,(patl,rhs)) acc ->
+ List.fold_right (fun {CAst.v=(patl,rhs)} acc ->
let ids = ids_of_pattern_list patl in
f (Id.Set.fold g ids n) acc rhs) bl acc
| CLetTuple (nal,(ona,po),b,c) ->
- let n' = List.fold_right (down_located (Name.fold_right g)) nal n in
- f (Option.fold_right (down_located (Name.fold_right g)) ona n') (f n acc b) c
+ let n' = List.fold_right (CAst.with_val (Name.fold_right g)) nal n in
+ f (Option.fold_right (CAst.with_val (Name.fold_right g)) ona n') (f n acc b) c
| CIf (c,(ona,po),b1,b2) ->
let acc = f n (f n (f n acc b1) b2) c in
Option.fold_left
- (f (Option.fold_right (down_located (Name.fold_right g)) ona n)) acc po
+ (f (Option.fold_right (CAst.with_val (Name.fold_right g)) ona n)) acc po
| CFix (_,l) ->
- let n' = List.fold_right (fun ((_,id),_,_,_,_) -> g id) l n in
+ let n' = List.fold_right (fun ( { CAst.v = id },_,_,_,_) -> g id) l n in
List.fold_right (fun (_,(_,o),lb,t,c) acc ->
fold_local_binders g f n'
(fold_local_binders g f n acc t lb) c lb) l acc
@@ -380,24 +366,19 @@ let free_vars_of_constr_expr c =
let occur_var_constr_expr id c = Id.Set.mem id (free_vars_of_constr_expr c)
(* Used in correctness and interface *)
-let map_binder g e nal = List.fold_right (down_located (Name.fold_right g)) nal e
-
-let map_binders f g e bl =
- (* TODO: avoid variable capture in [t] by some [na] in [List.tl nal] *)
- let h (e,bl) (nal,bk,t) = (map_binder g e nal,(nal,bk,f e t)::bl) in
- let (e,rbl) = List.fold_left h (e,[]) bl in
- (e, List.rev rbl)
+let map_binder g e nal = List.fold_right (CAst.with_val (Name.fold_right g)) nal e
let map_local_binders f g e bl =
(* TODO: avoid variable capture in [t] by some [na] in [List.tl nal] *)
+ let open CAst in
let h (e,bl) = function
CLocalAssum(nal,k,ty) ->
(map_binder g e nal, CLocalAssum(nal,k,f e ty)::bl)
- | CLocalDef((loc,na),c,ty) ->
- (Name.fold_right g na e, CLocalDef((loc,na),f e c,Option.map (f e) ty)::bl)
- | CLocalPattern (loc,(pat,t)) ->
+ | CLocalDef( { loc ; v = na } as cna ,c,ty) ->
+ (Name.fold_right g na e, CLocalDef(cna,f e c,Option.map (f e) ty)::bl)
+ | CLocalPattern { loc; v = pat,t } ->
let ids = ids_of_pattern pat in
- (Id.Set.fold g ids e, CLocalPattern (loc,(pat,Option.map (f e) t))::bl) in
+ (Id.Set.fold g ids e, CLocalPattern (make ?loc (pat,Option.map (f e) t))::bl) in
let (e,rbl) = List.fold_left h (e,[]) bl in
(e, List.rev rbl)
@@ -406,15 +387,15 @@ let map_constr_expr_with_binders g f e = CAst.map (function
| CApp ((p,a),l) ->
CApp ((p,f e a),List.map (fun (a,i) -> (f e a,i)) l)
| CProdN (bl,b) ->
- let (e,bl) = map_binders f g e bl in CProdN (bl,f e b)
+ let (e,bl) = map_local_binders f g e bl in CProdN (bl,f e b)
| CLambdaN (bl,b) ->
- let (e,bl) = map_binders f g e bl in CLambdaN (bl,f e b)
+ let (e,bl) = map_local_binders f g e bl in CLambdaN (bl,f e b)
| CLetIn (na,a,t,b) ->
- CLetIn (na,f e a,Option.map (f e) t,f (Name.fold_right g (snd na) e) b)
+ CLetIn (na,f e a,Option.map (f e) t,f (Name.fold_right g (na.CAst.v) e) b)
| CCast (a,c) -> CCast (f e a, Miscops.map_cast_type (f e) c)
- | CNotation (n,(l,ll,bll)) ->
+ | CNotation (n,(l,ll,bl,bll)) ->
(* This is an approximation because we don't know what binds what *)
- CNotation (n,(List.map (f e) l,List.map (List.map (f e)) ll,
+ CNotation (n,(List.map (f e) l,List.map (List.map (f e)) ll, bl,
List.map (fun bl -> snd (map_local_binders f g e bl)) bll))
| CGeneralization (b,a,c) -> CGeneralization (b,a,f e c)
| CDelimiters (s,a) -> CDelimiters (s,f e a)
@@ -422,32 +403,32 @@ let map_constr_expr_with_binders g f e = CAst.map (function
| CPrim _ | CRef _ as x -> x
| CRecord l -> CRecord (List.map (fun (id, c) -> (id, f e c)) l)
| CCases (sty,rtnpo,a,bl) ->
- let bl = List.map (fun (loc,(patl,rhs)) ->
+ let bl = List.map (fun {CAst.v=(patl,rhs);loc} ->
let ids = ids_of_pattern_list patl in
- (loc,(patl,f (Id.Set.fold g ids e) rhs))) bl in
+ CAst.make ?loc (patl,f (Id.Set.fold g ids e) rhs)) bl in
let ids = ids_of_cases_tomatch a in
let po = Option.map (f (Id.Set.fold g ids e)) rtnpo in
CCases (sty, po, List.map (fun (tm,x,y) -> f e tm,x,y) a,bl)
| CLetTuple (nal,(ona,po),b,c) ->
- let e' = List.fold_right (down_located (Name.fold_right g)) nal e in
- let e'' = Option.fold_right (down_located (Name.fold_right g)) ona e in
+ let e' = List.fold_right (CAst.with_val (Name.fold_right g)) nal e in
+ let e'' = Option.fold_right (CAst.with_val (Name.fold_right g)) ona e in
CLetTuple (nal,(ona,Option.map (f e'') po),f e b,f e' c)
| CIf (c,(ona,po),b1,b2) ->
- let e' = Option.fold_right (down_located (Name.fold_right g)) ona e in
+ let e' = Option.fold_right (CAst.with_val (Name.fold_right g)) ona e in
CIf (f e c,(ona,Option.map (f e') po),f e b1,f e b2)
| CFix (id,dl) ->
CFix (id,List.map (fun (id,n,bl,t,d) ->
let (e',bl') = map_local_binders f g e bl in
let t' = f e' t in
(* Note: fix names should be inserted before the arguments... *)
- let e'' = List.fold_left (fun e ((_,id),_,_,_,_) -> g id e) e' dl in
+ let e'' = List.fold_left (fun e ({ CAst.v = id },_,_,_,_) -> g id e) e' dl in
let d' = f e'' d in
(id,n,bl',t',d')) dl)
| CCoFix (id,dl) ->
CCoFix (id,List.map (fun (id,bl,t,d) ->
let (e',bl') = map_local_binders f g e bl in
let t' = f e' t in
- let e'' = List.fold_left (fun e ((_,id),_,_,_) -> g id e) e' dl in
+ let e'' = List.fold_left (fun e ({ CAst.v = id },_,_,_) -> g id e) e' dl in
let d' = f e'' d in
(id,bl',t',d')) dl)
| CProj (p,c) ->
@@ -473,9 +454,10 @@ let locs_of_notation ?loc locs ntn =
| (ba,ea)::l -> if Int.equal pos ba then aux ea l else (pos,ba)::aux ea l
in aux bl (List.sort (fun l1 l2 -> fst l1 - fst l2) locs)
-let ntn_loc ?loc (args,argslist,binderslist) =
+let ntn_loc ?loc (args,argslist,binders,binderslist) =
locs_of_notation ?loc
(List.map constr_loc (args@List.flatten argslist)@
+ List.map cases_pattern_expr_loc binders@
List.map local_binders_loc binderslist)
let patntn_loc ?loc (args,argslist) =
@@ -487,17 +469,18 @@ let error_invalid_pattern_notation ?loc () =
(* Interpret the index of a recursion order annotation *)
let split_at_annot bl na =
- let names = List.map snd (names_of_local_assums bl) in
+ let open CAst in
+ let names = List.map (fun { v } -> v) (names_of_local_assums bl) in
match na with
| None ->
begin match names with
| [] -> CErrors.user_err (Pp.str "A fixpoint needs at least one parameter.")
| _ -> ([], bl)
end
- | Some (loc, id) ->
+ | Some { loc; v = id } ->
let rec aux acc = function
| CLocalAssum (bls, k, t) as x :: rest ->
- let test (_, na) = match na with
+ let test { CAst.v = na } = match na with
| Name id' -> Id.equal id id'
| Anonymous -> false
in
@@ -511,13 +494,13 @@ let split_at_annot bl na =
in
(List.rev ans, CLocalAssum (r, k, t) :: rest)
end
- | CLocalDef ((_,na),_,_) as x :: rest ->
+ | CLocalDef ({ CAst.v = na },_,_) as x :: rest ->
if Name.equal (Name id) na then
CErrors.user_err ?loc
(Id.print id ++ str" must be a proper parameter and not a local definition.")
else
aux (x :: acc) rest
- | CLocalPattern (_,_) :: rest ->
+ | CLocalPattern _ :: rest ->
Loc.raise ?loc (Stream.Error "pattern with quote not allowed after fix")
| [] ->
CErrors.user_err ?loc
@@ -529,9 +512,9 @@ let split_at_annot bl na =
let mkIdentC id = CAst.make @@ CRef (Ident (Loc.tag id),None)
let mkRefC r = CAst.make @@ CRef (r,None)
let mkCastC (a,k) = CAst.make @@ CCast (a,k)
-let mkLambdaC (idl,bk,a,b) = CAst.make @@ CLambdaN ([idl,bk,a],b)
+let mkLambdaC (idl,bk,a,b) = CAst.make @@ CLambdaN ([CLocalAssum (idl,bk,a)],b)
let mkLetInC (id,a,t,b) = CAst.make @@ CLetIn (id,a,t,b)
-let mkProdC (idl,bk,a,b) = CAst.make @@ CProdN ([idl,bk,a],b)
+let mkProdC (idl,bk,a,b) = CAst.make @@ CProdN ([CLocalAssum (idl,bk,a)],b)
let mkAppC (f,l) =
let l = List.map (fun x -> (x,None)) l in
@@ -539,56 +522,11 @@ let mkAppC (f,l) =
| CApp (g,l') -> CAst.make @@ CApp (g, l' @ l)
| _ -> CAst.make @@ CApp ((None, f), l)
-let add_name_in_env env n =
- match snd n with
- | Anonymous -> env
- | Name id -> id :: env
-
-let fresh_var env c =
- Namegen.next_ident_away (Id.of_string "pat")
- (List.fold_left (fun accu id -> Id.Set.add id accu) (free_vars_of_constr_expr c) env)
-
-let expand_binders ?loc mkC bl c =
- let rec loop ?loc bl c =
- match bl with
- | [] -> ([], c)
- | b :: bl ->
- match b with
- | CLocalDef ((loc1,_) as n, oty, b) ->
- let env, c = loop ?loc:(Loc.merge_opt loc1 loc) bl c in
- let env = add_name_in_env env n in
- (env, CAst.make ?loc @@ CLetIn (n,oty,b,c))
- | CLocalAssum ((loc1,_)::_ as nl, bk, t) ->
- let env, c = loop ?loc:(Loc.merge_opt loc1 loc) bl c in
- let env = List.fold_left add_name_in_env env nl in
- (env, mkC ?loc (nl,bk,t) c)
- | CLocalAssum ([],_,_) -> loop ?loc bl c
- | CLocalPattern (loc1, (p, ty)) ->
- let env, c = loop ?loc:(Loc.merge_opt loc1 loc) bl c in
- let ni = fresh_var env c in
- let id = (loc1, Name ni) in
- let ty = match ty with
- | Some ty -> ty
- | None -> CAst.make ?loc:loc1 @@ CHole (None, IntroAnonymous, None)
- in
- let e = CAst.make @@ CRef (Libnames.Ident (loc1, ni), None) in
- let c = CAst.make ?loc @@
- CCases
- (LetPatternStyle, None, [(e,None,None)],
- [(Loc.tag ?loc:loc1 ([[p]], c))])
- in
- (ni :: env, mkC ?loc ([id],Default Explicit,ty) c)
- in
- let (_, c) = loop ?loc bl c in
- c
-
let mkCProdN ?loc bll c =
- let mk ?loc b c = CAst.make ?loc @@ CProdN ([b],c) in
- expand_binders ?loc mk bll c
+ CAst.make ?loc @@ CProdN (bll,c)
let mkCLambdaN ?loc bll c =
- let mk ?loc b c = CAst.make ?loc @@ CLambdaN ([b],c) in
- expand_binders ?loc mk bll c
+ CAst.make ?loc @@ CLambdaN (bll,c)
let coerce_reference_to_id = function
| Ident (_,id) -> id
@@ -597,17 +535,60 @@ let coerce_reference_to_id = function
(str "This expression should be a simple identifier.")
let coerce_to_id = function
- | { CAst.v = CRef (Ident (loc,id),None) } -> (loc,id)
+ | { CAst.v = CRef (Ident (loc,id),None) } -> CAst.make ?loc id
| { CAst.loc; _ } -> CErrors.user_err ?loc
~hdr:"coerce_to_id"
(str "This expression should be a simple identifier.")
let coerce_to_name = function
- | { CAst.v = CRef (Ident (loc,id),None) } -> (loc,Name id)
- | { CAst.loc; CAst.v = CHole (None,Misctypes.IntroAnonymous,None) } -> (loc,Anonymous)
+ | { CAst.v = CRef (Ident (loc,id),None) } -> CAst.make ?loc @@ Name id
+ | { CAst.loc; CAst.v = CHole (None,Misctypes.IntroAnonymous,None) } -> CAst.make ?loc Anonymous
| { CAst.loc; _ } -> CErrors.user_err ?loc ~hdr:"coerce_to_name"
(str "This expression should be a name.")
+let mkCPatOr ?loc = function
+ | [pat] -> pat
+ | disjpat -> CAst.make ?loc @@ (CPatOr disjpat)
+
+let mkAppPattern ?loc p lp =
+ let open CAst in
+ make ?loc @@ (match p.v with
+ | CPatAtom (Some r) -> CPatCstr (r, None, lp)
+ | CPatCstr (r, None, l2) ->
+ CErrors.user_err ?loc:p.loc ~hdr:"compound_pattern"
+ (Pp.str "Nested applications not supported.")
+ | CPatCstr (r, l1, l2) -> CPatCstr (r, l1 , l2@lp)
+ | CPatNotation (n, s, l) -> CPatNotation (n , s, l@lp)
+ | _ -> CErrors.user_err
+ ?loc:p.loc ~hdr:"compound_pattern"
+ (Pp.str "Such pattern cannot have arguments."))
+
+let rec coerce_to_cases_pattern_expr c = CAst.map_with_loc (fun ?loc -> function
+ | CRef (r,None) ->
+ CPatAtom (Some r)
+ | CHole (None,Misctypes.IntroAnonymous,None) ->
+ CPatAtom None
+ | CLetIn ({CAst.loc;v=Name id},b,None,{ CAst.v = CRef (Ident (_,id'),None) }) when Id.equal id id' ->
+ CPatAlias (coerce_to_cases_pattern_expr b, CAst.(make ?loc @@ Name id))
+ | CApp ((None,p),args) when List.for_all (fun (_,e) -> e=None) args ->
+ (mkAppPattern (coerce_to_cases_pattern_expr p) (List.map (fun (a,_) -> coerce_to_cases_pattern_expr a) args)).CAst.v
+ | CAppExpl ((None,r,i),args) ->
+ CPatCstr (r,Some (List.map coerce_to_cases_pattern_expr args),[])
+ | CNotation (ntn,(c,cl,[],[])) ->
+ CPatNotation (ntn,(List.map coerce_to_cases_pattern_expr c,
+ List.map (List.map coerce_to_cases_pattern_expr) cl),[])
+ | CPrim p ->
+ CPatPrim p
+ | CRecord l ->
+ CPatRecord (List.map (fun (r,p) -> (r,coerce_to_cases_pattern_expr p)) l)
+ | CDelimiters (s,p) ->
+ CPatDelimiters (s,coerce_to_cases_pattern_expr p)
+ | CCast (p,CastConv t) ->
+ CPatCast (coerce_to_cases_pattern_expr p,t)
+ | _ ->
+ CErrors.user_err ?loc ~hdr:"coerce_to_cases_pattern_expr"
+ (str "This expression should be coercible to a pattern.")) c
+
let asymmetric_patterns = ref (false)
let _ = Goptions.declare_bool_option {
Goptions.optdepr = false;
diff --git a/interp/constrexpr_ops.mli b/interp/constrexpr_ops.mli
index 6e5c0f851..50c818d3c 100644
--- a/interp/constrexpr_ops.mli
+++ b/interp/constrexpr_ops.mli
@@ -6,7 +6,6 @@
(* * GNU Lesser General Public License Version 2.1 *)
(************************************************************************)
-open Loc
open Names
open Libnames
open Misctypes
@@ -44,9 +43,9 @@ val mkIdentC : Id.t -> constr_expr
val mkRefC : reference -> constr_expr
val mkAppC : constr_expr * constr_expr list -> constr_expr
val mkCastC : constr_expr * constr_expr cast_type -> constr_expr
-val mkLambdaC : Name.t located list * binder_kind * constr_expr * constr_expr -> constr_expr
-val mkLetInC : Name.t located * constr_expr * constr_expr option * constr_expr -> constr_expr
-val mkProdC : Name.t located list * binder_kind * constr_expr * constr_expr -> constr_expr
+val mkLambdaC : lname list * binder_kind * constr_expr * constr_expr -> constr_expr
+val mkLetInC : lname * constr_expr * constr_expr option * constr_expr -> constr_expr
+val mkProdC : lname list * binder_kind * constr_expr * constr_expr -> constr_expr
val mkCLambdaN : ?loc:Loc.t -> local_binder_expr list -> constr_expr -> constr_expr
(** Same as [abstract_constr_expr], with location *)
@@ -54,6 +53,11 @@ val mkCLambdaN : ?loc:Loc.t -> local_binder_expr list -> constr_expr -> constr_e
val mkCProdN : ?loc:Loc.t -> local_binder_expr list -> constr_expr -> constr_expr
(** Same as [prod_constr_expr], with location *)
+val mkCPatOr : ?loc:Loc.t -> cases_pattern_expr list -> cases_pattern_expr
+
+val mkAppPattern : ?loc:Loc.t -> cases_pattern_expr -> cases_pattern_expr list -> cases_pattern_expr
+(** Apply a list of pattern arguments to a pattern *)
+
(** @deprecated variant of mkCLambdaN *)
val abstract_constr_expr : constr_expr -> local_binder_expr list -> constr_expr
[@@ocaml.deprecated "deprecated variant of mkCLambdaN"]
@@ -67,20 +71,22 @@ val prod_constr_expr : constr_expr -> local_binder_expr list -> constr_expr
val coerce_reference_to_id : reference -> Id.t
(** FIXME: nothing to do here *)
-val coerce_to_id : constr_expr -> Id.t located
+val coerce_to_id : constr_expr -> lident
(** Destruct terms of the form [CRef (Ident _)]. *)
-val coerce_to_name : constr_expr -> Name.t located
+val coerce_to_name : constr_expr -> lname
(** Destruct terms of the form [CRef (Ident _)] or [CHole _]. *)
+val coerce_to_cases_pattern_expr : constr_expr -> cases_pattern_expr
+
(** {6 Binder manipulation} *)
val default_binder_kind : binder_kind
-val names_of_local_binders : local_binder_expr list -> Name.t located list
+val names_of_local_binders : local_binder_expr list -> lname list
(** Retrieve a list of binding names from a list of binders. *)
-val names_of_local_assums : local_binder_expr list -> Name.t located list
+val names_of_local_assums : local_binder_expr list -> lname list
(** Same as [names_of_local_binder_exprs], but does not take the [let] bindings into
account. *)
@@ -106,7 +112,7 @@ val ids_of_cases_indtype : cases_pattern_expr -> Id.Set.t
val free_vars_of_constr_expr : constr_expr -> Id.Set.t
val occur_var_constr_expr : Id.t -> constr_expr -> bool
-val split_at_annot : local_binder_expr list -> Id.t located option -> local_binder_expr list * local_binder_expr list
+val split_at_annot : local_binder_expr list -> lident option -> local_binder_expr list * local_binder_expr list
val ntn_loc : ?loc:Loc.t -> constr_notation_substitution -> string -> (int * int) list
val patntn_loc : ?loc:Loc.t -> cases_pattern_notation_substitution -> string -> (int * int) list
diff --git a/interp/constrextern.ml b/interp/constrextern.ml
index 4f7d537d3..dec86ba81 100644
--- a/interp/constrextern.ml
+++ b/interp/constrextern.ml
@@ -257,7 +257,7 @@ let insert_pat_delimiters ?loc p = function
let insert_pat_alias ?loc p = function
| Anonymous -> p
- | Name id -> CAst.make ?loc @@ CPatAlias (p,id)
+ | Name _ as na -> CAst.make ?loc @@ CPatAlias (p,(CAst.make ?loc na))
(**********************************************************************)
(* conversion of references *)
@@ -323,34 +323,35 @@ let is_zero s =
Int.equal (String.length s) i || (s.[i] == '0' && aux (i+1))
in aux 0
-let make_notation_gen loc ntn mknot mkprim destprim l =
+let make_notation_gen loc ntn mknot mkprim destprim l bl =
match ntn,List.map destprim l with
(* Special case to avoid writing "- 3" for e.g. (Z.opp 3) *)
| "- _", [Some (Numeral (p,true))] when not (is_zero p) ->
- mknot (loc,ntn,([mknot (loc,"( _ )",l)]))
+ assert (bl=[]);
+ mknot (loc,ntn,([mknot (loc,"( _ )",l,[])]),[])
| _ ->
match decompose_notation_key ntn, l with
| [Terminal "-"; Terminal x], [] when is_number x ->
mkprim (loc, Numeral (x,false))
| [Terminal x], [] when is_number x ->
mkprim (loc, Numeral (x,true))
- | _ -> mknot (loc,ntn,l)
+ | _ -> mknot (loc,ntn,l,bl)
-let make_notation loc ntn (terms,termlists,binders as subst) =
- if not (List.is_empty termlists) || not (List.is_empty binders) then
+let make_notation loc ntn (terms,termlists,binders,binderlists as subst) =
+ if not (List.is_empty termlists) || not (List.is_empty binderlists) then
CAst.make ?loc @@ CNotation (ntn,subst)
else
make_notation_gen loc ntn
- (fun (loc,ntn,l) -> CAst.make ?loc @@ CNotation (ntn,(l,[],[])))
+ (fun (loc,ntn,l,bl) -> CAst.make ?loc @@ CNotation (ntn,(l,[],bl,[])))
(fun (loc,p) -> CAst.make ?loc @@ CPrim p)
- destPrim terms
+ destPrim terms binders
let make_pat_notation ?loc ntn (terms,termlists as subst) args =
if not (List.is_empty termlists) then (CAst.make ?loc @@ CPatNotation (ntn,subst,args)) else
make_notation_gen loc ntn
- (fun (loc,ntn,l) -> CAst.make ?loc @@ CPatNotation (ntn,(l,[]),args))
+ (fun (loc,ntn,l,_) -> CAst.make ?loc @@ CPatNotation (ntn,(l,[]),args))
(fun (loc,p) -> CAst.make ?loc @@ CPatPrim p)
- destPatPrim terms
+ destPatPrim terms []
let mkPat ?loc qid l = CAst.make ?loc @@
(* Normally irrelevant test with v8 syntax, but let's do it anyway *)
@@ -533,6 +534,10 @@ let occur_name na aty =
| Name id -> occur_var_constr_expr id aty
| Anonymous -> false
+let is_gvar id c = match DAst.get c with
+| GVar id' -> Id.equal id id'
+| _ -> false
+
let is_projection nargs = function
| Some r when not !Flags.in_debugger && not !Flags.raw_print && !print_projections ->
(try
@@ -569,7 +574,7 @@ let explicitize inctx impl (cf,f) args =
is_significant_implicit (Lazy.force a))
in
if visible then
- (Lazy.force a,Some (Loc.tag @@ ExplByName (name_of_implicit imp))) :: tail
+ (Lazy.force a,Some (make @@ ExplByName (name_of_implicit imp))) :: tail
else
tail
| a::args, _::impl -> (Lazy.force a,None) :: exprec (q+1) (args,impl)
@@ -811,19 +816,17 @@ let rec extern inctx scopes vars r =
(List.map (fun c -> lazy (sub_extern true scopes vars c)) args))
| GLetIn (na,b,t,c) ->
- CLetIn ((loc,na),sub_extern false scopes vars b,
+ CLetIn (make ?loc na,sub_extern false scopes vars b,
Option.map (extern_typ scopes vars) t,
extern inctx scopes (add_vname vars na) c)
| GProd (na,bk,t,c) ->
let t = extern_typ scopes vars t in
- let (idl,c) = factorize_prod scopes (add_vname vars na) na bk t c in
- CProdN ([(Loc.tag na)::idl,Default bk,t],c)
+ factorize_prod scopes (add_vname vars na) na bk t c
| GLambda (na,bk,t,c) ->
let t = extern_typ scopes vars t in
- let (idl,c) = factorize_lambda inctx scopes (add_vname vars na) na bk t c in
- CLambdaN ([(Loc.tag na)::idl,Default bk,t],c)
+ factorize_lambda inctx scopes (add_vname vars na) na bk t c
| GCases (sty,rtntypopt,tml,eqns) ->
let vars' =
@@ -837,12 +840,12 @@ let rec extern inctx scopes vars r =
| None -> None
| Some ntn ->
if occur_glob_constr id ntn then
- Some (Loc.tag Anonymous)
+ Some (CAst.make Anonymous)
else None
end
| Anonymous, _ -> None
| Name id, GVar id' when Id.equal id id' -> None
- | Name _, _ -> Some (Loc.tag na) in
+ | Name _, _ -> Some (CAst.make na) in
(sub_extern false scopes vars tm,
na',
Option.map (fun (loc,(ind,nal)) ->
@@ -856,15 +859,15 @@ let rec extern inctx scopes vars r =
CCases (sty,rtntypopt',tml,eqns)
| GLetTuple (nal,(na,typopt),tm,b) ->
- CLetTuple (List.map (fun na -> (Loc.tag na)) nal,
- (Option.map (fun _ -> (Loc.tag na)) typopt,
+ CLetTuple (List.map CAst.make nal,
+ (Option.map (fun _ -> (make na)) typopt,
Option.map (extern_typ scopes (add_vname vars na)) typopt),
sub_extern false scopes vars tm,
extern inctx scopes (List.fold_left add_vname vars nal) b)
| GIf (c,(na,typopt),b1,b2) ->
CIf (sub_extern false scopes vars c,
- (Option.map (fun _ -> (Loc.tag na)) typopt,
+ (Option.map (fun _ -> (CAst.make na)) typopt,
Option.map (extern_typ scopes (add_vname vars na)) typopt),
sub_extern inctx scopes vars b1, sub_extern inctx scopes vars b2)
@@ -882,13 +885,13 @@ let rec extern inctx scopes vars r =
let n =
match fst nv.(i) with
| None -> None
- | Some x -> Some (Loc.tag @@ Name.get_id (List.nth assums x))
+ | Some x -> Some (CAst.make @@ Name.get_id (List.nth assums x))
in
let ro = extern_recursion_order scopes vars (snd nv.(i)) in
- ((Loc.tag fi), (n, ro), bl, extern_typ scopes vars0 ty,
+ ((CAst.make fi), (n, ro), bl, extern_typ scopes vars0 ty,
extern false scopes vars1 def)) idv
in
- CFix ((loc,idv.(n)),Array.to_list listdecl)
+ CFix (CAst.(make ?loc idv.(n)), Array.to_list listdecl)
| GCoFix n ->
let listdecl =
Array.mapi (fun i fi ->
@@ -896,10 +899,10 @@ let rec extern inctx scopes vars r =
let (_,ids,bl) = extern_local_binder scopes vars bl in
let vars0 = List.fold_right (Name.fold_right Id.Set.add) ids vars in
let vars1 = List.fold_right (Name.fold_right Id.Set.add) ids vars' in
- ((Loc.tag fi),bl,extern_typ scopes vars0 tyv.(i),
+ ((CAst.make fi),bl,extern_typ scopes vars0 tyv.(i),
sub_extern false scopes vars1 bv.(i))) idv
in
- CCoFix ((loc,idv.(n)),Array.to_list listdecl))
+ CCoFix (CAst.(make ?loc idv.(n)),Array.to_list listdecl))
| GSort s -> CSort (extern_glob_sort s)
@@ -919,24 +922,60 @@ and extern_typ (_,scopes) =
and sub_extern inctx (_,scopes) = extern inctx (None,scopes)
and factorize_prod scopes vars na bk aty c =
- let c = extern_typ scopes vars c in
- match na, c with
- | Name id, { CAst.loc ; v = CProdN ([nal,Default bk',ty],c) }
- when binding_kind_eq bk bk' && constr_expr_eq aty ty
- && not (occur_var_constr_expr id ty) (* avoid na in ty escapes scope *) ->
- nal,c
- | _ ->
- [],c
+ let store, get = set_temporary_memory () in
+ match na, DAst.get c with
+ | Name id, GCases (LetPatternStyle, None, [(e,(Anonymous,None))],(_::_ as eqns))
+ when is_gvar id e && List.length (store (factorize_eqns eqns)) = 1 ->
+ (match get () with
+ | [(_,(ids,disj_of_patl,b))] ->
+ let disjpat = List.map (function [pat] -> pat | _ -> assert false) disj_of_patl in
+ let disjpat = if occur_glob_constr id b then List.map (set_pat_alias id) disjpat else disjpat in
+ let b = extern_typ scopes vars b in
+ let p = mkCPatOr (List.map (extern_cases_pattern_in_scope scopes vars) disjpat) in
+ let binder = CLocalPattern (make ?loc:c.loc (p,None)) in
+ (match b.v with
+ | CProdN (bl,b) -> CProdN (binder::bl,b)
+ | _ -> CProdN ([binder],b))
+ | _ -> assert false)
+ | _, _ ->
+ let c = extern_typ scopes vars c in
+ match na, c.v with
+ | Name id, CProdN (CLocalAssum(nal,Default bk',ty)::bl,b)
+ when binding_kind_eq bk bk' && constr_expr_eq aty ty
+ && not (occur_var_constr_expr id ty) (* avoid na in ty escapes scope *) ->
+ CProdN (CLocalAssum(make na::nal,Default bk,aty)::bl,b)
+ | _, CProdN (bl,b) ->
+ CProdN (CLocalAssum([make na],Default bk,aty)::bl,b)
+ | _, _ ->
+ CProdN ([CLocalAssum([make na],Default bk,aty)],c)
and factorize_lambda inctx scopes vars na bk aty c =
- let c = sub_extern inctx scopes vars c in
- match c with
- | { CAst.loc; v = CLambdaN ([nal,Default bk',ty],c) }
- when binding_kind_eq bk bk' && constr_expr_eq aty ty
- && not (occur_name na ty) (* avoid na in ty escapes scope *) ->
- nal,c
- | _ ->
- [],c
+ let store, get = set_temporary_memory () in
+ match na, DAst.get c with
+ | Name id, GCases (LetPatternStyle, None, [(e,(Anonymous,None))],(_::_ as eqns))
+ when is_gvar id e && List.length (store (factorize_eqns eqns)) = 1 ->
+ (match get () with
+ | [(_,(ids,disj_of_patl,b))] ->
+ let disjpat = List.map (function [pat] -> pat | _ -> assert false) disj_of_patl in
+ let disjpat = if occur_glob_constr id b then List.map (set_pat_alias id) disjpat else disjpat in
+ let b = sub_extern inctx scopes vars b in
+ let p = mkCPatOr (List.map (extern_cases_pattern_in_scope scopes vars) disjpat) in
+ let binder = CLocalPattern (make ?loc:c.loc (p,None)) in
+ (match b.v with
+ | CLambdaN (bl,b) -> CLambdaN (binder::bl,b)
+ | _ -> CLambdaN ([binder],b))
+ | _ -> assert false)
+ | _, _ ->
+ let c = sub_extern inctx scopes vars c in
+ match c.v with
+ | CLambdaN (CLocalAssum(nal,Default bk',ty)::bl,b)
+ when binding_kind_eq bk bk' && constr_expr_eq aty ty
+ && not (occur_name na ty) (* avoid na in ty escapes scope *) ->
+ CLambdaN (CLocalAssum(make na::nal,Default bk,aty)::bl,b)
+ | CLambdaN (bl,b) ->
+ CLambdaN (CLocalAssum([make na],Default bk,aty)::bl,b)
+ | _ ->
+ CLambdaN ([CLocalAssum([make na],Default bk,aty)],c)
and extern_local_binder scopes vars = function
[] -> ([],[],[])
@@ -946,7 +985,7 @@ and extern_local_binder scopes vars = function
let (assums,ids,l) =
extern_local_binder scopes (Name.fold_right Id.Set.add na vars) l in
(assums,na::ids,
- CLocalDef((Loc.tag na), extern false scopes vars bd,
+ CLocalDef(CAst.make na, extern false scopes vars bd,
Option.map (extern false scopes vars) ty) :: l)
| GLocalAssum (na,bk,ty) ->
@@ -957,21 +996,21 @@ and extern_local_binder scopes vars = function
match na with Name id -> not (occur_var_constr_expr id ty')
| _ -> true ->
(na::assums,na::ids,
- CLocalAssum((Loc.tag na)::nal,k,ty')::l)
+ CLocalAssum(CAst.make na::nal,k,ty')::l)
| (assums,ids,l) ->
(na::assums,na::ids,
- CLocalAssum([(Loc.tag na)],Default bk,ty) :: l))
+ CLocalAssum([CAst.make na],Default bk,ty) :: l))
| GLocalPattern ((p,_),_,bk,ty) ->
let ty =
if !Flags.raw_print then Some (extern_typ scopes vars ty) else None in
- let p = extern_cases_pattern vars p in
+ let p = mkCPatOr (List.map (extern_cases_pattern vars) p) in
let (assums,ids,l) = extern_local_binder scopes vars l in
- (assums,ids, CLocalPattern(Loc.tag @@ (p,ty)) :: l)
+ (assums,ids, CLocalPattern(CAst.make @@ (p,ty)) :: l)
and extern_eqn inctx scopes vars (loc,(ids,pll,c)) =
let pll = List.map (List.map (extern_cases_pattern_in_scope scopes vars)) pll in
- Loc.tag ?loc (pll,extern inctx scopes vars c)
+ make ?loc (pll,extern inctx scopes vars c)
and extern_notation (tmp_scope,scopes as allscopes) vars t = function
| [] -> raise No_match
@@ -1014,7 +1053,7 @@ and extern_notation (tmp_scope,scopes as allscopes) vars t = function
| _, None -> t, [], [], []
| _ -> raise No_match in
(* Try matching ... *)
- let terms,termlists,binders =
+ let terms,termlists,binders,binderlists =
match_notation_constr !print_universes t pat in
(* Try availability of interpretation ... *)
let e =
@@ -1035,11 +1074,15 @@ and extern_notation (tmp_scope,scopes as allscopes) vars t = function
List.map (fun (c,(scopt,scl)) ->
List.map (extern true (scopt,scl@scopes') vars) c)
termlists in
- let bll =
- List.map (fun (bl,(scopt,scl)) ->
- pi3 (extern_local_binder (scopt,scl@scopes') vars bl))
+ let bl =
+ List.map (fun (bl,(scopt,scl)) ->
+ mkCPatOr (List.map (extern_cases_pattern_in_scope (scopt,scl@scopes') vars) bl))
binders in
- insert_delimiters (make_notation loc ntn (l,ll,bll)) key)
+ let bll =
+ List.map (fun (bl,(scopt,scl)) ->
+ pi3 (extern_local_binder (scopt,scl@scopes') vars bl))
+ binderlists in
+ insert_delimiters (make_notation loc ntn (l,ll,bl,bll)) key)
| SynDefRule kn ->
let l =
List.map (fun (c,(scopt,scl)) ->
diff --git a/interp/constrintern.ml b/interp/constrintern.ml
index 4afe301dd..d03aa3552 100644
--- a/interp/constrintern.ml
+++ b/interp/constrintern.ml
@@ -9,6 +9,7 @@
open Pp
open CErrors
open Util
+open CAst
open Names
open Nameops
open Namegen
@@ -213,20 +214,20 @@ let expand_notation_string ntn n =
(* This contracts the special case of "{ _ }" for sumbool, sumor notations *)
(* Remark: expansion of squash at definition is done in metasyntax.ml *)
-let contract_notation ntn (l,ll,bll) =
+let contract_curly_brackets ntn (l,ll,bl,bll) =
let ntn' = ref ntn in
let rec contract_squash n = function
| [] -> []
- | { CAst.v = CNotation ("{ _ }",([a],[],[])) } :: l ->
+ | { CAst.v = CNotation ("{ _ }",([a],[],[],[])) } :: l ->
ntn' := expand_notation_string !ntn' n;
contract_squash n (a::l)
| a :: l ->
a::contract_squash (n+1) l in
let l = contract_squash 0 l in
(* side effect; don't inline *)
- !ntn',(l,ll,bll)
+ !ntn',(l,ll,bl,bll)
-let contract_pat_notation ntn (l,ll) =
+let contract_curly_brackets_pat ntn (l,ll) =
let ntn' = ref ntn in
let rec contract_squash n = function
| [] -> []
@@ -271,29 +272,24 @@ let error_expect_binder_notation_type ?loc id =
(Id.print id ++
str " is expected to occur in binding position in the right-hand side.")
-let set_var_scope ?loc id istermvar env ntnvars =
+let set_var_scope ?loc id istermvar (tmp_scope,subscopes as scopes) ntnvars =
try
- let isonlybinding,idscopes,typ = Id.Map.find id ntnvars in
- if istermvar then isonlybinding := false;
+ let used_as_binder,idscopes,typ = Id.Map.find id ntnvars in
+ if not istermvar then used_as_binder := true;
let () = if istermvar then
(* scopes have no effect on the interpretation of identifiers *)
begin match !idscopes with
- | None -> idscopes := Some (env.tmp_scope, env.scopes)
- | Some (tmp, scope) ->
- let s1 = make_current_scope tmp scope in
- let s2 = make_current_scope env.tmp_scope env.scopes in
- if not (List.equal String.equal s1 s2) then error_inconsistent_scope ?loc id s1 s2
+ | None -> idscopes := Some scopes
+ | Some (tmp_scope', subscopes') ->
+ let s' = make_current_scope tmp_scope' subscopes' in
+ let s = make_current_scope tmp_scope subscopes in
+ if not (List.equal String.equal s' s) then error_inconsistent_scope ?loc id s' s
end
in
match typ with
- | NtnInternTypeBinder ->
+ | Notation_term.NtnInternTypeOnlyBinder ->
if istermvar then error_expect_binder_notation_type ?loc id
- | NtnInternTypeConstr ->
- (* We need sometimes to parse idents at a constr level for
- factorization and we cannot enforce this constraint:
- if not istermvar then error_expect_constr_notation_type loc id *)
- ()
- | NtnInternTypeIdent -> ()
+ | Notation_term.NtnInternTypeAny -> ()
with Not_found ->
(* Not in a notation *)
()
@@ -302,15 +298,11 @@ let set_type_scope env = {env with tmp_scope = Notation.current_type_scope_name
let reset_tmp_scope env = {env with tmp_scope = None}
-let rec it_mkGProd ?loc env body =
- match env with
- (loc2, (na, bk, t)) :: tl -> it_mkGProd ?loc:loc2 tl (DAst.make ?loc:(Loc.merge_opt loc loc2) @@ GProd (na, bk, t, body))
- | [] -> body
+let set_env_scopes env (scopt,subscopes) =
+ {env with tmp_scope = scopt; scopes = subscopes @ env.scopes}
-let rec it_mkGLambda ?loc env body =
- match env with
- (loc2, (na, bk, t)) :: tl -> it_mkGLambda ?loc:loc2 tl (DAst.make ?loc:(Loc.merge_opt loc loc2) @@ GLambda (na, bk, t, body))
- | [] -> body
+let mkGProd ?loc (na,bk,t) body = DAst.make ?loc @@ GProd (na, bk, t, body)
+let mkGLambda ?loc (na,bk,t) body = DAst.make ?loc @@ GLambda (na, bk, t, body)
(**********************************************************************)
(* Utilities for binders *)
@@ -337,8 +329,8 @@ let impls_term_list ?(args = []) =
in aux []
(* Check if in binder "(x1 x2 .. xn : t)", none of x1 .. xn-1 occurs in t *)
-let rec check_capture ty = function
- | (loc,Name id)::(_,Name id')::_ when occur_glob_constr id ty ->
+let rec check_capture ty = let open CAst in function
+ | { loc; v = Name id } :: { v = Name id' } :: _ when occur_glob_constr id ty ->
raise (InternalizationError (loc,VariableCapture (id,id')))
| _::nal ->
check_capture ty nal
@@ -369,22 +361,23 @@ let check_hidden_implicit_parameters ?loc id impls =
strbrk "the type of a constructor shall use a different name.")
let push_name_env ?(global_level=false) ntnvars implargs env =
+ let open CAst in
function
- | loc,Anonymous ->
+ | { loc; v = Anonymous } ->
if global_level then
user_err ?loc (str "Anonymous variables not allowed");
env
- | loc,Name id ->
+ | { loc; v = Name id } ->
check_hidden_implicit_parameters ?loc id env.impls ;
if Id.Map.is_empty ntnvars && Id.equal id ldots_var
then error_ldots_var ?loc;
- set_var_scope ?loc id false env ntnvars;
- if global_level then Dumpglob.dump_definition (loc,id) true "var"
+ set_var_scope ?loc id false (env.tmp_scope,env.scopes) ntnvars;
+ if global_level then Dumpglob.dump_definition CAst.(make ?loc id) true "var"
else Dumpglob.dump_binding ?loc id;
{env with ids = Id.Set.add id env.ids; impls = Id.Map.add id implargs env.impls}
-let intern_generalized_binder ?(global_level=false) intern_type lvar
- env (loc, na) b b' t ty =
+let intern_generalized_binder ?(global_level=false) intern_type ntnvars
+ env {loc;v=na} b b' t ty =
let ids = (match na with Anonymous -> fun x -> x | Name na -> Id.Set.add na) env.ids in
let ty, ids' =
if t then ty, ids else
@@ -394,11 +387,11 @@ let intern_generalized_binder ?(global_level=false) intern_type lvar
let ty' = intern_type {env with ids = ids; unb = true} ty in
let fvs = Implicit_quantifiers.generalizable_vars_of_glob_constr ~bound:ids ~allowed:ids' ty' in
let env' = List.fold_left
- (fun env (l, x) -> push_name_env ~global_level lvar (Variable,[],[],[])(*?*) env (l, Name x))
+ (fun env {loc;v=x} -> push_name_env ~global_level ntnvars (Variable,[],[],[])(*?*) env (make ?loc @@ Name x))
env fvs in
let bl = List.map
- (fun (loc, id) ->
- (loc, (Name id, b, DAst.make ?loc @@ GHole (Evar_kinds.BinderType (Name id), Misctypes.IntroAnonymous, None))))
+ CAst.(map (fun id ->
+ (Name id, b, DAst.make ?loc @@ GHole (Evar_kinds.BinderType (Name id), Misctypes.IntroAnonymous, None))))
fvs
in
let na = match na with
@@ -413,9 +406,9 @@ let intern_generalized_binder ?(global_level=false) intern_type lvar
in Implicit_quantifiers.make_fresh ids' (Global.env ()) id
in Name name
| _ -> na
- in (push_name_env ~global_level lvar (impls_type_list ty')(*?*) env' (loc,na)), (loc,(na,b',ty')) :: List.rev bl
+ in (push_name_env ~global_level ntnvars (impls_type_list ty')(*?*) env' (make ?loc na)), (make ?loc (na,b',ty')) :: List.rev bl
-let intern_assumption intern lvar env nal bk ty =
+let intern_assumption intern ntnvars env nal bk ty =
let intern_type env = intern (set_type_scope env) in
match bk with
| Default k ->
@@ -423,12 +416,12 @@ let intern_assumption intern lvar env nal bk ty =
check_capture ty nal;
let impls = impls_type_list ty in
List.fold_left
- (fun (env, bl) (loc, na as locna) ->
- (push_name_env lvar impls env locna,
- (Loc.tag ?loc (na,k,locate_if_hole ?loc na ty))::bl))
+ (fun (env, bl) ({loc;v=na} as locna) ->
+ (push_name_env ntnvars impls env locna,
+ (make ?loc (na,k,locate_if_hole ?loc na ty))::bl))
(env, []) nal
| Generalized (b,b',t) ->
- let env, b = intern_generalized_binder intern_type lvar env (List.hd nal) b b' t ty in
+ let env, b = intern_generalized_binder intern_type ntnvars env (List.hd nal) b b' t ty in
env, b
let glob_local_binder_of_extended = DAst.with_loc_val (fun ?loc -> function
@@ -443,39 +436,48 @@ let glob_local_binder_of_extended = DAst.with_loc_val (fun ?loc -> function
let intern_cases_pattern_fwd = ref (fun _ -> failwith "intern_cases_pattern_fwd")
-let intern_local_binder_aux ?(global_level=false) intern lvar (env,bl) = function
+let intern_letin_binder intern ntnvars env (({loc;v=na} as locna),def,ty) =
+ let term = intern env def in
+ let ty = Option.map (intern env) ty in
+ (push_name_env ntnvars (impls_term_list term) env locna,
+ (na,Explicit,term,ty))
+
+let intern_cases_pattern_as_binder ?loc ntnvars env p =
+ let il,disjpat =
+ let (il, subst_disjpat) = !intern_cases_pattern_fwd ntnvars (None,env.scopes) p in
+ let substl,disjpat = List.split subst_disjpat in
+ if not (List.for_all (fun subst -> Id.Map.equal Id.equal subst Id.Map.empty) substl) then
+ user_err ?loc (str "Unsupported nested \"as\" clause.");
+ il,disjpat
+ in
+ let env = List.fold_right (fun {loc;v=id} env -> push_name_env ntnvars (Variable,[],[],[]) env (make ?loc @@ Name id)) il env in
+ let na = alias_of_pat (List.hd disjpat) in
+ let ienv = Name.fold_right Id.Set.remove na env.ids in
+ let id = Namegen.next_name_away_with_default "pat" na ienv in
+ let na = make ?loc @@ Name id in
+ env,((disjpat,il),id),na
+
+let intern_local_binder_aux ?(global_level=false) intern ntnvars (env,bl) = function
| CLocalAssum(nal,bk,ty) ->
- let env, bl' = intern_assumption intern lvar env nal bk ty in
- let bl' = List.map (fun (loc,(na,c,t)) -> DAst.make ?loc @@ GLocalAssum (na,c,t)) bl' in
+ let env, bl' = intern_assumption intern ntnvars env nal bk ty in
+ let bl' = List.map (fun {loc;v=(na,c,t)} -> DAst.make ?loc @@ GLocalAssum (na,c,t)) bl' in
env, bl' @ bl
- | CLocalDef((loc,na as locna),def,ty) ->
- let term = intern env def in
- let ty = Option.map (intern env) ty in
- (push_name_env lvar (impls_term_list term) env locna,
- (DAst.make ?loc @@ GLocalDef (na,Explicit,term,ty)) :: bl)
- | CLocalPattern (loc,(p,ty)) ->
+ | CLocalDef( {loc; v=na} as locna,def,ty) ->
+ let env,(na,bk,def,ty) = intern_letin_binder intern ntnvars env (locna,def,ty) in
+ env, (DAst.make ?loc @@ GLocalDef (na,bk,def,ty)) :: bl
+ | CLocalPattern {loc;v=(p,ty)} ->
let tyc =
match ty with
| Some ty -> ty
| None -> CAst.make ?loc @@ CHole(None,Misctypes.IntroAnonymous,None)
in
- let il,cp =
- match !intern_cases_pattern_fwd (None,env.scopes) p with
- | (il, [(subst,cp)]) ->
- if not (Id.Map.equal Id.equal subst Id.Map.empty) then
- user_err ?loc (str "Unsupported nested \"as\" clause.");
- il,cp
- | _ -> assert false
- in
- let env = {env with ids = List.fold_right Id.Set.add il env.ids} in
- let id = Namegen.next_ident_away (Id.of_string "pat") env.ids in
- let na = (loc, Name id) in
+ let env, ((disjpat,il),id),na = intern_cases_pattern_as_binder ?loc ntnvars env p in
let bk = Default Explicit in
- let _, bl' = intern_assumption intern lvar env [na] bk tyc in
- let _,(_,bk,t) = List.hd bl' in
- (env, (DAst.make ?loc @@ GLocalPattern((cp,il),id,bk,t)) :: bl)
+ let _, bl' = intern_assumption intern ntnvars env [na] bk tyc in
+ let {v=(_,bk,t)} = List.hd bl' in
+ (env, (DAst.make ?loc @@ GLocalPattern((disjpat,List.map (fun x -> x.v) il),id,bk,t)) :: bl)
-let intern_generalization intern env lvar loc bk ak c =
+let intern_generalization intern env ntnvars loc bk ak c =
let c = intern {env with unb = true} c in
let fvs = Implicit_quantifiers.generalizable_vars_of_glob_constr ~bound:env.ids c in
let env', c' =
@@ -495,19 +497,35 @@ let intern_generalization intern env lvar loc bk ak c =
| None -> false
in
if pi then
- (fun (loc', id) acc ->
+ (fun {loc=loc';v=id} acc ->
DAst.make ?loc:(Loc.merge_opt loc' loc) @@
GProd (Name id, bk, DAst.make ?loc:loc' @@ GHole (Evar_kinds.BinderType (Name id), Misctypes.IntroAnonymous, None), acc))
else
- (fun (loc', id) acc ->
+ (fun {loc=loc';v=id} acc ->
DAst.make ?loc:(Loc.merge_opt loc' loc) @@
GLambda (Name id, bk, DAst.make ?loc:loc' @@ GHole (Evar_kinds.BinderType (Name id), Misctypes.IntroAnonymous, None), acc))
in
- List.fold_right (fun (loc, id as lid) (env, acc) ->
- let env' = push_name_env lvar (Variable,[],[],[]) env (loc, Name id) in
+ List.fold_right (fun ({loc;v=id} as lid) (env, acc) ->
+ let env' = push_name_env ntnvars (Variable,[],[],[]) env CAst.(make @@ Name id) in
(env', abs lid acc)) fvs (env,c)
in c'
+let rec expand_binders ?loc mk bl c =
+ match bl with
+ | [] -> c
+ | b :: bl ->
+ match DAst.get b with
+ | GLocalDef (n, bk, b, oty) ->
+ expand_binders ?loc mk bl (DAst.make ?loc @@ GLetIn (n, b, oty, c))
+ | GLocalAssum (n, bk, t) ->
+ expand_binders ?loc mk bl (mk ?loc (n,bk,t) c)
+ | GLocalPattern ((disjpat,ids), id, bk, ty) ->
+ let tm = DAst.make ?loc (GVar id) in
+ (* Distribute the disjunctive patterns over the shared right-hand side *)
+ let eqnl = List.map (fun pat -> (loc,(ids,[pat],c))) disjpat in
+ let c = DAst.make ?loc @@ GCases (Misctypes.LetPatternStyle, None, [tm,(Anonymous,None)], eqnl) in
+ expand_binders ?loc mk bl (mk ?loc (Name id,Explicit,ty) c)
+
(**********************************************************************)
(* Syntax extensions *)
@@ -515,7 +533,7 @@ let option_mem_assoc id = function
| Some (id',c) -> Id.equal id id'
| None -> false
-let find_fresh_name renaming (terms,termlists,binders) avoid id =
+let find_fresh_name renaming (terms,termlists,binders,binderlists) avoid id =
let fold1 _ (c, _) accu = Id.Set.union (free_vars_of_constr_expr c) accu in
let fold2 _ (l, _) accu =
let fold accu c = Id.Set.union (free_vars_of_constr_expr c) accu in
@@ -528,14 +546,53 @@ let find_fresh_name renaming (terms,termlists,binders) avoid id =
(* TODO binders *)
next_ident_away_from id (fun id -> Id.Set.mem id fvs3)
-let traverse_binder (terms,_,_ as subst) avoid (renaming,env) = function
- | Anonymous -> (renaming,env),Anonymous
+let is_var store pat =
+ match DAst.get pat with
+ | PatVar na -> store na; true
+ | _ -> false
+
+let out_var pat =
+ match pat.CAst.v with
+ | CPatAtom (Some (Ident (_,id))) -> Name id
+ | CPatAtom None -> Anonymous
+ | _ -> assert false
+
+let term_of_name = function
+ | Name id -> DAst.make (GVar id)
+ | Anonymous ->
+ let st = Evar_kinds.Define (not (Program.get_proofs_transparency ())) in
+ DAst.make (GHole (Evar_kinds.QuestionMark (st,Anonymous), Misctypes.IntroAnonymous, None))
+
+let traverse_binder intern_pat ntnvars (terms,_,binders,_ as subst) avoid (renaming,env) = function
+ | Anonymous -> (renaming,env), None, Anonymous
| Name id ->
+ let store,get = set_temporary_memory () in
+ try
+ (* We instantiate binder name with patterns which may be parsed as terms *)
+ let pat = coerce_to_cases_pattern_expr (fst (Id.Map.find id terms)) in
+ let env,((disjpat,ids),id),na = intern_pat ntnvars env pat in
+ let pat, na = match disjpat with
+ | [pat] when is_var store pat -> let na = get () in None, na
+ | _ -> Some ((List.map (fun x -> x.v) ids,disjpat),id), na.v in
+ (renaming,env), pat, na
+ with Not_found ->
try
- (* Binders bound in the notation are considered first-order objects *)
- let _,na as locna = coerce_to_name (fst (Id.Map.find id terms)) in
- let env = push_name_env Id.Map.empty (Variable,[],[],[]) env locna in
- (renaming,env), na
+ (* Trying to associate a pattern *)
+ let pat,(onlyident,scopes) = Id.Map.find id binders in
+ let env = set_env_scopes env scopes in
+ if onlyident then
+ (* Do not try to interpret a variable as a constructor *)
+ let na = out_var pat in
+ let env = push_name_env ntnvars (Variable,[],[],[]) env (make ?loc:pat.loc na) in
+ (renaming,env), None, na
+ else
+ (* Interpret as a pattern *)
+ let env,((disjpat,ids),id),na = intern_pat ntnvars env pat in
+ let pat, na =
+ match disjpat with
+ | [pat] when is_var store pat -> let na = get () in None, na
+ | _ -> Some ((List.map (fun x -> x.v) ids,disjpat),id), na.v in
+ (renaming,env), pat, na
with Not_found ->
(* Binders not bound in the notation do not capture variables *)
(* outside the notation (i.e. in the substitution) *)
@@ -543,49 +600,27 @@ let traverse_binder (terms,_,_ as subst) avoid (renaming,env) = function
let renaming' =
if Id.equal id id' then renaming else Id.Map.add id id' renaming
in
- (renaming',env), Name id'
-
-type letin_param_r =
- | LPLetIn of Name.t * glob_constr * glob_constr option
- | LPCases of (cases_pattern * Id.t list) * Id.t
-(* Unused thus fatal warning *)
-(* and letin_param = letin_param_r Loc.located *)
-
-let make_letins =
- List.fold_right
- (fun a c ->
- match a with
- | loc, LPLetIn (na,b,t) ->
- DAst.make ?loc @@ GLetIn(na,b,t,c)
- | loc, LPCases ((cp,il),id) ->
- let tt = (DAst.make ?loc @@ GVar id, (Name id,None)) in
- DAst.make ?loc @@ GCases(Misctypes.LetPatternStyle,None,[tt],[(loc,(il,[cp],c))]))
-
-let rec subordinate_letins letins l = match l with
- | bnd :: l ->
- let loc = bnd.CAst.loc in
- begin match DAst.get bnd with
- (* binders come in reverse order; the non-let are returned in reverse order together *)
- (* with the subordinated let-in in writing order *)
- | GLocalDef (na,_,b,t) ->
- subordinate_letins ((Loc.tag ?loc @@ LPLetIn (na,b,t))::letins) l
- | GLocalAssum (na,bk,t) ->
- let letins',rest = subordinate_letins [] l in
- letins',((loc,(na,bk,t)),letins)::rest
- | GLocalPattern (u,id,bk,t) ->
- subordinate_letins ((Loc.tag ?loc @@ LPCases (u,id))::letins)
- ([DAst.make ?loc @@ GLocalAssum (Name id,bk,t)] @ l)
- end
- | [] ->
- letins,[]
+ (renaming',env), None, Name id'
+
+type binder_action =
+| AddLetIn of Misctypes.lname * constr_expr * constr_expr option
+| AddTermIter of (constr_expr * subscopes) Names.Id.Map.t
+| AddPreBinderIter of Id.t * local_binder_expr (* A binder to be internalized *)
+| AddBinderIter of Id.t * extended_glob_local_binder (* A binder already internalized - used for generalized binders *)
let dmap_with_loc f n =
CAst.map_with_loc (fun ?loc c -> f ?loc (DAst.get_thunk c)) n
+let error_cannot_coerce_wildcard_term ?loc () =
+ user_err ?loc Pp.(str "Cannot turn \"_\" into a term.")
+
+let error_cannot_coerce_disjunctive_pattern_term ?loc () =
+ user_err ?loc Pp.(str "Cannot turn a disjunctive pattern into a term.")
+
let terms_of_binders bl =
let rec term_of_pat pt = dmap_with_loc (fun ?loc -> function
| PatVar (Name id) -> CRef (Ident (loc,id), None)
- | PatVar (Anonymous) -> user_err Pp.(str "Cannot turn \"_\" into a term.")
+ | PatVar (Anonymous) -> error_cannot_coerce_wildcard_term ?loc ()
| PatCstr (c,l,_) ->
let r = Qualid (loc,qualid_of_path (path_of_global (ConstructRef c))) in
let hole = CAst.make ?loc @@ CHole (None,Misctypes.IntroAnonymous,None) in
@@ -599,45 +634,67 @@ let terms_of_binders bl =
| GLocalDef (Name id,_,_,_) -> extract_variables l
| GLocalDef (Anonymous,_,_,_)
| GLocalAssum (Anonymous,_,_) -> user_err Pp.(str "Cannot turn \"_\" into a term.")
- | GLocalPattern ((u,_),_,_,_) -> term_of_pat u :: extract_variables l
+ | GLocalPattern (([u],_),_,_,_) -> term_of_pat u :: extract_variables l
+ | GLocalPattern ((_,_),_,_,_) -> error_cannot_coerce_disjunctive_pattern_term ?loc ()
end
| [] -> [] in
extract_variables bl
-let instantiate_notation_constr loc intern ntnvars subst infos c =
- let (terms,termlists,binders) = subst in
+let flatten_generalized_binders_if_any y l =
+ match List.rev l with
+ | [] -> assert false
+ | a::l -> a, List.map (fun a -> AddBinderIter (y,a)) l (* if l not empty, this means we had a generalized binder *)
+
+let flatten_binders bl =
+ let dispatch = function
+ | CLocalAssum (nal,bk,t) -> List.map (fun na -> CLocalAssum ([na],bk,t)) nal
+ | a -> [a] in
+ List.flatten (List.map dispatch bl)
+
+let instantiate_notation_constr loc intern intern_pat ntnvars subst infos c =
+ let (terms,termlists,binders,binderlists) = subst in
(* when called while defining a notation, avoid capturing the private binders
of the expression by variables bound by the notation (see #3892) *)
let avoid = Id.Map.domain ntnvars in
- let rec aux (terms,binderopt,terminopt as subst') (renaming,env) c =
+ let rec aux (terms,binderopt,iteropt as subst') (renaming,env) c =
let subinfos = renaming,{env with tmp_scope = None} in
match c with
- | NVar id when Id.equal id ldots_var -> Option.get terminopt
+ | NVar id when Id.equal id ldots_var ->
+ let rec aux_letin env = function
+ | [],terminator,_ -> aux (terms,None,None) (renaming,env) terminator
+ | AddPreBinderIter (y,binder)::rest,terminator,iter ->
+ let env,binders = intern_local_binder_aux intern ntnvars (env,[]) binder in
+ let binder,extra = flatten_generalized_binders_if_any y binders in
+ aux (terms,Some (y,binder),Some (extra@rest,terminator,iter)) (renaming,env) iter
+ | AddBinderIter (y,binder)::rest,terminator,iter ->
+ aux (terms,Some (y,binder),Some (rest,terminator,iter)) (renaming,env) iter
+ | AddTermIter nterms::rest,terminator,iter ->
+ aux (nterms,None,Some (rest,terminator,iter)) (renaming,env) iter
+ | AddLetIn (na,c,t)::rest,terminator,iter ->
+ let env,(na,_,c,t) = intern_letin_binder intern ntnvars env (na,c,t) in
+ DAst.make ?loc (GLetIn (na,c,t,aux_letin env (rest,terminator,iter))) in
+ aux_letin env (Option.get iteropt)
| NVar id -> subst_var subst' (renaming, env) id
- | NList (x,y,iter,terminator,lassoc) ->
+ | NList (x,y,iter,terminator,revert) ->
let l,(scopt,subscopes) =
(* All elements of the list are in scopes (scopt,subscopes) *)
try
let l,scopes = Id.Map.find x termlists in
- (if lassoc then List.rev l else l),scopes
+ (if revert then List.rev l else l),scopes
with Not_found ->
try
- let (bl,(scopt,subscopes)) = Id.Map.find x binders in
+ let (bl,(scopt,subscopes)) = Id.Map.find x binderlists in
let env,bl' = List.fold_left (intern_local_binder_aux intern ntnvars) (env,[]) bl in
- terms_of_binders (if lassoc then bl' else List.rev bl'),(None,[])
+ terms_of_binders (if revert then bl' else List.rev bl'),(None,[])
with Not_found ->
anomaly (Pp.str "Inconsistent substitution of recursive notation.") in
- let termin = aux (terms,None,None) subinfos terminator in
- let fold a t =
- let nterms = Id.Map.add y (a, (scopt, subscopes)) terms in
- aux (nterms,None,Some t) subinfos iter
- in
- List.fold_right fold l termin
+ let l = List.map (fun a -> AddTermIter ((Id.Map.add y (a,(scopt,subscopes)) terms))) l in
+ aux (terms,None,Some (l,terminator,iter)) subinfos (NVar ldots_var)
| NHole (knd, naming, arg) ->
let knd = match knd with
| Evar_kinds.BinderType (Name id as na) ->
let na =
- try snd (coerce_to_name (fst (Id.Map.find id terms)))
+ try (coerce_to_name (fst (Id.Map.find id terms))).v
with Not_found ->
try Name (Id.Map.find id renaming)
with Not_found -> na
@@ -653,47 +710,57 @@ let instantiate_notation_constr loc intern ntnvars subst infos c =
let gc = intern nenv c in
(gc, Some c)
in
- let bindings = Id.Map.map mk_env terms in
+ let mk_env' (c, (onlyident,(tmp_scope,subscopes))) =
+ let nenv = {env with tmp_scope; scopes = subscopes @ env.scopes} in
+ if onlyident then
+ let na = out_var c in term_of_name na, None
+ else
+ let _,((disjpat,_),_),_ = intern_pat ntnvars nenv c in
+ match disjpat with
+ | [pat] -> (glob_constr_of_cases_pattern pat, None)
+ | _ -> error_cannot_coerce_disjunctive_pattern_term ?loc:c.CAst.loc ()
+ in
+ let terms = Id.Map.map mk_env terms in
+ let binders = Id.Map.map mk_env' binders in
+ let bindings = Id.Map.fold Id.Map.add terms binders in
Some (Genintern.generic_substitute_notation bindings arg)
in
DAst.make ?loc @@ GHole (knd, naming, arg)
- | NBinderList (x,y,iter,terminator) ->
+ | NBinderList (x,y,iter,terminator,revert) ->
(try
(* All elements of the list are in scopes (scopt,subscopes) *)
- let (bl,(scopt,subscopes)) = Id.Map.find x binders in
- let env,bl = List.fold_left (intern_local_binder_aux intern ntnvars) (env,[]) bl in
- let letins,bl = subordinate_letins [] bl in
- let termin = aux (terms,None,None) (renaming,env) terminator in
- let res = List.fold_left (fun t binder ->
- aux (terms,Some(y,binder),Some t) subinfos iter)
- termin bl in
- make_letins letins res
+ let (bl,(scopt,subscopes)) = Id.Map.find x binderlists in
+ (* We flatten binders so that we can interpret them at substitution time *)
+ let bl = flatten_binders bl in
+ let bl = if revert then List.rev bl else bl in
+ (* We isolate let-ins which do not contribute to the repeated pattern *)
+ let l = List.map (function | CLocalDef (na,c,t) -> AddLetIn (na,c,t)
+ | binder -> AddPreBinderIter (y,binder)) bl in
+ (* We stack the binders to iterate or let-ins to insert *)
+ aux (terms,None,Some (l,terminator,iter)) subinfos (NVar ldots_var)
with Not_found ->
anomaly (Pp.str "Inconsistent substitution of recursive notation."))
| NProd (Name id, NHole _, c') when option_mem_assoc id binderopt ->
- let a,letins = snd (Option.get binderopt) in
- let e = make_letins letins (aux subst' infos c') in
- let (_loc,(na,bk,t)) = a in
- DAst.make ?loc @@ GProd (na,bk,t,e)
+ let binder = snd (Option.get binderopt) in
+ expand_binders ?loc mkGProd [binder] (aux subst' (renaming,env) c')
| NLambda (Name id,NHole _,c') when option_mem_assoc id binderopt ->
- let a,letins = snd (Option.get binderopt) in
- let (_loc,(na,bk,t)) = a in
- DAst.make ?loc @@ GLambda (na,bk,t,make_letins letins (aux subst' infos c'))
+ let binder = snd (Option.get binderopt) in
+ expand_binders ?loc mkGLambda [binder] (aux subst' (renaming,env) c')
(* Two special cases to keep binder name synchronous with BinderType *)
| NProd (na,NHole(Evar_kinds.BinderType na',naming,arg),c')
when Name.equal na na' ->
- let subinfos,na = traverse_binder subst avoid subinfos na in
+ let subinfos,disjpat,na = traverse_binder intern_pat ntnvars subst avoid subinfos na in
let ty = DAst.make ?loc @@ GHole (Evar_kinds.BinderType na,naming,arg) in
- DAst.make ?loc @@ GProd (na,Explicit,ty,aux subst' subinfos c')
+ DAst.make ?loc @@ GProd (na,Explicit,ty,Option.fold_right apply_cases_pattern disjpat (aux subst' subinfos c'))
| NLambda (na,NHole(Evar_kinds.BinderType na',naming,arg),c')
when Name.equal na na' ->
- let subinfos,na = traverse_binder subst avoid subinfos na in
+ let subinfos,disjpat,na = traverse_binder intern_pat ntnvars subst avoid subinfos na in
let ty = DAst.make ?loc @@ GHole (Evar_kinds.BinderType na,naming,arg) in
- DAst.make ?loc @@ GLambda (na,Explicit,ty,aux subst' subinfos c')
+ DAst.make ?loc @@ GLambda (na,Explicit,ty,Option.fold_right apply_cases_pattern disjpat (aux subst' subinfos c'))
| t ->
glob_constr_of_notation_constr_with_binders ?loc
- (traverse_binder subst avoid) (aux subst') subinfos t
- and subst_var (terms, _binderopt, _terminopt) (renaming, env) id =
+ (traverse_binder intern_pat ntnvars subst avoid) (aux subst') subinfos t
+ and subst_var (terms, binderopt, _terminopt) (renaming, env) id =
(* subst remembers the delimiters stack in the interpretation *)
(* of the notations *)
try
@@ -701,6 +768,28 @@ let instantiate_notation_constr loc intern ntnvars subst infos c =
intern {env with tmp_scope = scopt;
scopes = subscopes @ env.scopes} a
with Not_found ->
+ try
+ let pat,(onlyident,scopes) = Id.Map.find id binders in
+ let env = set_env_scopes env scopes in
+ (* We deactivate impls to avoid the check on hidden parameters *)
+ (* and since we are only interested in the pattern as a term *)
+ let env = reset_hidden_inductive_implicit_test env in
+ if onlyident then
+ term_of_name (out_var pat)
+ else
+ let env,((disjpat,ids),id),na = intern_pat ntnvars env pat in
+ match disjpat with
+ | [pat] -> glob_constr_of_cases_pattern pat
+ | _ -> user_err Pp.(str "Cannot turn a disjunctive pattern into a term.")
+ with Not_found ->
+ try
+ match binderopt with
+ | Some (x,binder) when Id.equal x id ->
+ let terms = terms_of_binders [binder] in
+ assert (List.length terms = 1);
+ intern env (List.hd terms)
+ | _ -> raise Not_found
+ with Not_found ->
DAst.make ?loc (
try
GVar (Id.Map.find id renaming)
@@ -709,27 +798,80 @@ let instantiate_notation_constr loc intern ntnvars subst infos c =
GVar id)
in aux (terms,None,None) infos c
-let split_by_type ids =
- List.fold_right (fun (x,(scl,typ)) (l1,l2,l3) ->
+(* Turning substitution coming from parsing and based on production
+ into a substitution for interpretation and based on binding/constr
+ distinction *)
+
+let cases_pattern_of_name {loc;v=na} =
+ let atom = match na with Name id -> Some (Ident (loc,id)) | Anonymous -> None in
+ CAst.make ?loc (CPatAtom atom)
+
+let split_by_type ids subst =
+ let bind id scl l s =
+ match l with
+ | [] -> assert false
+ | a::l -> l, Id.Map.add id (a,scl) s in
+ let (terms,termlists,binders,binderlists),subst =
+ List.fold_left (fun ((terms,termlists,binders,binderlists),(terms',termlists',binders',binderlists')) (id,(scl,typ)) ->
match typ with
- | NtnTypeConstr | NtnTypeOnlyBinder -> ((x,scl)::l1,l2,l3)
- | NtnTypeConstrList -> (l1,(x,scl)::l2,l3)
- | NtnTypeBinderList -> (l1,l2,(x,scl)::l3)) ids ([],[],[])
+ | NtnTypeConstr ->
+ let terms,terms' = bind id scl terms terms' in
+ (terms,termlists,binders,binderlists),(terms',termlists',binders',binderlists')
+ | NtnTypeBinder NtnBinderParsedAsConstr (Extend.AsIdentOrPattern | Extend.AsStrictPattern) ->
+ let a,terms = match terms with a::terms -> a,terms | _ -> assert false in
+ let binders' = Id.Map.add id (coerce_to_cases_pattern_expr a,(false,scl)) binders' in
+ (terms,termlists,binders,binderlists),(terms',termlists',binders',binderlists')
+ | NtnTypeBinder NtnBinderParsedAsConstr Extend.AsIdent ->
+ let a,terms = match terms with a::terms -> a,terms | _ -> assert false in
+ let binders' = Id.Map.add id (cases_pattern_of_name (coerce_to_name a),(true,scl)) binders' in
+ (terms,termlists,binders,binderlists),(terms',termlists',binders',binderlists')
+ | NtnTypeBinder (NtnParsedAsIdent | NtnParsedAsPattern _ as x) ->
+ let onlyident = (x = NtnParsedAsIdent) in
+ let binders,binders' = bind id (onlyident,scl) binders binders' in
+ (terms,termlists,binders,binderlists),(terms',termlists',binders',binderlists')
+ | NtnTypeConstrList ->
+ let termlists,termlists' = bind id scl termlists termlists' in
+ (terms,termlists,binders,binderlists),(terms',termlists',binders',binderlists')
+ | NtnTypeBinderList ->
+ let binderlists,binderlists' = bind id scl binderlists binderlists' in
+ (terms,termlists,binders,binderlists),(terms',termlists',binders',binderlists'))
+ (subst,(Id.Map.empty,Id.Map.empty,Id.Map.empty,Id.Map.empty)) ids in
+ assert (terms = [] && termlists = [] && binders = [] && binderlists = []);
+ subst
+
+let split_by_type_pat ?loc ids subst =
+ let bind id scl l s =
+ match l with
+ | [] -> assert false
+ | a::l -> l, Id.Map.add id (a,scl) s in
+ let (terms,termlists),subst =
+ List.fold_left (fun ((terms,termlists),(terms',termlists')) (id,(scl,typ)) ->
+ match typ with
+ | NtnTypeConstr | NtnTypeBinder _ ->
+ let terms,terms' = bind id scl terms terms' in
+ (terms,termlists),(terms',termlists')
+ | NtnTypeConstrList ->
+ let termlists,termlists' = bind id scl termlists termlists' in
+ (terms,termlists),(terms',termlists')
+ | NtnTypeBinderList -> error_invalid_pattern_notation ?loc ())
+ (subst,(Id.Map.empty,Id.Map.empty)) ids in
+ assert (terms = [] && termlists = []);
+ subst
let make_subst ids l =
let fold accu (id, scl) a = Id.Map.add id (a, scl) accu in
List.fold_left2 fold Id.Map.empty ids l
-let intern_notation intern env lvar loc ntn fullargs =
- let ntn,(args,argslist,bll as fullargs) = contract_notation ntn fullargs in
+let intern_notation intern env ntnvars loc ntn fullargs =
+ (* Adjust to parsing of { } *)
+ let ntn,fullargs = contract_curly_brackets ntn fullargs in
+ (* Recover interpretation { } *)
let ((ids,c),df) = interp_notation ?loc ntn (env.tmp_scope,env.scopes) in
Dumpglob.dump_notation_location (ntn_loc ?loc fullargs ntn) ntn df;
- let ids,idsl,idsbl = split_by_type ids in
- let terms = make_subst ids args in
- let termlists = make_subst idsl argslist in
- let binders = make_subst idsbl bll in
- instantiate_notation_constr loc intern lvar
- (terms, termlists, binders) (Id.Map.empty, env) c
+ (* Dispatch parsing substitution to an interpretation substitution *)
+ let subst = split_by_type ids fullargs in
+ (* Instantiate the notation *)
+ instantiate_notation_constr loc intern intern_cases_pattern_as_binder ntnvars subst (Id.Map.empty, env) c
(**********************************************************************)
(* Discriminating between bound variables and global references *)
@@ -746,25 +888,25 @@ let gvar (loc, id) us = match us with
user_err ?loc (str "Variable " ++ Id.print id ++
str " cannot have a universe instance")
-let intern_var genv (ltacvars,ntnvars) namedctx loc id us =
+let intern_var env (ltacvars,ntnvars) namedctx loc id us =
(* Is [id] a notation variable *)
if Id.Map.mem id ntnvars then
begin
- if not (Id.Map.mem id genv.impls) then set_var_scope ?loc id true genv ntnvars;
+ if not (Id.Map.mem id env.impls) then set_var_scope ?loc id true (env.tmp_scope,env.scopes) ntnvars;
gvar (loc,id) us, [], [], []
end
else
(* Is [id] registered with implicit arguments *)
try
- let ty,expl_impls,impls,argsc = Id.Map.find id genv.impls in
+ let ty,expl_impls,impls,argsc = Id.Map.find id env.impls in
let expl_impls = List.map
- (fun id -> CAst.make ?loc @@ CRef (Ident (loc,id),None), Some (loc,ExplByName id)) expl_impls in
+ (fun id -> CAst.make ?loc @@ CRef (Ident (loc,id),None), Some (make ?loc @@ ExplByName id)) expl_impls in
let tys = string_of_ty ty in
Dumpglob.dump_reference ?loc "<>" (Id.to_string id) tys;
gvar (loc,id) us, make_implicits_list impls, argsc, expl_impls
with Not_found ->
(* Is [id] bound in current term or is an ltac var bound to constr *)
- if Id.Set.mem id genv.ids || Id.Set.mem id ltacvars.ltac_vars
+ if Id.Set.mem id env.ids || Id.Set.mem id ltacvars.ltac_vars
then
gvar (loc,id) us, [], [], []
else if Id.equal id ldots_var
@@ -818,7 +960,7 @@ let check_no_explicitation l =
match l with
| [] -> ()
| (_, None) :: _ -> assert false
- | (_, Some (loc, _)) :: _ ->
+ | (_, Some {loc}) :: _ ->
user_err ?loc (str"Unexpected explicitation of the argument of an abbreviation.")
let dump_extended_global loc = function
@@ -849,7 +991,7 @@ let glob_sort_of_level (level: Misctypes.glob_level) : Misctypes.glob_sort =
| Misctypes.GType info -> Misctypes.GType [sort_info_of_level_info info]
(* Is it a global reference or a syntactic definition? *)
-let intern_qualid loc qid intern env lvar us args =
+let intern_qualid loc qid intern env ntnvars us args =
match intern_extended_global_of_qualid (loc,qid) with
| TrueGlobal ref -> (DAst.make ?loc @@ GRef (ref, us)), true, args
| SynDef sp ->
@@ -859,10 +1001,10 @@ let intern_qualid loc qid intern env lvar us args =
let args1,args2 = List.chop nids args in
check_no_explicitation args1;
let terms = make_subst ids (List.map fst args1) in
- let subst = (terms, Id.Map.empty, Id.Map.empty) in
+ let subst = (terms, Id.Map.empty, Id.Map.empty, Id.Map.empty) in
let infos = (Id.Map.empty, env) in
let projapp = match c with NRef _ -> true | _ -> false in
- let c = instantiate_notation_constr loc intern lvar subst infos c in
+ let c = instantiate_notation_constr loc intern intern_cases_pattern_as_binder ntnvars subst infos c in
let loc = c.CAst.loc in
let err () =
user_err ?loc (str "Notation " ++ pr_qualid qid
@@ -888,13 +1030,14 @@ let intern_qualid loc qid intern env lvar us args =
c, projapp, args2
(* Rule out section vars since these should have been found by intern_var *)
-let intern_non_secvar_qualid loc qid intern env lvar us args =
- let c, _, _ as r = intern_qualid loc qid intern env lvar us args in
+let intern_non_secvar_qualid loc qid intern env ntnvars us args =
+ let c, _, _ as r = intern_qualid loc qid intern env ntnvars us args in
match DAst.get c with
| GRef (VarRef _, _) -> raise Not_found
| _ -> r
-let intern_applied_reference intern env namedctx (_, ntnvars as lvar) us args = function
+let intern_applied_reference intern env namedctx (_, ntnvars as lvar) us args =
+function
| Qualid (loc, qid) ->
let r,projapp,args2 =
try intern_qualid loc qid intern env ntnvars us args
@@ -929,11 +1072,11 @@ let interp_reference vars r =
(** Private internalization patterns *)
type 'a raw_cases_pattern_expr_r =
- | RCPatAlias of 'a raw_cases_pattern_expr * Id.t
+ | RCPatAlias of 'a raw_cases_pattern_expr * Misctypes.lname
| RCPatCstr of Globnames.global_reference
* 'a raw_cases_pattern_expr list * 'a raw_cases_pattern_expr list
(** [RCPatCstr (loc, c, l1, l2)] represents ((@c l1) l2) *)
- | RCPatAtom of Id.t option
+ | RCPatAtom of (Misctypes.lident * (Notation_term.tmp_scope_name option * Notation_term.scope_name list)) option
| RCPatOr of 'a raw_cases_pattern_expr list
and 'a raw_cases_pattern_expr = ('a raw_cases_pattern_expr_r, 'a) DAst.t
@@ -993,7 +1136,7 @@ let check_number_of_pattern loc n l =
if not (Int.equal n p) then raise (InternalizationError (loc,BadPatternsNumber (n,p)))
let check_or_pat_variables loc ids idsl =
- if List.exists (fun ids' -> not (List.eq_set Id.equal ids ids')) idsl then
+ if List.exists (fun ids' -> not (List.eq_set (fun {loc;v=id} {v=id'} -> Id.equal id id') ids ids')) idsl then
user_err ?loc (str
"The components of this disjunctive pattern must bind the same variables.")
@@ -1059,7 +1202,7 @@ let add_implicits_check_length fail nargs nargs_with_letin impls_st len_pl1 pl2
then let (b,out) = aux i (q,[]) in (b,(DAst.make @@ RCPatAtom None)::out)
else fail (remaining_args (len_pl1+i) il)
|imp::q,(hh::tt as l) -> if is_status_implicit imp
- then let (b,out) = aux i (q,l) in (b,(DAst.make @@ RCPatAtom(None))::out)
+ then let (b,out) = aux i (q,l) in (b,(DAst.make @@ RCPatAtom None)::out)
else let (b,out) = aux (succ i) (q,tt) in (b,hh::out)
in aux 0 (impl_list,pl2)
@@ -1232,7 +1375,7 @@ let sort_fields ~complete loc fields completer =
(** {6 Manage multiple aliases} *)
type alias = {
- alias_ids : Id.t list;
+ alias_ids : Misctypes.lident list;
alias_map : Id.t Id.Map.t;
}
@@ -1243,17 +1386,20 @@ let empty_alias = {
(* [merge_aliases] returns the sets of all aliases encountered at this
point and a substitution mapping extra aliases to the first one *)
-let merge_aliases aliases id =
- let alias_ids = aliases.alias_ids @ [id] in
+let merge_aliases aliases {loc;v=na} =
+ match na with
+ | Anonymous -> aliases
+ | Name id ->
+ let alias_ids = aliases.alias_ids @ [make ?loc id] in
let alias_map = match aliases.alias_ids with
| [] -> aliases.alias_map
- | id' :: _ -> Id.Map.add id id' aliases.alias_map
+ | {v=id'} :: _ -> Id.Map.add id id' aliases.alias_map
in
{ alias_ids; alias_map; }
let alias_of als = match als.alias_ids with
| [] -> Anonymous
-| id :: _ -> Name id
+| {v=id} :: _ -> Name id
(** {6 Expanding notations }
@@ -1271,6 +1417,8 @@ let is_zero s =
let merge_subst s1 s2 = Id.Map.fold Id.Map.add s1 s2
let product_of_cases_patterns aliases idspl =
+ (* each [pl] is a disjunction of patterns over common identifiers [ids] *)
+ (* We stepwise build a disjunction of patterns [ptaill] over common [ids'] *)
List.fold_right (fun (ids,pl) (ids',ptaill) ->
(ids @ ids',
(* Cartesian prod of the or-pats for the nth arg and the tail args *)
@@ -1281,7 +1429,7 @@ let product_of_cases_patterns aliases idspl =
let rec subst_pat_iterator y t = DAst.(map (function
| RCPatAtom id as p ->
- begin match id with Some x when Id.equal x y -> DAst.get t | _ -> p end
+ begin match id with Some ({v=x},_) when Id.equal x y -> DAst.get t | _ -> p end
| RCPatCstr (id,l1,l2) ->
RCPatCstr (id,List.map (subst_pat_iterator y t) l1,
List.map (subst_pat_iterator y t) l2)
@@ -1310,13 +1458,16 @@ let drop_notations_pattern looked_for genv =
if top then looked_for else function ConstructRef _ -> () | _ -> raise Not_found
in
(** [rcp_of_glob] : from [glob_constr] to [raw_cases_pattern_expr] *)
- let rec rcp_of_glob x = DAst.(map (function
- | GVar id -> RCPatAtom (Some id)
+ let rec rcp_of_glob scopes x = DAst.(map (function
+ | GVar id -> RCPatAtom (Some (CAst.make ?loc:x.loc id,scopes))
| GHole (_,_,_) -> RCPatAtom (None)
| GRef (g,_) -> RCPatCstr (g,[],[])
| GApp (r, l) ->
begin match DAst.get r with
- | GRef (g,_) -> RCPatCstr (g, List.map rcp_of_glob l,[])
+ | GRef (g,_) ->
+ let allscs = find_arguments_scope g in
+ let allscs = simple_adjust_scopes (List.length l) allscs in (* TO CHECK *)
+ RCPatCstr (g, List.map2 (fun sc a -> rcp_of_glob (sc,snd scopes) a) allscs l,[])
| _ ->
CErrors.anomaly Pp.(str "Invalid return pattern from Notation.interp_prim_token_cases_pattern_expr.")
end
@@ -1396,27 +1547,25 @@ let drop_notations_pattern looked_for genv =
| CPatNotation ("- _",([a],[]),[]) when is_non_zero_pat a ->
let p = match a.CAst.v with CPatPrim (Numeral (p, _)) -> p | _ -> assert false in
let pat, _df = Notation.interp_prim_token_cases_pattern_expr ?loc (ensure_kind false loc) (Numeral (p,false)) scopes in
- rcp_of_glob pat
+ rcp_of_glob scopes pat
| CPatNotation ("( _ )",([a],[]),[]) ->
in_pat top scopes a
- | CPatNotation (ntn, fullargs,extrargs) ->
- let ntn,(args,argsl as fullargs) = contract_pat_notation ntn fullargs in
+ | CPatNotation (ntn,fullargs,extrargs) ->
+ let ntn,(terms,termlists) = contract_curly_brackets_pat ntn fullargs in
let ((ids',c),df) = Notation.interp_notation ?loc ntn scopes in
- let (ids',idsl',_) = split_by_type ids' in
+ let (terms,termlists) = split_by_type_pat ?loc ids' (terms,termlists) in
Dumpglob.dump_notation_location (patntn_loc ?loc fullargs ntn) ntn df;
- let substlist = make_subst idsl' argsl in
- let subst = make_subst ids' args in
- in_not top loc scopes (subst,substlist) extrargs c
+ in_not top loc scopes (terms,termlists) extrargs c
| CPatDelimiters (key, e) ->
in_pat top (None,find_delimiters_scope ?loc key::snd scopes) e
| CPatPrim p ->
let pat, _df = Notation.interp_prim_token_cases_pattern_expr ?loc (test_kind false) p scopes in
- rcp_of_glob pat
- | CPatAtom Some id ->
+ rcp_of_glob scopes pat
+ | CPatAtom (Some id) ->
begin
match drop_syndef top scopes id [] with
| Some (a,b,c) -> DAst.make ?loc @@ RCPatCstr (a, b, c)
- | None -> DAst.make ?loc @@ RCPatAtom (Some (find_pattern_variable id))
+ | None -> DAst.make ?loc @@ RCPatAtom (Some ((make ?loc @@ find_pattern_variable id),scopes))
end
| CPatAtom None -> DAst.make ?loc @@ RCPatAtom None
| CPatOr pl -> DAst.make ?loc @@ RCPatOr (List.map (in_pat top scopes) pl)
@@ -1446,7 +1595,7 @@ let drop_notations_pattern looked_for genv =
let (a,(scopt,subscopes)) = Id.Map.find id subst in
in_pat top (scopt,subscopes@snd scopes) a
with Not_found ->
- if Id.equal id ldots_var then DAst.make ?loc @@ RCPatAtom (Some id) else
+ if Id.equal id ldots_var then DAst.make ?loc @@ RCPatAtom (Some ((make ?loc id),scopes)) else
anomaly (str "Unbound pattern notation variable: " ++ Id.print id ++ str ".")
end
| NRef g ->
@@ -1459,7 +1608,7 @@ let drop_notations_pattern looked_for genv =
let pl = List.map2 (fun x -> in_not false loc (x,snd scopes) fullsubst []) argscs1 pl in
let pl = add_local_defs_and_check_length loc genv g pl args in
DAst.make ?loc @@ RCPatCstr (g, pl @ List.map (in_pat false scopes) args, [])
- | NList (x,y,iter,terminator,lassoc) ->
+ | NList (x,y,iter,terminator,revert) ->
if not (List.is_empty args) then user_err ?loc
(strbrk "Application of arguments to a recursive notation not supported in patterns.");
(try
@@ -1470,7 +1619,7 @@ let drop_notations_pattern looked_for genv =
let nsubst = Id.Map.add y (a, (scopt, subscopes)) subst in
let u = in_not false loc scopes (nsubst, substlist) [] iter in
subst_pat_iterator ldots_var t u)
- (if lassoc then List.rev l else l) termin
+ (if revert then List.rev l else l) termin
with Not_found ->
anomaly (Pp.str "Inconsistent substitution of recursive notation."))
| NHole _ ->
@@ -1479,18 +1628,18 @@ let drop_notations_pattern looked_for genv =
| t -> error_invalid_pattern_notation ?loc ()
in in_pat true
-let rec intern_pat genv aliases pat =
+let rec intern_pat genv ntnvars aliases pat =
let intern_cstr_with_all_args loc c with_letin idslpl1 pl2 =
- let idslpl2 = List.map (intern_pat genv empty_alias) pl2 in
+ let idslpl2 = List.map (intern_pat genv ntnvars empty_alias) pl2 in
let (ids',pll) = product_of_cases_patterns aliases (idslpl1@idslpl2) in
let pl' = List.map (fun (asubst,pl) ->
(asubst, DAst.make ?loc @@ PatCstr (c,chop_params_pattern loc (fst c) pl with_letin,alias_of aliases))) pll in
ids',pl' in
- let loc = CAst.(pat.loc) in
+ let loc = pat.loc in
match DAst.get pat with
| RCPatAlias (p, id) ->
let aliases' = merge_aliases aliases id in
- intern_pat genv aliases' p
+ intern_pat genv ntnvars aliases' p
| RCPatCstr (head, expl_pl, pl) ->
if !asymmetric_patterns then
let len = if List.is_empty expl_pl then Some (List.length pl) else None in
@@ -1503,29 +1652,30 @@ let rec intern_pat genv aliases pat =
let with_letin, pl2 =
add_implicits_check_constructor_length genv loc c (List.length idslpl1 + List.length expl_pl) pl in
intern_cstr_with_all_args loc c with_letin idslpl1 (expl_pl@pl2)
- | RCPatAtom (Some id) ->
- let aliases = merge_aliases aliases id in
- (aliases.alias_ids,[aliases.alias_map, DAst.make ?loc @@ PatVar (alias_of aliases)])
+ | RCPatAtom (Some ({loc;v=id},scopes)) ->
+ let aliases = merge_aliases aliases (make ?loc @@ Name id) in
+ set_var_scope ?loc id false scopes ntnvars;
+ (aliases.alias_ids,[aliases.alias_map, DAst.make ?loc @@ PatVar (alias_of aliases)]) (* TO CHECK: aura-t-on id? *)
| RCPatAtom (None) ->
let { alias_ids = ids; alias_map = asubst; } = aliases in
(ids, [asubst, DAst.make ?loc @@ PatVar (alias_of aliases)])
| RCPatOr pl ->
assert (not (List.is_empty pl));
- let pl' = List.map (intern_pat genv aliases) pl in
+ let pl' = List.map (intern_pat genv ntnvars aliases) pl in
let (idsl,pl') = List.split pl' in
let ids = List.hd idsl in
check_or_pat_variables loc ids (List.tl idsl);
(ids,List.flatten pl')
-let intern_cases_pattern genv scopes aliases pat =
- intern_pat genv aliases
+let intern_cases_pattern genv ntnvars scopes aliases pat =
+ intern_pat genv ntnvars aliases
(drop_notations_pattern (function ConstructRef _ -> () | _ -> raise Not_found) genv scopes pat)
let _ =
intern_cases_pattern_fwd :=
- fun scopes p -> intern_cases_pattern (Global.env ()) scopes empty_alias p
+ fun ntnvars scopes p -> intern_cases_pattern (Global.env ()) ntnvars scopes empty_alias p
-let intern_ind_pattern genv scopes pat =
+let intern_ind_pattern genv ntnvars scopes pat =
let no_not =
try
drop_notations_pattern (function (IndRef _ | ConstructRef _) -> () | _ -> raise Not_found) genv scopes pat
@@ -1537,10 +1687,9 @@ let intern_ind_pattern genv scopes pat =
let c = (function IndRef ind -> ind | _ -> error_bad_inductive_type ?loc) head in
let with_letin, pl2 = add_implicits_check_ind_length genv loc c
(List.length expl_pl) pl in
- let idslpl1 = List.rev_map (intern_pat genv empty_alias) expl_pl in
- let idslpl2 = List.map (intern_pat genv empty_alias) pl2 in
+ let idslpl = List.map (intern_pat genv ntnvars empty_alias) (expl_pl@pl2) in
(with_letin,
- match product_of_cases_patterns empty_alias (List.rev_append idslpl1 idslpl2) with
+ match product_of_cases_patterns empty_alias idslpl with
| _,[_,pl] -> (c,chop_params_pattern loc c pl with_letin)
| _ -> error_bad_inductive_type ?loc)
| x -> error_bad_inductive_type ?loc
@@ -1550,12 +1699,12 @@ let intern_ind_pattern genv scopes pat =
let merge_impargs l args =
let test x = function
- | (_, Some (_, y)) -> explicitation_eq x y
+ | (_, Some {v=y}) -> explicitation_eq x y
| _ -> false
in
List.fold_right (fun a l ->
match a with
- | (_,Some (_,(ExplByName id as x))) when
+ | (_, Some {v=ExplByName id as x}) when
List.exists (test x) args -> l
| _ -> a::l)
l args
@@ -1587,7 +1736,7 @@ let extract_explicit_arg imps args =
let (eargs,rargs) = aux l in
match e with
| None -> (eargs,a::rargs)
- | Some (loc,pos) ->
+ | Some {loc;v=pos} ->
let id = match pos with
| ExplByName id ->
if not (exists_implicit_name id imps) then
@@ -1626,8 +1775,8 @@ let internalize globalenv env pattern_mode (_, ntnvars as lvar) c =
in
apply_impargs c env imp subscopes l loc
- | CFix ((locid,iddef), dl) ->
- let lf = List.map (fun ((_, id),_,_,_,_) -> id) dl in
+ | CFix ({ CAst.loc = locid; v = iddef}, dl) ->
+ let lf = List.map (fun ({CAst.v = id},_,_,_,_) -> id) dl in
let dl = Array.of_list dl in
let n =
try List.index0 Id.equal iddef lf
@@ -1662,7 +1811,7 @@ let internalize globalenv env pattern_mode (_, ntnvars as lvar) c =
let (_,bli,tyi,_) = idl_temp.(i) in
let fix_args = (List.map (fun (na, bk, _, _) -> (build_impls bk na)) bli) in
push_name_env ntnvars (impls_type_list ~args:fix_args tyi)
- en (Loc.tag @@ Name name)) 0 env' lf in
+ en (CAst.make @@ Name name)) 0 env' lf in
(a,b,c,intern {env'' with tmp_scope = None} bd)) dl idl_temp in
DAst.make ?loc @@
GRec (GFix
@@ -1671,8 +1820,8 @@ let internalize globalenv env pattern_mode (_, ntnvars as lvar) c =
Array.map (fun (_,bl,_,_) -> bl) idl,
Array.map (fun (_,_,ty,_) -> ty) idl,
Array.map (fun (_,_,_,bd) -> bd) idl)
- | CCoFix ((locid,iddef), dl) ->
- let lf = List.map (fun ((_, id),_,_,_) -> id) dl in
+ | CCoFix ({ CAst.loc = locid; v = iddef }, dl) ->
+ let lf = List.map (fun ({CAst.v = id},_,_,_) -> id) dl in
let dl = Array.of_list dl in
let n =
try List.index0 Id.equal iddef lf
@@ -1680,7 +1829,7 @@ let internalize globalenv env pattern_mode (_, ntnvars as lvar) c =
raise (InternalizationError (locid,UnboundFixName (true,iddef)))
in
let idl_tmp = Array.map
- (fun ((loc,id),bl,ty,_) ->
+ (fun ({ CAst.loc; v = id },bl,ty,_) ->
let (env',rbl) = List.fold_left intern_local_binder (env,[]) bl in
(List.rev (List.map glob_local_binder_of_extended rbl),
intern_type env' ty,env')) dl in
@@ -1689,7 +1838,7 @@ let internalize globalenv env pattern_mode (_, ntnvars as lvar) c =
let (bli,tyi,_) = idl_tmp.(i) in
let cofix_args = List.map (fun (na, bk, _, _) -> (build_impls bk na)) bli in
push_name_env ntnvars (impls_type_list ~args:cofix_args tyi)
- en (Loc.tag @@ Name name)) 0 env' lf in
+ en (CAst.make @@ Name name)) 0 env' lf in
(b,c,intern {env'' with tmp_scope = None} bd)) dl idl_tmp in
DAst.make ?loc @@
GRec (GCoFix n,
@@ -1697,24 +1846,25 @@ let internalize globalenv env pattern_mode (_, ntnvars as lvar) c =
Array.map (fun (bl,_,_) -> bl) idl,
Array.map (fun (_,ty,_) -> ty) idl,
Array.map (fun (_,_,bd) -> bd) idl)
- | CProdN ([],c2) ->
- intern_type env c2
- | CProdN ((nal,bk,ty)::bll,c2) ->
- iterate_prod ?loc env bk ty (CAst.make ?loc @@ CProdN (bll, c2)) nal
+ | CProdN (bl,c2) ->
+ let (env',bl) = List.fold_left intern_local_binder (env,[]) bl in
+ expand_binders ?loc mkGProd bl (intern_type env' c2)
| CLambdaN ([],c2) ->
+ (* Such a term is built sometimes: it should not change scope *)
intern env c2
- | CLambdaN ((nal,bk,ty)::bll,c2) ->
- iterate_lam loc (reset_tmp_scope env) bk ty (CAst.make ?loc @@ CLambdaN (bll, c2)) nal
+ | CLambdaN (bl,c2) ->
+ let (env',bl) = List.fold_left intern_local_binder (reset_tmp_scope env,[]) bl in
+ expand_binders ?loc mkGLambda bl (intern env' c2)
| CLetIn (na,c1,t,c2) ->
let inc1 = intern (reset_tmp_scope env) c1 in
let int = Option.map (intern_type env) t in
DAst.make ?loc @@
- GLetIn (snd na, inc1, int,
+ GLetIn (na.CAst.v, inc1, int,
intern (push_name_env ntnvars (impls_term_list inc1) env na) c2)
- | CNotation ("- _", ([a],[],[])) when is_non_zero a ->
+ | CNotation ("- _", ([a],[],[],[])) when is_non_zero a ->
let p = match a.CAst.v with CPrim (Numeral (p, _)) -> p | _ -> assert false in
intern env (CAst.make ?loc @@ CPrim (Numeral (p,false)))
- | CNotation ("( _ )",([a],[],[])) -> intern env a
+ | CNotation ("( _ )",([a],[],[],[])) -> intern env a
| CNotation (ntn,args) ->
intern_notation intern env ntnvars loc ntn args
| CGeneralization (b,a,c) ->
@@ -1746,8 +1896,8 @@ let internalize globalenv env pattern_mode (_, ntnvars as lvar) c =
| CRef (ref,us) ->
intern_applied_reference intern env
(Environ.named_context globalenv) lvar us args ref
- | CNotation (ntn,([],[],[])) ->
- let c = intern_notation intern env ntnvars loc ntn ([],[],[]) in
+ | CNotation (ntn,([],[],[],[])) ->
+ let c = intern_notation intern env ntnvars loc ntn ([],[],[],[]) in
let x, impl, scopes, l = find_appl_head_data c in
(x,impl,scopes,l), args
| _ -> (intern env f,[],[],[]), args in
@@ -1772,7 +1922,7 @@ let internalize globalenv env pattern_mode (_, ntnvars as lvar) c =
| CCases (sty, rtnpo, tms, eqns) ->
let as_in_vars = List.fold_left (fun acc (_,na,inb) ->
Option.fold_left (fun acc tt -> Id.Set.union (ids_of_cases_indtype tt) acc)
- (Option.fold_left (fun acc (_,y) -> Name.fold_right Id.Set.add y acc) acc na)
+ (Option.fold_left (fun acc { CAst.v = y } -> Name.fold_right Id.Set.add y acc) acc na)
inb) Id.Set.empty tms in
(* as, in & return vars *)
let forbidden_vars = Option.cata free_vars_of_constr_expr as_in_vars rtnpo in
@@ -1782,7 +1932,7 @@ let internalize globalenv env pattern_mode (_, ntnvars as lvar) c =
(tm,ind)::inds, Option.fold_right Id.Set.add extra_id ex_ids, List.rev_append match_td matchs)
tms ([],Id.Set.empty,[]) in
let env' = Id.Set.fold
- (fun var bli -> push_name_env ntnvars (Variable,[],[],[]) bli (Loc.tag @@ Name var))
+ (fun var bli -> push_name_env ntnvars (Variable,[],[],[]) bli (CAst.make @@ Name var))
(Id.Set.union ex_ids as_in_vars) (reset_hidden_inductive_implicit_test env) in
(* PatVars before a real pattern do not need to be matched *)
let stripped_match_from_in =
@@ -1822,17 +1972,17 @@ let internalize globalenv env pattern_mode (_, ntnvars as lvar) c =
let ((b',(na',_)),_,_) = intern_case_item env' Id.Set.empty (b,na,None) in
let p' = Option.map (fun u ->
let env'' = push_name_env ntnvars (Variable,[],[],[]) (reset_hidden_inductive_implicit_test env')
- (Loc.tag na') in
+ (CAst.make na') in
intern_type env'' u) po in
DAst.make ?loc @@
- GLetTuple (List.map snd nal, (na', p'), b',
+ GLetTuple (List.map (fun { CAst.v } -> v) nal, (na', p'), b',
intern (List.fold_left (push_name_env ntnvars (Variable,[],[],[])) (reset_hidden_inductive_implicit_test env) nal) c)
| CIf (c, (na,po), b1, b2) ->
let env' = reset_tmp_scope env in
let ((c',(na',_)),_,_) = intern_case_item env' Id.Set.empty (c,na,None) in (* no "in" no match to ad too *)
let p' = Option.map (fun p ->
let env'' = push_name_env ntnvars (Variable,[],[],[]) (reset_hidden_inductive_implicit_test env)
- (Loc.tag na') in
+ (CAst.make na') in
intern_type env'' p) po in
DAst.make ?loc @@
GIf (c', (na', p'), intern env b1, intern env b2)
@@ -1849,6 +1999,8 @@ let internalize globalenv env pattern_mode (_, ntnvars as lvar) c =
| None -> None
| Some gen ->
let (ltacvars, ntnvars) = lvar in
+ (* Preventively declare notation variables in ltac as non-bindings *)
+ Id.Map.iter (fun x (used_as_binder,_,_) -> used_as_binder := false) ntnvars;
let ntnvars = Id.Map.domain ntnvars in
let extra = ltacvars.ltac_extra in
let lvars = Id.Set.union ltacvars.ltac_bound ltacvars.ltac_vars in
@@ -1899,7 +2051,7 @@ let internalize globalenv env pattern_mode (_, ntnvars as lvar) c =
(* Expands a multiple pattern into a disjunction of multiple patterns *)
and intern_multiple_pattern env n pl =
- let idsl_pll = List.map (intern_cases_pattern globalenv (None,env.scopes) empty_alias) pl in
+ let idsl_pll = List.map (intern_cases_pattern globalenv ntnvars (None,env.scopes) empty_alias) pl in
let loc = loc_of_multiple_pattern pl in
check_number_of_pattern loc n pl;
product_of_cases_patterns empty_alias idsl_pll
@@ -1914,9 +2066,10 @@ let internalize globalenv env pattern_mode (_, ntnvars as lvar) c =
(ids,List.flatten mpl')
(* Expands a pattern-matching clause [lhs => rhs] *)
- and intern_eqn n env (loc,(lhs,rhs)) =
+ and intern_eqn n env {loc;v=(lhs,rhs)} =
let eqn_ids,pll = intern_disjunctive_multiple_pattern env loc n lhs in
(* Linearity implies the order in ids is irrelevant *)
+ let eqn_ids = List.map (fun x -> x.v) eqn_ids in
check_linearity lhs eqn_ids;
let env_ids = List.fold_right Id.Set.add eqn_ids env.ids in
List.map (fun (asubst,pl) ->
@@ -1931,14 +2084,14 @@ let internalize globalenv env pattern_mode (_, ntnvars as lvar) c =
let extra_id,na =
let loc = tm'.CAst.loc in
match DAst.get tm', na with
- | GVar id, None when not (Id.Map.mem id (snd lvar)) -> Some id,(loc,Name id)
- | GRef (VarRef id, _), None -> Some id,(loc,Name id)
- | _, None -> None,(Loc.tag Anonymous)
- | _, Some (loc,na) -> None,(loc,na) in
+ | GVar id, None when not (Id.Map.mem id (snd lvar)) -> Some id, CAst.make ?loc @@ Name id
+ | GRef (VarRef id, _), None -> Some id, CAst.make ?loc @@ Name id
+ | _, None -> None, CAst.make Anonymous
+ | _, Some ({ CAst.loc; v = na } as lna) -> None, lna in
(* the "in" part *)
let match_td,typ = match t with
| Some t ->
- let with_letin,(ind,l) = intern_ind_pattern globalenv (None,env.scopes) t in
+ let with_letin,(ind,l) = intern_ind_pattern globalenv ntnvars (None,env.scopes) t in
let (mib,mip) = Inductive.lookup_mind_specif globalenv ind in
let nparams = (List.length (mib.Declarations.mind_params_ctxt)) in
(* for "in Vect n", we answer (["n","n"],[(loc,"n")])
@@ -1950,8 +2103,8 @@ let internalize globalenv env pattern_mode (_, ntnvars as lvar) c =
let (match_to_do,nal) =
let rec canonize_args case_rel_ctxt arg_pats forbidden_names match_acc var_acc =
let add_name l = function
- | _,Anonymous -> l
- | loc,(Name y as x) -> (y, DAst.make ?loc @@ PatVar x) :: l in
+ | { CAst.v = Anonymous } -> l
+ | { CAst.loc; v = (Name y as x) } -> (y, DAst.make ?loc @@ PatVar x) :: l in
match case_rel_ctxt,arg_pats with
(* LetIn in the rel_context *)
| LocalDef _ :: t, l when not with_letin ->
@@ -1963,7 +2116,7 @@ let internalize globalenv env pattern_mode (_, ntnvars as lvar) c =
| PatVar x ->
let loc = c.CAst.loc in
canonize_args t tt forbidden_names
- (add_name match_acc (loc,x)) ((loc,x)::var_acc)
+ (add_name match_acc CAst.(make ?loc x)) ((loc,x)::var_acc)
| _ ->
let fresh =
Namegen.next_name_away_with_default_using_types "iV" cano_name forbidden_names (EConstr.of_constr ty) in
@@ -1977,15 +2130,7 @@ let internalize globalenv env pattern_mode (_, ntnvars as lvar) c =
match_to_do, Some (cases_pattern_expr_loc t,(ind,List.rev_map snd nal))
| None ->
[], None in
- (tm',(snd na,typ)), extra_id, match_td
-
- and iterate_prod ?loc env bk ty body nal =
- let env, bl = intern_assumption intern ntnvars env nal bk ty in
- it_mkGProd ?loc bl (intern_type env body)
-
- and iterate_lam loc env bk ty body nal =
- let env, bl = intern_assumption intern ntnvars env nal bk ty in
- it_mkGLambda ?loc bl (intern env body)
+ (tm',(na.CAst.v,typ)), extra_id, match_td
and intern_impargs c env l subscopes args =
let eargs, rargs = extract_explicit_arg l args in
@@ -2027,7 +2172,6 @@ let internalize globalenv env pattern_mode (_, ntnvars as lvar) c =
in aux 1 l subscopes eargs rargs
and apply_impargs c env imp subscopes l loc =
- let l : (Constrexpr.constr_expr * Constrexpr.explicitation Loc.located option) list = l in
let imp = select_impargs_size (List.length (List.filter (fun (_,x) -> x == None) l)) imp in
let l = intern_impargs c env imp subscopes l in
smart_gapp c loc l
@@ -2089,7 +2233,7 @@ let intern_type env c = intern_gen IsType env c
let intern_pattern globalenv patt =
try
- intern_cases_pattern globalenv (None,[]) empty_alias patt
+ intern_cases_pattern globalenv Id.Map.empty (None,[]) empty_alias patt
with
InternalizationError (loc,e) ->
user_err ?loc ~hdr:"internalize" (explain_internalization_error e)
@@ -2160,7 +2304,8 @@ let intern_constr_pattern env ?(as_type=false) ?(ltacvars=empty_ltac_sign) c =
let interp_notation_constr env ?(impls=empty_internalization_env) nenv a =
(* [vl] is intended to remember the scope of the free variables of [a] *)
- let vl = Id.Map.map (fun typ -> (ref true, ref None, typ)) nenv.ninterp_var_type in
+ let vl = Id.Map.map (fun typ -> (ref false, ref None, typ)) nenv.ninterp_var_type in
+ let impls = Id.Map.fold (fun id _ impls -> Id.Map.remove id impls) nenv.ninterp_var_type impls in
let c = internalize (Global.env()) {ids = extract_ids env; unb = false;
tmp_scope = None; scopes = []; impls = impls}
false (empty_ltac_sign, vl) a in
@@ -2169,8 +2314,9 @@ let interp_notation_constr env ?(impls=empty_internalization_env) nenv a =
(* Splits variables into those that are binding, bound, or both *)
(* binding and bound *)
let out_scope = function None -> None,[] | Some (a,l) -> a,l in
- let vars = Id.Map.map (fun (isonlybinding, sc, typ) ->
- (!isonlybinding, out_scope !sc, typ)) vl in
+ let unused = match reversible with NonInjective ids -> ids | _ -> [] in
+ let vars = Id.Map.mapi (fun id (used_as_binder, sc, typ) ->
+ (!used_as_binder && not (List.mem_f Id.equal id unused), out_scope !sc)) vl in
(* Returns [a] and the ordered list of variables with their scopes *)
vars, a, reversible
diff --git a/interp/constrintern.mli b/interp/constrintern.mli
index 632b423b0..7411fb84b 100644
--- a/interp/constrintern.mli
+++ b/interp/constrintern.mli
@@ -87,7 +87,7 @@ val intern_gen : typing_constraint -> env ->
constr_expr -> glob_constr
val intern_pattern : env -> cases_pattern_expr ->
- Id.t list * (Id.t Id.Map.t * cases_pattern) list
+ lident list * (Id.t Id.Map.t * cases_pattern) list
val intern_context : bool -> env -> internalization_env -> local_binder_expr list -> internalization_env * glob_decl list
@@ -184,8 +184,7 @@ val global_reference_in_absolute_module : DirPath.t -> Id.t -> Globnames.global_
guaranteed to have the same domain as the input one. *)
val interp_notation_constr : env -> ?impls:internalization_env ->
notation_interp_env -> constr_expr ->
- (bool * subscopes * notation_var_internalization_type) Id.Map.t *
- notation_constr * reversibility_flag
+ (bool * subscopes) Id.Map.t * notation_constr * reversibility_status
(** Globalization options *)
val parsing_explicit : bool ref
diff --git a/interp/declare.ml b/interp/declare.ml
index 72cdabfd2..dfa84f278 100644
--- a/interp/declare.ml
+++ b/interp/declare.ml
@@ -561,7 +561,7 @@ let do_universe poly l =
(str"Cannot declare polymorphic universes outside sections")
in
let l =
- List.map (fun (l, id) ->
+ List.map (fun {CAst.v=id} ->
let lev = Universes.new_univ_id () in
(id, lev)) l
in
diff --git a/interp/declare.mli b/interp/declare.mli
index f368d164e..9bec32d29 100644
--- a/interp/declare.mli
+++ b/interp/declare.mli
@@ -85,6 +85,6 @@ val declare_univ_binders : Globnames.global_reference -> Universes.universe_bind
val declare_universe_context : polymorphic -> Univ.ContextSet.t -> unit
-val do_universe : polymorphic -> Id.t Loc.located list -> unit
+val do_universe : polymorphic -> Misctypes.lident list -> unit
val do_constraint : polymorphic -> (Misctypes.glob_level * Univ.constraint_type * Misctypes.glob_level) list ->
unit
diff --git a/interp/dumpglob.ml b/interp/dumpglob.ml
index d7962e29a..e439db2b2 100644
--- a/interp/dumpglob.ml
+++ b/interp/dumpglob.ml
@@ -249,12 +249,12 @@ let dump_def ?loc ty secpath id = Option.iter (fun loc ->
dump_string (Printf.sprintf "%s %d:%d %s %s\n" ty bl el secpath id)
) loc
-let dump_definition (loc, id) sec s =
+let dump_definition {CAst.loc;v=id} sec s =
dump_def ?loc s (Names.DirPath.to_string (Lib.current_dirpath sec)) (Names.Id.to_string id)
-let dump_constraint (((loc, n),_), _, _) sec ty =
+let dump_constraint (({ CAst.loc; v = n },_), _, _) sec ty =
match n with
- | Names.Name id -> dump_definition (loc, id) sec ty
+ | Names.Name id -> dump_definition CAst.(make ?loc id) sec ty
| Names.Anonymous -> ()
let dump_moddef ?loc mp ty =
diff --git a/interp/dumpglob.mli b/interp/dumpglob.mli
index f3ad50f28..c779e860f 100644
--- a/interp/dumpglob.mli
+++ b/interp/dumpglob.mli
@@ -25,7 +25,7 @@ val continue : unit -> unit
val add_glob : ?loc:Loc.t -> Globnames.global_reference -> unit
val add_glob_kn : ?loc:Loc.t -> Names.KerName.t -> unit
-val dump_definition : Names.Id.t Loc.located -> bool -> string -> unit
+val dump_definition : Misctypes.lident -> bool -> string -> unit
val dump_moddef : ?loc:Loc.t -> Names.ModPath.t -> string -> unit
val dump_modref : ?loc:Loc.t -> Names.ModPath.t -> string -> unit
val dump_reference : ?loc:Loc.t -> string -> string -> string -> unit
diff --git a/interp/implicit_quantifiers.ml b/interp/implicit_quantifiers.ml
index 519f2480b..326969b67 100644
--- a/interp/implicit_quantifiers.ml
+++ b/interp/implicit_quantifiers.ml
@@ -26,7 +26,7 @@ module RelDecl = Context.Rel.Declaration
let generalizable_table = Summary.ref Id.Pred.empty ~name:"generalizable-ident"
-let declare_generalizable_ident table (loc,id) =
+let declare_generalizable_ident table {CAst.loc;v=id} =
if not (Id.equal id (root_of_id id)) then
user_err ?loc ~hdr:"declare_generalizable_ident"
((Id.print id ++ str
@@ -49,7 +49,7 @@ let cache_generalizable_type (_,(local,cmd)) =
let load_generalizable_type _ (_,(local,cmd)) =
generalizable_table := add_generalizable cmd !generalizable_table
-let in_generalizable : bool * Id.t Loc.located list option -> obj =
+let in_generalizable : bool * Misctypes.lident list option -> obj =
declare_object {(default_object "GENERALIZED-IDENT") with
load_function = load_generalizable_type;
cache_function = cache_generalizable_type;
@@ -93,13 +93,13 @@ let free_vars_of_constr_expr c ?(bound=Id.Set.empty) l =
in
let rec aux bdvars l c = match CAst.(c.v) with
| CRef (Ident (loc,id),_) -> found loc id bdvars l
- | CNotation ("{ _ : _ | _ }", ({ CAst.v = CRef (Ident (_, id),_) } :: _, [], [])) when not (Id.Set.mem id bdvars) ->
- Constrexpr_ops.fold_constr_expr_with_binders (fun a l -> Id.Set.add a l) aux (Id.Set.add id bdvars) l c
+ | CNotation ("{ _ : _ | _ }", ({ CAst.v = CRef (Ident (_, id),_) } :: _, [], [], [])) when not (Id.Set.mem id bdvars) ->
+ Constrexpr_ops.fold_constr_expr_with_binders (fun a l -> Id.Set.add a l) aux (Id.Set.add id bdvars) l c
| _ -> Constrexpr_ops.fold_constr_expr_with_binders (fun a l -> Id.Set.add a l) aux bdvars l c
in aux bound l c
let ids_of_names l =
- List.fold_left (fun acc x -> match snd x with Name na -> na :: acc | Anonymous -> acc) [] l
+ List.fold_left (fun acc x -> match x.CAst.v with Name na -> na :: acc | Anonymous -> acc) [] l
let free_vars_of_binders ?(bound=Id.Set.empty) l (binders : local_binder_expr list) =
let rec aux bdvars l c = match c with
@@ -109,7 +109,7 @@ let free_vars_of_binders ?(bound=Id.Set.empty) l (binders : local_binder_expr li
aux (Id.Set.union (ids_of_list bound) bdvars) l' tl
| ((CLocalDef (n, c, t)) :: tl) ->
- let bound = match snd n with Anonymous -> [] | Name n -> [n] in
+ let bound = match n.CAst.v with Anonymous -> [] | Name n -> [n] in
let l' = free_vars_of_constr_expr c ~bound:bdvars l in
let l'' = Option.fold_left (fun l t -> free_vars_of_constr_expr t ~bound:bdvars l) l' t in
aux (Id.Set.union (ids_of_list bound) bdvars) l'' tl
@@ -123,13 +123,13 @@ let generalizable_vars_of_glob_constr ?(bound=Id.Set.empty) ?(allowed=Id.Set.emp
| GVar id ->
let loc = c.CAst.loc in
if is_freevar bound (Global.env ()) id then
- if Id.List.mem_assoc_sym id vs then vs
- else (Loc.tag ?loc id) :: vs
+ if List.exists (fun {CAst.v} -> Id.equal v id) vs then vs
+ else CAst.(make ?loc id) :: vs
else vs
| _ -> Glob_ops.fold_glob_constr_with_binders Id.Set.add vars bound vs c
in fun rt ->
let vars = List.rev (vars bound [] rt) in
- List.iter (fun (loc, id) ->
+ List.iter (fun {CAst.loc;v=id} ->
if not (Id.Set.mem id allowed || find_generalizable_ident id) then
ungeneralizable loc id) vars;
vars
@@ -146,7 +146,7 @@ let combine_params avoid fn applied needed =
let named, applied =
List.partition
(function
- (t, Some (loc, ExplByName id)) ->
+ (t, Some {CAst.loc;v=ExplByName id}) ->
let is_id (_, decl) = match RelDecl.get_name decl with
| Name id' -> Id.equal id id'
| Anonymous -> false
@@ -157,7 +157,7 @@ let combine_params avoid fn applied needed =
| _ -> false) applied
in
let named = List.map
- (fun x -> match x with (t, Some (loc, ExplByName id)) -> id, t | _ -> assert false)
+ (fun x -> match x with (t, Some {CAst.loc;v=ExplByName id}) -> id, t | _ -> assert false)
named
in
let is_unset (_, decl) = match decl with
@@ -198,23 +198,23 @@ let destClassApp cl =
let open CAst in
let loc = cl.loc in
match cl.v with
- | CApp ((None, { v = CRef (ref, inst) }), l) -> Loc.tag ?loc (ref, List.map fst l, inst)
- | CAppExpl ((None, ref, inst), l) -> Loc.tag ?loc (ref, l, inst)
- | CRef (ref, inst) -> Loc.tag ?loc:(loc_of_reference ref) (ref, [], inst)
+ | CApp ((None, { v = CRef (ref, inst) }), l) -> CAst.make ?loc (ref, List.map fst l, inst)
+ | CAppExpl ((None, ref, inst), l) -> CAst.make ?loc (ref, l, inst)
+ | CRef (ref, inst) -> CAst.make ?loc:(loc_of_reference ref) (ref, [], inst)
| _ -> raise Not_found
let destClassAppExpl cl =
let open CAst in
let loc = cl.loc in
match cl.v with
- | CApp ((None, { v = CRef (ref, inst) } ), l) -> Loc.tag ?loc (ref, l, inst)
- | CRef (ref, inst) -> Loc.tag ?loc:(loc_of_reference ref) (ref, [], inst)
+ | CApp ((None, { v = CRef (ref, inst) } ), l) -> CAst.make ?loc (ref, l, inst)
+ | CRef (ref, inst) -> CAst.make ?loc:(loc_of_reference ref) (ref, [], inst)
| _ -> raise Not_found
let implicit_application env ?(allow_partial=true) f ty =
let is_class =
try
- let (_, (r, _, _) as clapp) = destClassAppExpl ty in
+ let ({CAst.v=(r, _, _)} as clapp) = destClassAppExpl ty in
let (loc, qid) = qualid_of_reference r in
let gr = Nametab.locate qid in
if Typeclasses.is_class gr then Some (clapp, gr) else None
@@ -222,7 +222,7 @@ let implicit_application env ?(allow_partial=true) f ty =
in
match is_class with
| None -> ty, env
- | Some ((loc, (id, par, inst)), gr) ->
+ | Some ({CAst.loc;v=(id, par, inst)}, gr) ->
let avoid = Id.Set.union env (ids_of_list (free_vars_of_constr_expr ty ~bound:env [])) in
let c, avoid =
let c = class_info gr in
diff --git a/interp/implicit_quantifiers.mli b/interp/implicit_quantifiers.mli
index bfe73160b..625e12003 100644
--- a/interp/implicit_quantifiers.mli
+++ b/interp/implicit_quantifiers.mli
@@ -6,18 +6,17 @@
(* * GNU Lesser General Public License Version 2.1 *)
(************************************************************************)
-open Loc
open Names
open Glob_term
open Constrexpr
open Libnames
open Globnames
-val declare_generalizable : Vernacexpr.locality_flag -> (Id.t located) list option -> unit
+val declare_generalizable : Vernacexpr.locality_flag -> Misctypes.lident list option -> unit
val ids_of_list : Id.t list -> Id.Set.t
-val destClassApp : constr_expr -> (reference * constr_expr list * instance_expr option) located
-val destClassAppExpl : constr_expr -> (reference * (constr_expr * explicitation located option) list * instance_expr option) located
+val destClassApp : constr_expr -> (reference * constr_expr list * instance_expr option) CAst.t
+val destClassAppExpl : constr_expr -> (reference * (constr_expr * explicitation CAst.t option) list * instance_expr option) CAst.t
(** Fragile, should be used only for construction a set of identifiers to avoid *)
@@ -31,7 +30,7 @@ val free_vars_of_binders :
order with the location of their first occurrence *)
val generalizable_vars_of_glob_constr : ?bound:Id.Set.t -> ?allowed:Id.Set.t ->
- glob_constr -> Id.t located list
+ glob_constr -> Misctypes.lident list
val make_fresh : Id.Set.t -> Environ.env -> Id.t -> Id.t
diff --git a/interp/notation.ml b/interp/notation.ml
index 94ce2a6c8..ea7ef21b1 100644
--- a/interp/notation.ml
+++ b/interp/notation.ml
@@ -82,18 +82,35 @@ let parenRelation_eq t1 t2 = match t1, t2 with
| Prec l1, Prec l2 -> Int.equal l1 l2
| _ -> false
-let notation_var_internalization_type_eq v1 v2 = match v1, v2 with
-| NtnInternTypeConstr, NtnInternTypeConstr -> true
-| NtnInternTypeBinder, NtnInternTypeBinder -> true
-| NtnInternTypeIdent, NtnInternTypeIdent -> true
-| (NtnInternTypeConstr | NtnInternTypeBinder | NtnInternTypeIdent), _ -> false
-
-let level_eq (l1, t1, u1) (l2, t2, u2) =
- let tolerability_eq (i1, r1) (i2, r2) =
- Int.equal i1 i2 && parenRelation_eq r1 r2
- in
+open Extend
+
+let production_level_eq l1 l2 = true (* (l1 = l2) *)
+
+let production_position_eq pp1 pp2 = true (* pp1 = pp2 *) (* match pp1, pp2 with
+| NextLevel, NextLevel -> true
+| NumLevel n1, NumLevel n2 -> Int.equal n1 n2
+| (NextLevel | NumLevel _), _ -> false *)
+
+let constr_entry_key_eq eq v1 v2 = match v1, v2 with
+| ETName, ETName -> true
+| ETReference, ETReference -> true
+| ETBigint, ETBigint -> true
+| ETBinder b1, ETBinder b2 -> b1 == b2
+| ETConstr lev1, ETConstr lev2 -> eq lev1 lev2
+| ETConstrAsBinder (bk1,lev1), ETConstrAsBinder (bk2,lev2) -> eq lev1 lev2 && bk1 = bk2
+| ETPattern (b1,n1), ETPattern (b2,n2) -> b1 = b2 && Option.equal Int.equal n1 n2
+| ETOther (s1,s1'), ETOther (s2,s2') -> String.equal s1 s2 && String.equal s1' s2'
+| (ETName | ETReference | ETBigint | ETBinder _ | ETConstr _ | ETPattern _ | ETOther _ | ETConstrAsBinder _), _ -> false
+
+let level_eq_gen strict (l1, t1, u1) (l2, t2, u2) =
+ let tolerability_eq (i1, r1) (i2, r2) = Int.equal i1 i2 && parenRelation_eq r1 r2 in
+ let prod_eq (l1,pp1) (l2,pp2) =
+ if strict then production_level_eq l1 l2 && production_position_eq pp1 pp2
+ else production_level_eq l1 l2 in
Int.equal l1 l2 && List.equal tolerability_eq t1 t2
- && List.equal notation_var_internalization_type_eq u1 u2
+ && List.equal (constr_entry_key_eq prod_eq) u1 u2
+
+let level_eq = level_eq_gen false
let declare_scope scope =
try let _ = String.Map.find scope !scope_map in ()
@@ -292,7 +309,7 @@ let cases_pattern_key c = match DAst.get c with
let notation_constr_key = function (* Rem: NApp(NRef ref,[]) stands for @ref *)
| NApp (NRef ref,args) -> RefKey(canonical_gr ref), Some (List.length args)
| NList (_,_,NApp (NRef ref,args),_,_)
- | NBinderList (_,_,NApp (NRef ref,args),_) ->
+ | NBinderList (_,_,NApp (NRef ref,args),_,_) ->
RefKey (canonical_gr ref), Some (List.length args)
| NRef ref -> RefKey(canonical_gr ref), None
| NApp (_,args) -> Oth, Some (List.length args)
@@ -609,12 +626,18 @@ let availability_of_prim_token n printer_scope local_scopes =
let pair_eq f g (x1, y1) (x2, y2) = f x1 x2 && g y1 y2
+let notation_binder_source_eq s1 s2 = match s1, s2 with
+| NtnParsedAsIdent, NtnParsedAsIdent -> true
+| NtnParsedAsPattern b1, NtnParsedAsPattern b2 -> b1 = b2
+| NtnBinderParsedAsConstr bk1, NtnBinderParsedAsConstr bk2 -> bk1 = bk2
+| (NtnParsedAsIdent | NtnParsedAsPattern _ | NtnBinderParsedAsConstr _), _ -> false
+
let ntpe_eq t1 t2 = match t1, t2 with
| NtnTypeConstr, NtnTypeConstr -> true
-| NtnTypeOnlyBinder, NtnTypeOnlyBinder -> true
+| NtnTypeBinder s1, NtnTypeBinder s2 -> notation_binder_source_eq s1 s2
| NtnTypeConstrList, NtnTypeConstrList -> true
| NtnTypeBinderList, NtnTypeBinderList -> true
-| (NtnTypeConstr | NtnTypeOnlyBinder | NtnTypeConstrList | NtnTypeBinderList), _ -> false
+| (NtnTypeConstr | NtnTypeBinder _ | NtnTypeConstrList | NtnTypeBinderList), _ -> false
let var_attributes_eq (_, (sc1, tp1)) (_, (sc2, tp2)) =
pair_eq (Option.equal String.equal) (List.equal String.equal) sc1 sc2 &&
@@ -926,8 +949,63 @@ let factorize_entries = function
(ntn,[c],[]) l in
(ntn,l_of_ntn)::rest
+type symbol_token = WhiteSpace of int | String of string
+
+let split_notation_string str =
+ let push_token beg i l =
+ if Int.equal beg i then l else
+ let s = String.sub str beg (i - beg) in
+ String s :: l
+ in
+ let push_whitespace beg i l =
+ if Int.equal beg i then l else WhiteSpace (i-beg) :: l
+ in
+ let rec loop beg i =
+ if i < String.length str then
+ if str.[i] == ' ' then
+ push_token beg i (loop_on_whitespace (i+1) (i+1))
+ else
+ loop beg (i+1)
+ else
+ push_token beg i []
+ and loop_on_whitespace beg i =
+ if i < String.length str then
+ if str.[i] != ' ' then
+ push_whitespace beg i (loop i (i+1))
+ else
+ loop_on_whitespace beg (i+1)
+ else
+ push_whitespace beg i []
+ in
+ loop 0 0
+
+let rec raw_analyze_notation_tokens = function
+ | [] -> []
+ | String ".." :: sl -> NonTerminal Notation_ops.ldots_var :: raw_analyze_notation_tokens sl
+ | String "_" :: _ -> user_err Pp.(str "_ must be quoted.")
+ | String x :: sl when Id.is_valid x ->
+ NonTerminal (Names.Id.of_string x) :: raw_analyze_notation_tokens sl
+ | String s :: sl ->
+ Terminal (String.drop_simple_quotes s) :: raw_analyze_notation_tokens sl
+ | WhiteSpace n :: sl ->
+ Break n :: raw_analyze_notation_tokens sl
+
+let decompose_raw_notation ntn = raw_analyze_notation_tokens (split_notation_string ntn)
+
+let possible_notations ntn =
+ (* We collect the possible interpretations of a notation string depending on whether it is
+ in "x 'U' y" or "_ U _" format *)
+ let toks = split_notation_string ntn in
+ if List.exists (function String "_" -> true | _ -> false) toks then
+ (* Only "_ U _" format *)
+ [ntn]
+ else
+ let ntn' = make_notation_key (raw_analyze_notation_tokens toks) in
+ if String.equal ntn ntn' then (* Only symbols *) [ntn] else [ntn;ntn']
+
let browse_notation strict ntn map =
- let find ntn' =
+ let ntns = possible_notations ntn in
+ let find ntn' ntn =
if String.contains ntn ' ' then String.equal ntn ntn'
else
let toks = decompose_notation_key ntn' in
@@ -940,7 +1018,7 @@ let browse_notation strict ntn map =
String.Map.fold
(fun scope_name sc ->
String.Map.fold (fun ntn { not_interp = (_, r); not_location = df } l ->
- if find ntn then (ntn,(scope_name,r,df))::l else l) sc.notations)
+ if List.exists (find ntn) ntns then (ntn,(scope_name,r,df))::l else l) sc.notations)
map [] in
List.sort (fun x y -> String.compare (fst x) (fst y)) l
diff --git a/interp/notation.mli b/interp/notation.mli
index 7d055571c..a4c79d6d3 100644
--- a/interp/notation.mli
+++ b/interp/notation.mli
@@ -176,16 +176,20 @@ val scope_class_of_class : Classops.cl_typ -> scope_class
(** Building notation key *)
type symbol =
- | Terminal of string
- | NonTerminal of Id.t
- | SProdList of Id.t * symbol list
- | Break of int
+ | Terminal of string (* an expression including symbols or a simply-quoted ident, e.g. "'U'" or "!" *)
+ | NonTerminal of Id.t (* an identifier "x" *)
+ | SProdList of Id.t * symbol list (* an expression "x sep .. sep y", remembering x (or y) and sep *)
+ | Break of int (* a sequence of blanks > 1, e.g. " " *)
val symbol_eq : symbol -> symbol -> bool
+(** Make/decompose a notation of the form "_ U _" *)
val make_notation_key : symbol list -> notation
val decompose_notation_key : notation -> symbol list
+(** Decompose a notation of the form "a 'U' b" *)
+val decompose_raw_notation : string -> symbol list
+
(** Prints scopes (expects a pure aconstr printer) *)
val pr_scope_class : scope_class -> Pp.t
val pr_scope : (glob_constr -> Pp.t) -> scope_name -> Pp.t
diff --git a/interp/notation_ops.ml b/interp/notation_ops.ml
index 326d05cba..c65f4785e 100644
--- a/interp/notation_ops.ml
+++ b/interp/notation_ops.ml
@@ -42,9 +42,9 @@ let rec eq_notation_constr (vars1,vars2 as vars) t1 t2 = match t1, t2 with
Name.equal na1 na2 && (eq_notation_constr vars) t1 t2 && (eq_notation_constr vars) u1 u2
| NProd (na1, t1, u1), NProd (na2, t2, u2) ->
Name.equal na1 na2 && (eq_notation_constr vars) t1 t2 && (eq_notation_constr vars) u1 u2
-| NBinderList (i1, j1, t1, u1), NBinderList (i2, j2, t2, u2) ->
+| NBinderList (i1, j1, t1, u1, b1), NBinderList (i2, j2, t2, u2, b2) ->
Id.equal i1 i2 && Id.equal j1 j2 && (eq_notation_constr vars) t1 t2 &&
- (eq_notation_constr vars) u1 u2
+ (eq_notation_constr vars) u1 u2 && b1 == b2
| NLetIn (na1, b1, t1, u1), NLetIn (na2, b2, t2, u2) ->
Name.equal na1 na2 && eq_notation_constr vars b1 b2 &&
Option.equal (eq_notation_constr vars) t1 t2 && (eq_notation_constr vars) u1 u2
@@ -101,13 +101,24 @@ let name_to_ident = function
let to_id g e id = let e,na = g e (Name id) in e,name_to_ident na
+let product_of_cases_patterns patl =
+ List.fold_right (fun patl restl ->
+ List.flatten (List.map (fun p -> List.map (fun rest -> p::rest) restl) patl))
+ patl [[]]
+
let rec cases_pattern_fold_map ?loc g e = DAst.with_val (function
| PatVar na ->
- let e',na' = g e na in e', DAst.make ?loc @@ PatVar na'
+ let e',disjpat,na' = g e na in
+ e', (match disjpat with
+ | None -> [DAst.make ?loc @@ PatVar na']
+ | Some ((_,disjpat),_) -> disjpat)
| PatCstr (cstr,patl,na) ->
- let e',na' = g e na in
+ let e',disjpat,na' = g e na in
+ if disjpat <> None then user_err (Pp.str "Unable to instantiate an \"as\" clause with a pattern.");
let e',patl' = List.fold_left_map (cases_pattern_fold_map ?loc g) e patl in
- e', DAst.make ?loc @@ PatCstr (cstr,patl',na')
+ (* Distribute outwards the inner disjunctive patterns *)
+ let disjpatl' = product_of_cases_patterns patl' in
+ e', List.map (fun patl' -> DAst.make ?loc @@ PatCstr (cstr,patl',na')) disjpatl'
)
let subst_binder_type_vars l = function
@@ -136,6 +147,16 @@ let rec subst_glob_vars l gc = DAst.map (function
let ldots_var = Id.of_string ".."
+let protect g e na =
+ let e',disjpat,na = g e na in
+ if disjpat <> None then user_err (Pp.str "Unsupported substitution of an arbitrary pattern.");
+ e',na
+
+let apply_cases_pattern ?loc ((ids,disjpat),id) c =
+ let tm = DAst.make ?loc (GVar id) in
+ let eqns = List.map (fun pat -> (loc,(ids,[pat],c))) disjpat in
+ DAst.make ?loc @@ GCases (LetPatternStyle, None, [tm,(Anonymous,None)], eqns)
+
let glob_constr_of_notation_constr_with_binders ?loc g f e nc =
let lt x = DAst.make ?loc x in lt @@ match nc with
| NVar id -> GVar id
@@ -146,46 +167,51 @@ let glob_constr_of_notation_constr_with_binders ?loc g f e nc =
let inner = lt @@ GApp (lt @@ GVar (ldots_var),[subst_glob_vars innerl it]) in
let outerl = (ldots_var,inner)::(if swap then [x, lt @@ GVar y] else []) in
DAst.get (subst_glob_vars outerl it)
- | NBinderList (x,y,iter,tail) ->
+ | NBinderList (x,y,iter,tail,swap) ->
let t = f e tail in let it = f e iter in
- let innerl = [(ldots_var,t);(x, lt @@ GVar y)] in
+ let innerl = (ldots_var,t)::(if swap then [] else [x, lt @@ GVar y]) in
let inner = lt @@ GApp (lt @@ GVar ldots_var,[subst_glob_vars innerl it]) in
- let outerl = [(ldots_var,inner)] in
+ let outerl = (ldots_var,inner)::(if swap then [x, lt @@ GVar y] else []) in
DAst.get (subst_glob_vars outerl it)
| NLambda (na,ty,c) ->
- let e',na = g e na in GLambda (na,Explicit,f e ty,f e' c)
+ let e',disjpat,na = g e na in GLambda (na,Explicit,f e ty,Option.fold_right (apply_cases_pattern ?loc) disjpat (f e' c))
| NProd (na,ty,c) ->
- let e',na = g e na in GProd (na,Explicit,f e ty,f e' c)
+ let e',disjpat,na = g e na in GProd (na,Explicit,f e ty,Option.fold_right (apply_cases_pattern ?loc) disjpat (f e' c))
| NLetIn (na,b,t,c) ->
- let e',na = g e na in GLetIn (na,f e b,Option.map (f e) t,f e' c)
+ let e',disjpat,na = g e na in
+ (match disjpat with
+ | None -> GLetIn (na,f e b,Option.map (f e) t,f e' c)
+ | Some disjpat -> DAst.get (apply_cases_pattern ?loc disjpat (f e' c)))
| NCases (sty,rtntypopt,tml,eqnl) ->
let e',tml' = List.fold_right (fun (tm,(na,t)) (e',tml') ->
let e',t' = match t with
| None -> e',None
| Some (ind,nal) ->
let e',nal' = List.fold_right (fun na (e',nal) ->
- let e',na' = g e' na in e',na'::nal) nal (e',[]) in
- e',Some (Loc.tag ?loc (ind,nal')) in
- let e',na' = g e' na in
- (e',(f e tm,(na',t'))::tml')) tml (e,[]) in
- let fold (idl,e) na = let (e,na) = g e na in ((Name.cons na idl,e),na) in
+ let e',na' = protect g e' na in
+ e',na'::nal) nal (e',[]) in
+ e',Some (Loc.tag ?loc (ind,nal')) in
+ let e',na' = protect g e' na in
+ (e',(f e tm,(na',t'))::tml')) tml (e,[]) in
+ let fold (idl,e) na = let (e,disjpat,na) = g e na in ((Name.cons na idl,e),disjpat,na) in
let eqnl' = List.map (fun (patl,rhs) ->
- let ((idl,e),patl) =
- List.fold_left_map (cases_pattern_fold_map ?loc fold) ([],e) patl in
- Loc.tag (idl,patl,f e rhs)) eqnl in
- GCases (sty,Option.map (f e') rtntypopt,tml',eqnl')
+ let ((idl,e),patl) =
+ List.fold_left_map (cases_pattern_fold_map ?loc fold) ([],e) patl in
+ let disjpatl = product_of_cases_patterns patl in
+ List.map (fun patl -> Loc.tag (idl,patl,f e rhs)) disjpatl) eqnl in
+ GCases (sty,Option.map (f e') rtntypopt,tml',List.flatten eqnl')
| NLetTuple (nal,(na,po),b,c) ->
- let e',nal = List.fold_left_map g e nal in
- let e'',na = g e na in
+ let e',nal = List.fold_left_map (protect g) e nal in
+ let e'',na = protect g e na in
GLetTuple (nal,(na,Option.map (f e'') po),f e b,f e' c)
| NIf (c,(na,po),b1,b2) ->
- let e',na = g e na in
+ let e',na = protect g e na in
GIf (f e c,(na,Option.map (f e') po),f e b1,f e b2)
| NRec (fk,idl,dll,tl,bl) ->
- let e,dll = Array.fold_left_map (List.fold_left_map (fun e (na,oc,b) ->
- let e,na = g e na in
+ let e,dll = Array.fold_left_map (List.fold_map (fun e (na,oc,b) ->
+ let e,na = protect g e na in
(e,(na,Explicit,Option.map (f e) oc,f e b)))) e dll in
- let e',idl = Array.fold_left_map (to_id g) e idl in
+ let e',idl = Array.fold_left_map (to_id (protect g)) e idl in
GRec (fk,idl,dll,Array.map (f e) tl,Array.map (f e') bl)
| NCast (c,k) -> GCast (f e c,Miscops.map_cast_type (f e) k)
| NSort x -> GSort x
@@ -195,13 +221,19 @@ let glob_constr_of_notation_constr_with_binders ?loc g f e nc =
let glob_constr_of_notation_constr ?loc x =
let rec aux () x =
- glob_constr_of_notation_constr_with_binders ?loc (fun () id -> ((),id)) aux () x
+ glob_constr_of_notation_constr_with_binders ?loc (fun () id -> ((),None,id)) aux () x
in aux () x
(******************************************************************************)
(* Translating a glob_constr into a notation, interpreting recursive patterns *)
-let add_id r id = r := (id :: pi1 !r, pi2 !r, pi3 !r)
+type found_variables = {
+ vars : Id.t list;
+ recursive_term_vars : (Id.t * Id.t) list;
+ recursive_binders_vars : (Id.t * Id.t) list;
+ }
+
+let add_id r id = r := { !r with vars = id :: (!r).vars }
let add_name r = function Anonymous -> () | Name id -> add_id r id
let is_gvar id c = match DAst.get c with
@@ -245,13 +277,25 @@ let check_is_hole id t = match DAst.get t with GHole _ -> () | _ ->
(strbrk "In recursive notation with binders, " ++ Id.print id ++
strbrk " is expected to come without type.")
+let check_pair_matching ?loc x y x' y' revert revert' =
+ if not (Id.equal x x' && Id.equal y y' && revert = revert') then
+ let x,y = if revert then y,x else x,y in
+ let x',y' = if revert' then y',x' else x',y' in
+ (* This is a case where one would like to highlight two locations! *)
+ user_err ?loc
+ (strbrk "Found " ++ Id.print x ++ strbrk " matching " ++ Id.print y ++
+ strbrk " while " ++ Id.print x' ++ strbrk " matching " ++ Id.print y' ++
+ strbrk " was first found.")
+
let pair_equal eq1 eq2 (a,b) (a',b') = eq1 a a' && eq2 b b'
+let mem_recursive_pair (x,y) l = List.mem_f (pair_equal Id.equal Id.equal) (x,y) l
+
type recursive_pattern_kind =
-| RecursiveTerms of bool (* associativity *)
-| RecursiveBinders of glob_constr * glob_constr
+| RecursiveTerms of bool (* in reverse order *)
+| RecursiveBinders of bool (* in reverse order *)
-let compare_recursive_parts found f f' (iterator,subc) =
+let compare_recursive_parts recvars found f f' (iterator,subc) =
let diff = ref None in
let terminator = ref None in
let rec aux c1 c2 = match DAst.get c1, DAst.get c2 with
@@ -270,24 +314,41 @@ let compare_recursive_parts found f f' (iterator,subc) =
List.for_all2eq aux l1 l2
| _ -> mk_glob_constr_eq aux c1 c2
end
- | GVar x, GVar y when not (Id.equal x y) ->
+ | GVar x, GVar y
+ when mem_recursive_pair (x,y) recvars || mem_recursive_pair (y,x) recvars ->
(* We found the position where it differs *)
- let lassoc = match !terminator with None -> false | Some _ -> true in
- let x,y = if lassoc then y,x else x,y in
+ let revert = mem_recursive_pair (y,x) recvars in
+ let x,y = if revert then y,x else x,y in
begin match !diff with
| None ->
- let () = diff := Some (x, y, RecursiveTerms lassoc) in
+ let () = diff := Some (x, y, RecursiveTerms revert) in
+ true
+ | Some (x', y', RecursiveTerms revert')
+ | Some (x', y', RecursiveBinders revert') ->
+ check_pair_matching ?loc:c1.CAst.loc x y x' y' revert revert';
true
- | Some _ -> false
end
| GLambda (Name x,_,t_x,c), GLambda (Name y,_,t_y,term)
- | GProd (Name x,_,t_x,c), GProd (Name y,_,t_y,term) when not (Id.equal x y) ->
+ | GProd (Name x,_,t_x,c), GProd (Name y,_,t_y,term)
+ when mem_recursive_pair (x,y) recvars || mem_recursive_pair (y,x) recvars ->
(* We found a binding position where it differs *)
+ check_is_hole x t_x;
+ check_is_hole y t_y;
+ let revert = mem_recursive_pair (y,x) recvars in
+ let x,y = if revert then y,x else x,y in
begin match !diff with
| None ->
- let () = diff := Some (x, y, RecursiveBinders (t_x,t_y)) in
+ let () = diff := Some (x, y, RecursiveBinders revert) in
aux c term
- | Some _ -> false
+ | Some (x', y', RecursiveBinders revert') ->
+ check_pair_matching ?loc:c1.CAst.loc x y x' y' revert revert';
+ true
+ | Some (x', y', RecursiveTerms revert') ->
+ (* Recursive binders have precedence: they can be coerced to
+ terms but not reciprocally *)
+ check_pair_matching ?loc:c1.CAst.loc x y x' y' revert revert';
+ let () = diff := Some (x, y, RecursiveBinders revert) in
+ true
end
| _ ->
mk_glob_constr_eq aux c1 c2 in
@@ -296,46 +357,36 @@ let compare_recursive_parts found f f' (iterator,subc) =
| None ->
let loc1 = loc_of_glob_constr iterator in
let loc2 = loc_of_glob_constr (Option.get !terminator) in
- (* Here, we would need a loc made of several parts ... *)
- user_err ?loc:(subtract_loc loc1 loc2)
+ (* Here, we would need a loc made of several parts ... *)
+ user_err ?loc:(subtract_loc loc1 loc2)
(str "Both ends of the recursive pattern are the same.")
- | Some (x,y,RecursiveTerms lassoc) ->
- let toadd,x,y,lassoc =
- if List.mem_f (pair_equal Id.equal Id.equal) (x,y) (pi2 !found) ||
- List.mem_f (pair_equal Id.equal Id.equal) (x,y) (pi3 !found)
- then
- None,x,y,lassoc
- else if List.mem_f (pair_equal Id.equal Id.equal) (y,x) (pi2 !found) ||
- List.mem_f (pair_equal Id.equal Id.equal) (y,x) (pi3 !found)
- then
- None,y,x,not lassoc
- else
- Some (x,y),x,y,lassoc in
- let iterator =
- f' (if lassoc then iterator
- else subst_glob_vars [x, DAst.make @@ GVar y] iterator) in
- (* found variables have been collected by compare_constr *)
- found := (List.remove Id.equal y (pi1 !found),
- Option.fold_right (fun a l -> a::l) toadd (pi2 !found),
- pi3 !found);
- NList (x,y,iterator,f (Option.get !terminator),lassoc)
- | Some (x,y,RecursiveBinders (t_x,t_y)) ->
- let iterator = f' (subst_glob_vars [x, DAst.make @@ GVar y] iterator) in
- (* found have been collected by compare_constr *)
- found := (List.remove Id.equal y (pi1 !found), pi2 !found, (x,y) :: pi3 !found);
- check_is_hole x t_x;
- check_is_hole y t_y;
- NBinderList (x,y,iterator,f (Option.get !terminator))
+ | Some (x,y,RecursiveTerms revert) ->
+ (* By arbitrary convention, we use the second variable of the pair
+ as the place-holder for the iterator *)
+ let iterator =
+ f' (if revert then iterator else subst_glob_vars [x, DAst.make @@ GVar y] iterator) in
+ (* found variables have been collected by compare_constr *)
+ found := { !found with vars = List.remove Id.equal y (!found).vars;
+ recursive_term_vars = List.add_set (pair_equal Id.equal Id.equal) (x,y) (!found).recursive_term_vars };
+ NList (x,y,iterator,f (Option.get !terminator),revert)
+ | Some (x,y,RecursiveBinders revert) ->
+ let iterator =
+ f' (if revert then iterator else subst_glob_vars [x, DAst.make @@ GVar y] iterator) in
+ (* found have been collected by compare_constr *)
+ found := { !found with vars = List.remove Id.equal y (!found).vars;
+ recursive_binders_vars = List.add_set (pair_equal Id.equal Id.equal) (x,y) (!found).recursive_binders_vars };
+ NBinderList (x,y,iterator,f (Option.get !terminator),revert)
else
raise Not_found
-let notation_constr_and_vars_of_glob_constr a =
- let found = ref ([],[],[]) in
+let notation_constr_and_vars_of_glob_constr recvars a =
+ let found = ref { vars = []; recursive_term_vars = []; recursive_binders_vars = [] } in
let has_ltac = ref false in
+ (* Turn a glob_constr into a notation_constr by first trying to find a recursive pattern *)
let rec aux c =
let keepfound = !found in
(* n^2 complexity but small and done only once per notation *)
- try compare_recursive_parts found aux aux' (split_at_recursive_part c)
+ try compare_recursive_parts recvars found aux aux' (split_at_recursive_part c)
with Not_found ->
found := keepfound;
match DAst.get c with
@@ -395,8 +446,9 @@ let notation_constr_and_vars_of_glob_constr a =
(* Side effect *)
t, !found, !has_ltac
-let check_variables_and_reversibility nenv (found,foundrec,foundrecbinding) =
- let injective = ref true in
+let check_variables_and_reversibility nenv
+ { vars = found; recursive_term_vars = foundrec; recursive_binders_vars = foundrecbinding } =
+ let injective = ref [] in
let recvars = nenv.ninterp_rec_vars in
let fold _ y accu = Id.Set.add y accu in
let useless_vars = Id.Map.fold fold recvars Id.Set.empty in
@@ -419,33 +471,36 @@ let check_variables_and_reversibility nenv (found,foundrec,foundrecbinding) =
user_err Pp.(str
(Id.to_string x ^
" should not be bound in a recursive pattern of the right-hand side."))
- else injective := false
+ else injective := x :: !injective
in
let check_pair s x y where =
- if not (List.mem_f (pair_equal Id.equal Id.equal) (x,y) where) then
+ if not (mem_recursive_pair (x,y) where) then
user_err (strbrk "in the right-hand side, " ++ Id.print x ++
str " and " ++ Id.print y ++ strbrk " should appear in " ++ str s ++
str " position as part of a recursive pattern.") in
let check_type x typ =
match typ with
- | NtnInternTypeConstr ->
+ | NtnInternTypeAny ->
begin
try check_pair "term" x (Id.Map.find x recvars) foundrec
with Not_found -> check_bound x
end
- | NtnInternTypeBinder ->
+ | NtnInternTypeOnlyBinder ->
begin
try check_pair "binding" x (Id.Map.find x recvars) foundrecbinding
with Not_found -> check_bound x
- end
- | NtnInternTypeIdent -> check_bound x in
+ end in
Id.Map.iter check_type vars;
- !injective
+ List.rev !injective
let notation_constr_of_glob_constr nenv a =
- let a, found, has_ltac = notation_constr_and_vars_of_glob_constr a in
+ let recvars = Id.Map.bindings nenv.ninterp_rec_vars in
+ let a, found, has_ltac = notation_constr_and_vars_of_glob_constr recvars a in
let injective = check_variables_and_reversibility nenv found in
- a, not has_ltac && injective
+ let status = if has_ltac then HasLtac else match injective with
+ | [] -> APrioriReversible
+ | l -> NonInjective l in
+ a, status
(**********************************************************************)
(* Substitution of kernel names, avoiding a list of bound identifiers *)
@@ -501,11 +556,11 @@ let rec subst_notation_constr subst bound raw =
if r1' == r1 && r2' == r2 then raw else
NProd (n,r1',r2')
- | NBinderList (id1,id2,r1,r2) ->
+ | NBinderList (id1,id2,r1,r2,b) ->
let r1' = subst_notation_constr subst bound r1
and r2' = subst_notation_constr subst bound r2 in
if r1' == r1 && r2' == r2 then raw else
- NBinderList (id1,id2,r1',r2')
+ NBinderList (id1,id2,r1',r2',b)
| NLetIn (n,r1,t,r2) ->
let r1' = subst_notation_constr subst bound r1 in
@@ -616,8 +671,20 @@ let is_term_meta id metas =
try match Id.List.assoc id metas with _,(NtnTypeConstr | NtnTypeConstrList) -> true | _ -> false
with Not_found -> false
+let is_onlybinding_strict_meta id metas =
+ try match Id.List.assoc id metas with _,NtnTypeBinder (NtnParsedAsPattern true) -> true | _ -> false
+ with Not_found -> false
+
let is_onlybinding_meta id metas =
- try match Id.List.assoc id metas with _,NtnTypeOnlyBinder -> true | _ -> false
+ try match Id.List.assoc id metas with _,NtnTypeBinder _ -> true | _ -> false
+ with Not_found -> false
+
+let is_onlybinding_pattern_like_meta isvar id metas =
+ try match Id.List.assoc id metas with
+ | _,NtnTypeBinder (NtnBinderParsedAsConstr
+ (Extend.AsIdentOrPattern | Extend.AsStrictPattern)) -> true
+ | _,NtnTypeBinder (NtnParsedAsPattern strict) -> not (strict && isvar)
+ | _ -> false
with Not_found -> false
let is_bindinglist_meta id metas =
@@ -636,7 +703,7 @@ let alpha_rename alpmetas v =
if alpmetas == [] then v
else try rename_glob_vars alpmetas v with UnsoundRenaming -> raise No_match
-let add_env (alp,alpmetas) (terms,onlybinders,termlists,binderlists) var v =
+let add_env (alp,alpmetas) (terms,termlists,binders,binderlists) var v =
(* Check that no capture of binding variables occur *)
(* [alp] is used when matching a pattern "fun x => ... x ... ?var ... x ..."
with an actual term "fun z => ... z ..." when "x" is not bound in the
@@ -664,19 +731,49 @@ let add_env (alp,alpmetas) (terms,onlybinders,termlists,binderlists) var v =
refinement *)
let v = alpha_rename alpmetas v in
(* TODO: handle the case of multiple occs in different scopes *)
- ((var,v)::terms,onlybinders,termlists,binderlists)
+ ((var,v)::terms,termlists,binders,binderlists)
-let add_termlist_env (alp,alpmetas) (terms,onlybinders,termlists,binderlists) var vl =
+let add_termlist_env (alp,alpmetas) (terms,termlists,binders,binderlists) var vl =
if List.exists (fun (id,_) -> List.exists (occur_glob_constr id) vl) alp then raise No_match;
let vl = List.map (alpha_rename alpmetas) vl in
- (terms,onlybinders,(var,vl)::termlists,binderlists)
+ (terms,(var,vl)::termlists,binders,binderlists)
-let add_binding_env alp (terms,onlybinders,termlists,binderlists) var v =
+let add_binding_env alp (terms,termlists,binders,binderlists) var v =
(* TODO: handle the case of multiple occs in different scopes *)
- (terms,(var,v)::onlybinders,termlists,binderlists)
+ (terms,termlists,(var,v)::binders,binderlists)
-let add_bindinglist_env (terms,onlybinders,termlists,binderlists) x bl =
- (terms,onlybinders,termlists,(x,bl)::binderlists)
+let add_bindinglist_env (terms,termlists,binders,binderlists) x bl =
+ (terms,termlists,binders,(x,bl)::binderlists)
+
+let rec map_cases_pattern_name_left f = DAst.map (function
+ | PatVar na -> PatVar (f na)
+ | PatCstr (c,l,na) -> PatCstr (c,List.map_left (map_cases_pattern_name_left f) l,f na)
+ )
+
+let rec fold_cases_pattern_eq f x p p' =
+ let loc = p.CAst.loc in
+ match DAst.get p, DAst.get p' with
+ | PatVar na, PatVar na' -> let x,na = f x na na' in x, DAst.make ?loc @@ PatVar na
+ | PatCstr (c,l,na), PatCstr (c',l',na') when eq_constructor c c' ->
+ let x,l = fold_cases_pattern_list_eq f x l l' in
+ let x,na = f x na na' in
+ x, DAst.make ?loc @@ PatCstr (c,l,na)
+ | _ -> failwith "Not equal"
+
+and fold_cases_pattern_list_eq f x pl pl' = match pl, pl' with
+ | [], [] -> x, []
+ | p::pl, p'::pl' ->
+ let x, p = fold_cases_pattern_eq f x p p' in
+ let x, pl = fold_cases_pattern_list_eq f x pl pl' in
+ x, p :: pl
+ | _ -> assert false
+
+let rec cases_pattern_eq p1 p2 = match DAst.get p1, DAst.get p2 with
+| PatVar na1, PatVar na2 -> Name.equal na1 na2
+| PatCstr (c1, pl1, na1), PatCstr (c2, pl2, na2) ->
+ eq_constructor c1 c2 && List.equal cases_pattern_eq pl1 pl2 &&
+ Name.equal na1 na2
+| _ -> false
let rec pat_binder_of_term t = DAst.map (function
| GVar id -> PatVar (Name id)
@@ -691,39 +788,111 @@ let rec pat_binder_of_term t = DAst.map (function
| _ -> raise No_match
) t
-let bind_term_env alp (terms,onlybinders,termlists,binderlists as sigma) var v =
+let unify_name_upto alp na na' =
+ match na, na' with
+ | Anonymous, na' -> alp, na'
+ | na, Anonymous -> alp, na
+ | Name id, Name id' ->
+ if Id.equal id id' then alp, na'
+ else (fst alp,(id,id')::snd alp), na'
+
+let unify_pat_upto alp p p' =
+ try fold_cases_pattern_eq unify_name_upto alp p p' with Failure _ -> raise No_match
+
+let unify_term alp v v' =
+ match DAst.get v, DAst.get v' with
+ | GHole _, _ -> v'
+ | _, GHole _ -> v
+ | _, _ -> if glob_constr_eq (alpha_rename (snd alp) v) v' then v else raise No_match
+
+let unify_opt_term alp v v' =
+ match v, v' with
+ | Some t, Some t' -> Some (unify_term alp t t')
+ | (Some _ as x), None | None, (Some _ as x) -> x
+ | None, None -> None
+
+let unify_binding_kind bk bk' = if bk == bk' then bk' else raise No_match
+
+let unify_binder_upto alp b b' =
+ let loc, loc' = CAst.(b.loc, b'.loc) in
+ match DAst.get b, DAst.get b' with
+ | GLocalAssum (na,bk,t), GLocalAssum (na',bk',t') ->
+ let alp, na = unify_name_upto alp na na' in
+ alp, DAst.make ?loc @@ GLocalAssum (na, unify_binding_kind bk bk', unify_term alp t t')
+ | GLocalDef (na,bk,c,t), GLocalDef (na',bk',c',t') ->
+ let alp, na = unify_name_upto alp na na' in
+ alp, DAst.make ?loc @@ GLocalDef (na, unify_binding_kind bk bk', unify_term alp c c', unify_opt_term alp t t')
+ | GLocalPattern ((disjpat,ids),id,bk,t), GLocalPattern ((disjpat',_),_,bk',t') when List.length disjpat = List.length disjpat' ->
+ let alp, p = List.fold_left2_map unify_pat_upto alp disjpat disjpat' in
+ alp, DAst.make ?loc @@ GLocalPattern ((p,ids), id, unify_binding_kind bk bk', unify_term alp t t')
+ | _ -> raise No_match
+
+let rec unify_terms alp vl vl' =
+ match vl, vl' with
+ | [], [] -> []
+ | v :: vl, v' :: vl' -> unify_term alp v v' :: unify_terms alp vl vl'
+ | _ -> raise No_match
+
+let rec unify_binders_upto alp bl bl' =
+ match bl, bl' with
+ | [], [] -> alp, []
+ | b :: bl, b' :: bl' ->
+ let alp,b = unify_binder_upto alp b b' in
+ let alp,bl = unify_binders_upto alp bl bl' in
+ alp, b :: bl
+ | _ -> raise No_match
+
+let unify_id alp id na' =
+ match na' with
+ | Anonymous -> Name (rename_var (snd alp) id)
+ | Name id' ->
+ if Id.equal (rename_var (snd alp) id) id' then na' else raise No_match
+
+let unify_pat alp p p' =
+ if cases_pattern_eq (map_cases_pattern_name_left (Name.map (rename_var (snd alp))) p) p' then p'
+ else raise No_match
+
+let unify_term_binder alp c = DAst.(map (fun b' ->
+ match DAst.get c, b' with
+ | GVar id, GLocalAssum (na', bk', t') ->
+ GLocalAssum (unify_id alp id na', bk', t')
+ | _, GLocalPattern (([p'],ids), id, bk', t') ->
+ let p = pat_binder_of_term c in
+ GLocalPattern (([unify_pat alp p p'],ids), id, bk', t')
+ | _ -> raise No_match))
+
+let rec unify_terms_binders alp cl bl' =
+ match cl, bl' with
+ | [], [] -> []
+ | c :: cl, b' :: bl' ->
+ begin match DAst.get b' with
+ | GLocalDef ( _, _, _, t) -> unify_terms_binders alp cl bl'
+ | _ -> unify_term_binder alp c b' :: unify_terms_binders alp cl bl'
+ end
+ | _ -> raise No_match
+
+let bind_term_env alp (terms,termlists,binders,binderlists as sigma) var v =
try
+ (* If already bound to a term, unify with the new term *)
let v' = Id.List.assoc var terms in
- match DAst.get v, DAst.get v' with
- | GHole _, _ -> sigma
- | _, GHole _ ->
- let sigma = Id.List.remove_assoc var terms,onlybinders,termlists,binderlists in
- add_env alp sigma var v
- | _, _ ->
- if glob_constr_eq (alpha_rename (snd alp) v) v' then sigma
- else raise No_match
+ let v'' = unify_term alp v v' in
+ if v'' == v' then sigma else
+ let sigma = (Id.List.remove_assoc var terms,termlists,binders,binderlists) in
+ add_env alp sigma var v
with Not_found -> add_env alp sigma var v
-let bind_termlist_env alp (terms,onlybinders,termlists,binderlists as sigma) var vl =
+let bind_termlist_env alp (terms,termlists,binders,binderlists as sigma) var vl =
try
+ (* If already bound to a list of term, unify with the new terms *)
let vl' = Id.List.assoc var termlists in
- let unify_term v v' =
- match DAst.get v, DAst.get v' with
- | GHole _, _ -> v'
- | _, GHole _ -> v
- | _, _ -> if glob_constr_eq (alpha_rename (snd alp) v) v' then v' else raise No_match in
- let rec unify vl vl' =
- match vl, vl' with
- | [], [] -> []
- | v :: vl, v' :: vl' -> unify_term v v' :: unify vl vl'
- | _ -> raise No_match in
- let vl = unify vl vl' in
- let sigma = (terms,onlybinders,Id.List.remove_assoc var termlists,binderlists) in
+ let vl = unify_terms alp vl vl' in
+ let sigma = (terms,Id.List.remove_assoc var termlists,binders,binderlists) in
add_termlist_env alp sigma var vl
with Not_found -> add_termlist_env alp sigma var vl
-let bind_term_as_binding_env alp (terms,onlybinders,termlists,binderlists as sigma) var id =
+let bind_term_as_binding_env alp (terms,termlists,binders,binderlists as sigma) var id =
try
+ (* If already bound to a term, unify the binder and the term *)
match DAst.get (Id.List.assoc var terms) with
| GVar id' ->
(if not (Id.equal id id') then (fst alp,(id,id')::snd alp) else alp),
@@ -735,142 +904,49 @@ let bind_term_as_binding_env alp (terms,onlybinders,termlists,binderlists as sig
(* TODO: look at the consequences for alp *)
alp, add_env alp sigma var (DAst.make @@ GVar id)
-let bind_binding_as_term_env alp (terms,onlybinders,termlists,binderlists as sigma) var id =
+let force_cases_pattern c =
+ DAst.make ?loc:c.CAst.loc (DAst.get c)
+
+let bind_binding_as_term_env alp (terms,termlists,binders,binderlists as sigma) var c =
+ let pat = try force_cases_pattern (cases_pattern_of_glob_constr Anonymous c) with Not_found -> raise No_match in
try
- let v' = Id.List.assoc var onlybinders in
- match v' with
- | Anonymous ->
- (* Should not occur, since the term has to be bound upwards *)
- let sigma = (terms,Id.List.remove_assoc var onlybinders,termlists,binderlists) in
- add_binding_env alp sigma var (Name id)
- | Name id' ->
- if Id.equal (rename_var (snd alp) id) id' then sigma else raise No_match
- with Not_found -> add_binding_env alp sigma var (Name id)
-
-let bind_binding_env alp (terms,onlybinders,termlists,binderlists as sigma) var v =
+ (* If already bound to a binder, unify the term and the binder *)
+ let patl' = Id.List.assoc var binders in
+ let patl'' = List.map2 (unify_pat alp) [pat] patl' in
+ if patl' == patl'' then sigma
+ else
+ let sigma = (terms,termlists,Id.List.remove_assoc var binders,binderlists) in
+ add_binding_env alp sigma var patl''
+ with Not_found -> add_binding_env alp sigma var [pat]
+
+let bind_binding_env alp (terms,termlists,binders,binderlists as sigma) var disjpat =
try
- let v' = Id.List.assoc var onlybinders in
- match v, v' with
- | Anonymous, _ -> alp, sigma
- | _, Anonymous ->
- let sigma = (terms,Id.List.remove_assoc var onlybinders,termlists,binderlists) in
- alp, add_binding_env alp sigma var v
- | Name id1, Name id2 ->
- if Id.equal id1 id2 then alp,sigma
- else (fst alp,(id1,id2)::snd alp),sigma
- with Not_found -> alp, add_binding_env alp sigma var v
-
-let rec map_cases_pattern_name_left f = DAst.map (function
- | PatVar na -> PatVar (f na)
- | PatCstr (c,l,na) -> PatCstr (c,List.map_left (map_cases_pattern_name_left f) l,f na)
- )
-
-let rec fold_cases_pattern_eq f x p p' =
- let loc = p.CAst.loc in
- match DAst.get p, DAst.get p' with
- | PatVar na, PatVar na' -> let x,na = f x na na' in x, DAst.make ?loc @@ PatVar na
- | PatCstr (c,l,na), PatCstr (c',l',na') when eq_constructor c c' ->
- let x,l = fold_cases_pattern_list_eq f x l l' in
- let x,na = f x na na' in
- x, DAst.make ?loc @@ PatCstr (c,l,na)
- | _ -> failwith "Not equal"
-
-and fold_cases_pattern_list_eq f x pl pl' = match pl, pl' with
- | [], [] -> x, []
- | p::pl, p'::pl' ->
- let x, p = fold_cases_pattern_eq f x p p' in
- let x, pl = fold_cases_pattern_list_eq f x pl pl' in
- x, p :: pl
- | _ -> assert false
-
-let rec cases_pattern_eq p1 p2 = match DAst.get p1, DAst.get p2 with
-| PatVar na1, PatVar na2 -> Name.equal na1 na2
-| PatCstr (c1, pl1, na1), PatCstr (c2, pl2, na2) ->
- eq_constructor c1 c2 && List.equal cases_pattern_eq pl1 pl2 &&
- Name.equal na1 na2
-| _ -> false
-
-let bind_bindinglist_env alp (terms,onlybinders,termlists,binderlists as sigma) var bl =
+ (* If already bound to a binder possibly *)
+ (* generating an alpha-renaming from unifying the new binder *)
+ let disjpat' = Id.List.assoc var binders in
+ let alp, disjpat = List.fold_left2_map unify_pat_upto alp disjpat disjpat' in
+ let sigma = (terms,termlists,Id.List.remove_assoc var binders,binderlists) in
+ alp, add_binding_env alp sigma var disjpat
+ with Not_found -> alp, add_binding_env alp sigma var disjpat
+
+let bind_bindinglist_env alp (terms,termlists,binders,binderlists as sigma) var bl =
let bl = List.rev bl in
try
+ (* If already bound to a list of binders possibly *)
+ (* generating an alpha-renaming from unifying the new binders *)
let bl' = Id.List.assoc var binderlists in
- let unify_name alp na na' =
- match na, na' with
- | Anonymous, na' -> alp, na'
- | na, Anonymous -> alp, na
- | Name id, Name id' ->
- if Id.equal id id' then alp, na'
- else (fst alp,(id,id')::snd alp), na' in
- let unify_pat alp p p' =
- try fold_cases_pattern_eq unify_name alp p p' with Failure _ -> raise No_match in
- let unify_term alp v v' =
- match DAst.get v, DAst.get v' with
- | GHole _, _ -> v'
- | _, GHole _ -> v
- | _, _ -> if glob_constr_eq (alpha_rename (snd alp) v) v' then v else raise No_match in
- let unify_opt_term alp v v' =
- match v, v' with
- | Some t, Some t' -> Some (unify_term alp t t')
- | (Some _ as x), None | None, (Some _ as x) -> x
- | None, None -> None in
- let unify_binding_kind bk bk' = if bk == bk' then bk' else raise No_match in
- let unify_binder alp b b' =
- let loc, loc' = CAst.(b.loc, b'.loc) in
- match DAst.get b, DAst.get b' with
- | GLocalAssum (na,bk,t), GLocalAssum (na',bk',t') ->
- let alp, na = unify_name alp na na' in
- alp, DAst.make ?loc @@ GLocalAssum (na, unify_binding_kind bk bk', unify_term alp t t')
- | GLocalDef (na,bk,c,t), GLocalDef (na',bk',c',t') ->
- let alp, na = unify_name alp na na' in
- alp, DAst.make ?loc @@ GLocalDef (na, unify_binding_kind bk bk', unify_term alp c c', unify_opt_term alp t t')
- | GLocalPattern ((p,ids),id,bk,t), GLocalPattern ((p',_),_,bk',t') ->
- let alp, p = unify_pat alp p p' in
- alp, DAst.make ?loc @@ GLocalPattern ((p,ids), id, unify_binding_kind bk bk', unify_term alp t t')
- | _ -> raise No_match in
- let rec unify alp bl bl' =
- match bl, bl' with
- | [], [] -> alp, []
- | b :: bl, b' :: bl' ->
- let alp,b = unify_binder alp b b' in
- let alp,bl = unify alp bl bl' in
- alp, b :: bl
- | _ -> raise No_match in
- let alp, bl = unify alp bl bl' in
- let sigma = (terms,onlybinders,termlists,Id.List.remove_assoc var binderlists) in
+ let alp, bl = unify_binders_upto alp bl bl' in
+ let sigma = (terms,termlists,binders,Id.List.remove_assoc var binderlists) in
alp, add_bindinglist_env sigma var bl
with Not_found ->
alp, add_bindinglist_env sigma var bl
-let bind_bindinglist_as_term_env alp (terms,onlybinders,termlists,binderlists) var cl =
+let bind_bindinglist_as_termlist_env alp (terms,termlists,binders,binderlists) var cl =
try
+ (* If already bound to a list of binders, unify the terms and binders *)
let bl' = Id.List.assoc var binderlists in
- let unify_id id na' =
- match na' with
- | Anonymous -> Name (rename_var (snd alp) id)
- | Name id' ->
- if Id.equal (rename_var (snd alp) id) id' then na' else raise No_match in
- let unify_pat p p' =
- if cases_pattern_eq (map_cases_pattern_name_left (Name.map (rename_var (snd alp))) p) p' then p'
- else raise No_match in
- let unify_term_binder c = DAst.(map (fun b' ->
- match DAst.get c, b' with
- | GVar id, GLocalAssum (na', bk', t') ->
- GLocalAssum (unify_id id na', bk', t')
- | _, GLocalPattern ((p',ids), id, bk', t') ->
- let p = pat_binder_of_term c in
- GLocalPattern ((unify_pat p p',ids), id, bk', t')
- | _ -> raise No_match )) in
- let rec unify cl bl' =
- match cl, bl' with
- | [], [] -> []
- | c :: cl, b' :: bl' ->
- begin match DAst.get b' with
- | GLocalDef ( _, _, _, t) -> unify cl bl'
- | _ -> unify_term_binder c b' :: unify cl bl'
- end
- | _ -> raise No_match in
- let bl = unify cl bl' in
- let sigma = (terms,onlybinders,termlists,Id.List.remove_assoc var binderlists) in
+ let bl = unify_terms_binders alp cl bl' in
+ let sigma = (terms,termlists,binders,Id.List.remove_assoc var binderlists) in
add_bindinglist_env sigma var bl
with Not_found ->
anomaly (str "There should be a binder list bindings this list of terms.")
@@ -894,8 +970,10 @@ let match_opt f sigma t1 t2 = match (t1,t2) with
| _ -> raise No_match
let match_names metas (alp,sigma) na1 na2 = match (na1,na2) with
+ | (na1,Name id2) when is_onlybinding_strict_meta id2 metas ->
+ raise No_match
| (na1,Name id2) when is_onlybinding_meta id2 metas ->
- bind_binding_env alp sigma id2 na1
+ bind_binding_env alp sigma id2 [DAst.make (PatVar na1)]
| (Name id1,Name id2) when is_term_meta id2 metas ->
(* We let the non-binding occurrence define the rhs and hence reason up to *)
(* alpha-conversion for the given occurrence of the name (see #4592)) *)
@@ -907,54 +985,42 @@ let match_names metas (alp,sigma) na1 na2 = match (na1,na2) with
| (Anonymous,Anonymous) -> alp,sigma
| _ -> raise No_match
-let rec match_cases_pattern_binders metas acc pat1 pat2 =
+let rec match_cases_pattern_binders allow_catchall metas (alp,sigma as acc) pat1 pat2 =
match DAst.get pat1, DAst.get pat2 with
+ | PatVar _, PatVar (Name id2) when is_onlybinding_pattern_like_meta true id2 metas ->
+ bind_binding_env alp sigma id2 [pat1]
+ | _, PatVar (Name id2) when is_onlybinding_pattern_like_meta false id2 metas ->
+ bind_binding_env alp sigma id2 [pat1]
| PatVar na1, PatVar na2 -> match_names metas acc na1 na2
+ | _, PatVar Anonymous when allow_catchall -> acc
| PatCstr (c1,patl1,na1), PatCstr (c2,patl2,na2)
when eq_constructor c1 c2 && Int.equal (List.length patl1) (List.length patl2) ->
- List.fold_left2 (match_cases_pattern_binders metas)
- (match_names metas acc na1 na2) patl1 patl2
+ List.fold_left2 (match_cases_pattern_binders false metas)
+ (match_names metas acc na1 na2) patl1 patl2
| _ -> raise No_match
-let glue_letin_with_decls = true
-
-let rec match_iterated_binders islambda decls bi = DAst.(with_loc_val (fun ?loc -> function
- | GLambda (na,bk,t,b) as b0 ->
- begin match na, DAst.get b with
- | Name p, GCases (LetPatternStyle,None,[(e,_)],[(_,(ids,[cp],b))])
- when islambda && is_gvar p e && not (occur_glob_constr p b) ->
- match_iterated_binders islambda ((DAst.make ?loc @@ GLocalPattern((cp,ids),p,bk,t))::decls) b
- | _, _ when islambda ->
- match_iterated_binders islambda ((DAst.make ?loc @@ GLocalAssum(na,bk,t))::decls) b
- | _ -> (decls, DAst.make ?loc b0)
- end
- | GProd (na,bk,t,b) as b0 ->
- begin match na, DAst.get b with
- | Name p, GCases (LetPatternStyle,None,[(e,_)],[(_,(ids,[cp],b))])
- when not islambda && is_gvar p e && not (occur_glob_constr p b) ->
- match_iterated_binders islambda ((DAst.make ?loc @@ GLocalPattern((cp,ids),p,bk,t))::decls) b
- | Name _, _ when not islambda ->
- match_iterated_binders islambda ((DAst.make ?loc @@ GLocalAssum(na,bk,t))::decls) b
- | _ -> (decls, DAst.make ?loc b0)
- end
- | GLetIn (na,c,t,b) when glue_letin_with_decls ->
- match_iterated_binders islambda
- ((DAst.make ?loc @@ GLocalDef (na,Explicit (*?*), c,t))::decls) b
- | b -> (decls, DAst.make ?loc b)
- )) bi
-
-let remove_sigma x (terms,onlybinders,termlists,binderlists) =
- (Id.List.remove_assoc x terms,onlybinders,termlists,binderlists)
+let remove_sigma x (terms,termlists,binders,binderlists) =
+ (Id.List.remove_assoc x terms,termlists,binders,binderlists)
-let remove_bindinglist_sigma x (terms,onlybinders,termlists,binderlists) =
- (terms,onlybinders,termlists,Id.List.remove_assoc x binderlists)
+let remove_bindinglist_sigma x (terms,termlists,binders,binderlists) =
+ (terms,termlists,binders,Id.List.remove_assoc x binderlists)
let add_ldots_var metas = (ldots_var,((None,[]),NtnTypeConstr))::metas
let add_meta_bindinglist x metas = (x,((None,[]),NtnTypeBinderList))::metas
-let match_binderlist_with_app match_fun alp metas sigma rest x y iter termin =
- let rec aux sigma bl rest =
+(* This tells if letins in the middle of binders should be included in
+ the sequence of binders *)
+let glue_inner_letin_with_decls = true
+
+(* This tells if trailing letins (with no further proper binders)
+ should be included in sequence of binders *)
+let glue_trailing_letin_with_decls = false
+
+exception OnlyTrailingLetIns
+
+let match_binderlist match_fun alp metas sigma rest x y iter termin revert =
+ let rec aux trailing_letins sigma bl rest =
try
let metas = add_ldots_var (add_meta_bindinglist y metas) in
let (terms,_,_,binderlists as sigma) = match_fun alp metas sigma rest iter in
@@ -963,16 +1029,32 @@ let match_binderlist_with_app match_fun alp metas sigma rest x y iter termin =
match Id.List.assoc y binderlists with [b] -> b | _ ->assert false
in
let sigma = remove_bindinglist_sigma y (remove_sigma ldots_var sigma) in
- aux sigma (b::bl) rest
- with No_match when not (List.is_empty bl) ->
- bl, rest, sigma in
- let bl,rest,sigma = aux sigma [] rest in
+ (* In case y is bound not only to a binder but also to a term *)
+ let sigma = remove_sigma y sigma in
+ aux false sigma (b::bl) rest
+ with No_match ->
+ match DAst.get rest with
+ | GLetIn (na,c,t,rest') when glue_inner_letin_with_decls ->
+ let b = DAst.make ?loc:rest.CAst.loc @@ GLocalDef (na,Explicit (*?*), c,t) in
+ (* collect let-in *)
+ (try aux true sigma (b::bl) rest'
+ with OnlyTrailingLetIns
+ when not (trailing_letins && not glue_trailing_letin_with_decls) ->
+ (* renounce to take into account trailing let-ins *)
+ if not (List.is_empty bl) then bl, rest, sigma else raise No_match)
+ | _ ->
+ if trailing_letins && not glue_trailing_letin_with_decls then
+ (* Backtrack to when we tried to glue letins *)
+ raise OnlyTrailingLetIns;
+ if not (List.is_empty bl) then bl, rest, sigma else raise No_match in
+ let bl,rest,sigma = aux false sigma [] rest in
+ let bl = if revert then List.rev bl else bl in
let alp,sigma = bind_bindinglist_env alp sigma x bl in
match_fun alp metas sigma rest termin
let add_meta_term x metas = (x,((None,[]),NtnTypeConstr))::metas
-let match_termlist match_fun alp metas sigma rest x y iter termin lassoc =
+let match_termlist match_fun alp metas sigma rest x y iter termin revert =
let rec aux sigma acc rest =
try
let metas = add_ldots_var (add_meta_term y metas) in
@@ -983,12 +1065,12 @@ let match_termlist match_fun alp metas sigma rest x y iter termin lassoc =
aux sigma (t::acc) rest
with No_match when not (List.is_empty acc) ->
acc, match_fun metas sigma rest termin in
- let l,(terms,onlybinders,termlists,binderlists as sigma) = aux sigma [] rest in
- let l = if lassoc then l else List.rev l in
+ let l,(terms,termlists,binders,binderlists as sigma) = aux sigma [] rest in
+ let l = if revert then l else List.rev l in
if is_bindinglist_meta x metas then
(* This is a recursive pattern for both bindings and terms; it is *)
(* registered for binders *)
- bind_bindinglist_as_term_env alp sigma x l
+ bind_bindinglist_as_termlist_env alp sigma x l
else
bind_termlist_env alp sigma x l
@@ -1023,72 +1105,19 @@ let rec match_ inner u alp metas sigma a1 a2 =
match DAst.get a1, a2 with
(* Matching notation variable *)
| r1, NVar id2 when is_term_meta id2 metas -> bind_term_env alp sigma id2 a1
- | GVar id1, NVar id2 when is_onlybinding_meta id2 metas -> bind_binding_as_term_env alp sigma id2 id1
+ | GVar _, NVar id2 when is_onlybinding_pattern_like_meta true id2 metas -> bind_binding_as_term_env alp sigma id2 a1
+ | r1, NVar id2 when is_onlybinding_pattern_like_meta false id2 metas -> bind_binding_as_term_env alp sigma id2 a1
+ | GVar _, NVar id2 when is_onlybinding_strict_meta id2 metas -> raise No_match
+ | GVar _, NVar id2 when is_onlybinding_meta id2 metas -> bind_binding_as_term_env alp sigma id2 a1
| r1, NVar id2 when is_bindinglist_meta id2 metas -> bind_term_env alp sigma id2 a1
(* Matching recursive notations for terms *)
- | r1, NList (x,y,iter,termin,lassoc) ->
- match_termlist (match_hd u alp) alp metas sigma a1 x y iter termin lassoc
-
- | GLambda (na1, bk, t1, b1), NBinderList (x,y,iter,termin) ->
- begin match na1, DAst.get b1, iter with
- (* "λ p, let 'cp = p in t" -> "λ 'cp, t" *)
- | Name p, GCases (LetPatternStyle,None,[(e,_)],[(_,(ids,[cp],b1))]), NLambda (Name _, _, _)
- when is_gvar p e && not (occur_glob_constr p b1) ->
- let (decls,b) = match_iterated_binders true [DAst.make ?loc @@ GLocalPattern((cp,ids),p,bk,t1)] b1 in
- let alp,sigma = bind_bindinglist_env alp sigma x decls in
- match_in u alp metas sigma b termin
- (* Matching recursive notations for binders: ad hoc cases supporting let-in *)
- | _, _, NLambda (Name _,_,_) ->
- let (decls,b) = match_iterated_binders true [DAst.make ?loc @@ GLocalAssum (na1,bk,t1)] b1 in
- (* TODO: address the possibility that termin is a Lambda itself *)
- let alp,sigma = bind_bindinglist_env alp sigma x decls in
- match_in u alp metas sigma b termin
- (* Matching recursive notations for binders: general case *)
- | _, _, _ ->
- match_binderlist_with_app (match_hd u) alp metas sigma a1 x y iter termin
- end
-
- | GProd (na1, bk, t1, b1), NBinderList (x,y,iter,termin) ->
- (* "∀ p, let 'cp = p in t" -> "∀ 'cp, t" *)
- begin match na1, DAst.get b1, iter, termin with
- | Name p, GCases (LetPatternStyle,None,[(e, _)],[(_,(ids,[cp],b1))]), NProd (Name _,_,_), NVar _
- when is_gvar p e && not (occur_glob_constr p b1) ->
- let (decls,b) = match_iterated_binders true [DAst.make ?loc @@ GLocalPattern ((cp,ids),p,bk,t1)] b1 in
- let alp,sigma = bind_bindinglist_env alp sigma x decls in
- match_in u alp metas sigma b termin
- | _, _, NProd (Name _,_,_), _ when na1 != Anonymous ->
- let (decls,b) = match_iterated_binders false [DAst.make ?loc @@ GLocalAssum (na1,bk,t1)] b1 in
- (* TODO: address the possibility that termin is a Prod itself *)
- let alp,sigma = bind_bindinglist_env alp sigma x decls in
- match_in u alp metas sigma b termin
- (* Matching recursive notations for binders: general case *)
- | _, _, _, _ ->
- match_binderlist_with_app (match_hd u) alp metas sigma a1 x y iter termin
- end
+ | r1, NList (x,y,iter,termin,revert) ->
+ match_termlist (match_hd u alp) alp metas sigma a1 x y iter termin revert
(* Matching recursive notations for binders: general case *)
- | _r, NBinderList (x,y,iter,termin) ->
- match_binderlist_with_app (match_hd u) alp metas sigma a1 x y iter termin
-
- (* Matching individual binders as part of a recursive pattern *)
- | GLambda (na1, bk, t1, b1), NLambda (na2, t2, b2) ->
- begin match na1, DAst.get b1, na2 with
- | Name p, GCases (LetPatternStyle,None,[(e,_)],[(_,(ids,[cp],b1))]), Name id
- when is_gvar p e && is_bindinglist_meta id metas && not (occur_glob_constr p b1) ->
- let alp,sigma = bind_bindinglist_env alp sigma id [DAst.make ?loc @@ GLocalPattern ((cp,ids),p,bk,t1)] in
- match_in u alp metas sigma b1 b2
- | _, _, Name id when is_bindinglist_meta id metas ->
- let alp,sigma = bind_bindinglist_env alp sigma id [DAst.make ?loc @@ GLocalAssum (na1,bk,t1)] in
- match_in u alp metas sigma b1 b2
- | _ ->
- match_binders u alp metas na1 na2 (match_in u alp metas sigma t1 t2) b1 b2
- end
-
- | GProd (na,bk,t,b1), NProd (Name id,_,b2)
- when is_bindinglist_meta id metas && na != Anonymous ->
- let alp,sigma = bind_bindinglist_env alp sigma id [DAst.make ?loc @@ GLocalAssum (na,bk,t)] in
- match_in u alp metas sigma b1 b2
+ | _r, NBinderList (x,y,iter,termin,revert) ->
+ match_binderlist (match_hd u) alp metas sigma a1 x y iter termin revert
(* Matching compositionally *)
| GVar id1, NVar id2 when alpha_var id1 id2 (fst alp) -> sigma
@@ -1104,8 +1133,10 @@ let rec match_ inner u alp metas sigma a1 a2 =
let may_use_eta = does_not_come_from_already_eta_expanded_var f1 in
List.fold_left2 (match_ may_use_eta u alp metas)
(match_in u alp metas sigma f1 f2) l1 l2
- | GProd (na1,_,t1,b1), NProd (na2,t2,b2) ->
- match_binders u alp metas na1 na2 (match_in u alp metas sigma t1 t2) b1 b2
+ | GLambda (na1,bk1,t1,b1), NLambda (na2,t2,b2) ->
+ match_extended_binders false u alp metas na1 na2 bk1 t1 (match_in u alp metas sigma t1 t2) b1 b2
+ | GProd (na1,bk1,t1,b1), NProd (na2,t2,b2) ->
+ match_extended_binders true u alp metas na1 na2 bk1 t1 (match_in u alp metas sigma t1 t2) b1 b2
| GLetIn (na1,b1,_,c1), NLetIn (na2,b2,None,c2)
| GLetIn (na1,b1,None,c1), NLetIn (na2,b2,_,c2) ->
match_binders u alp metas na1 na2 (match_in u alp metas sigma b1 b2) c1 c2
@@ -1113,9 +1144,7 @@ let rec match_ inner u alp metas sigma a1 a2 =
match_binders u alp metas na1 na2
(match_in u alp metas (match_in u alp metas sigma b1 b2) t1 t2) c1 c2
| GCases (sty1,rtno1,tml1,eqnl1), NCases (sty2,rtno2,tml2,eqnl2)
- when sty1 == sty2
- && Int.equal (List.length tml1) (List.length tml2)
- && Int.equal (List.length eqnl1) (List.length eqnl2) ->
+ when sty1 == sty2 && Int.equal (List.length tml1) (List.length tml2) ->
let rtno1' = abstract_return_type_context_glob_constr tml1 rtno1 in
let rtno2' = abstract_return_type_context_notation_constr tml2 rtno2 in
let sigma =
@@ -1125,7 +1154,14 @@ let rec match_ inner u alp metas sigma a1 a2 =
let sigma = List.fold_left2
(fun s (tm1,_) (tm2,_) ->
match_in u alp metas s tm1 tm2) sigma tml1 tml2 in
- List.fold_left2 (match_equations u alp metas) sigma eqnl1 eqnl2
+ (* Try two different strategies for matching clauses *)
+ (try
+ List.fold_left2_set No_match (match_equations u alp metas) sigma eqnl1 eqnl2
+ with
+ No_match ->
+ List.fold_left2_set No_match (match_disjunctive_equations u alp metas) sigma
+ (Detyping.factorize_eqns eqnl1)
+ (List.map (fun (patl,rhs) -> ([patl],rhs)) eqnl2))
| GLetTuple (nal1,(na1,to1),b1,c1), NLetTuple (nal2,(na2,to2),b2,c2)
when Int.equal (List.length nal1) (List.length nal2) ->
let sigma = match_opt (match_binders u alp metas na1 na2) sigma to1 to2 in
@@ -1191,44 +1227,83 @@ and match_in u = match_ true u
and match_hd u = match_ false u
and match_binders u alp metas na1 na2 sigma b1 b2 =
+ (* Match binders which cannot be substituted by a pattern *)
let (alp,sigma) = match_names metas (alp,sigma) na1 na2 in
match_in u alp metas sigma b1 b2
-and match_equations u alp metas sigma (_,(_,patl1,rhs1)) (patl2,rhs2) =
+and match_extended_binders ?loc isprod u alp metas na1 na2 bk t sigma b1 b2 =
+ (* Match binders which can be substituted by a pattern *)
+ let store, get = set_temporary_memory () in
+ match na1, DAst.get b1, na2 with
+ (* Matching individual binders as part of a recursive pattern *)
+ | Name p, GCases (LetPatternStyle,None,[(e,_)],(_::_ as eqns)), Name id
+ when is_gvar p e && is_bindinglist_meta id metas && List.length (store (Detyping.factorize_eqns eqns)) = 1 ->
+ (match get () with
+ | [(_,(ids,disj_of_patl,b1))] ->
+ let disjpat = List.map (function [pat] -> pat | _ -> assert false) disj_of_patl in
+ let disjpat = if occur_glob_constr p b1 then List.map (set_pat_alias p) disjpat else disjpat in
+ let alp,sigma = bind_bindinglist_env alp sigma id [DAst.make ?loc @@ GLocalPattern ((disjpat,ids),p,bk,t)] in
+ match_in u alp metas sigma b1 b2
+ | _ -> assert false)
+ | Name p, GCases (LetPatternStyle,None,[(e,_)],(_::_ as eqns)), Name id
+ when is_gvar p e && is_onlybinding_pattern_like_meta false id metas && List.length (store (Detyping.factorize_eqns eqns)) = 1 ->
+ (match get () with
+ | [(_,(ids,disj_of_patl,b1))] ->
+ let disjpat = List.map (function [pat] -> pat | _ -> assert false) disj_of_patl in
+ let disjpat = if occur_glob_constr p b1 then List.map (set_pat_alias p) disjpat else disjpat in
+ let alp,sigma = bind_binding_env alp sigma id disjpat in
+ match_in u alp metas sigma b1 b2
+ | _ -> assert false)
+ | _, _, Name id when is_bindinglist_meta id metas && (not isprod || na1 != Anonymous)->
+ let alp,sigma = bind_bindinglist_env alp sigma id [DAst.make ?loc @@ GLocalAssum (na1,bk,t)] in
+ match_in u alp metas sigma b1 b2
+ | _, _, _ ->
+ let (alp,sigma) = match_names metas (alp,sigma) na1 na2 in
+ match_in u alp metas sigma b1 b2
+
+and match_equations u alp metas sigma (_,(ids,patl1,rhs1)) (patl2,rhs2) rest1 rest2 =
(* patl1 and patl2 have the same length because they respectively
correspond to some tml1 and tml2 that have the same length *)
+ let allow_catchall = (rest2 = [] && ids = []) in
let (alp,sigma) =
- List.fold_left2 (match_cases_pattern_binders metas)
+ List.fold_left2 (match_cases_pattern_binders allow_catchall metas)
(alp,sigma) patl1 patl2 in
match_in u alp metas sigma rhs1 rhs2
-let term_of_binder bi = DAst.make @@ match bi with
- | Name id -> GVar id
- | Anonymous -> GHole (Evar_kinds.InternalHole,Misctypes.IntroAnonymous,None)
+and match_disjunctive_equations u alp metas sigma (_,(ids,disjpatl1,rhs1)) (disjpatl2,rhs2) _ _ =
+ (* patl1 and patl2 have the same length because they respectively
+ correspond to some tml1 and tml2 that have the same length *)
+ let (alp,sigma) =
+ List.fold_left2_set No_match
+ (fun alp_sigma patl1 patl2 _ _ ->
+ List.fold_left2 (match_cases_pattern_binders false metas) alp_sigma patl1 patl2)
+ (alp,sigma) disjpatl1 disjpatl2 in
+ match_in u alp metas sigma rhs1 rhs2
let match_notation_constr u c (metas,pat) =
- let terms,binders,termlists,binderlists =
+ let terms,termlists,binders,binderlists =
match_ false u ([],[]) metas ([],[],[],[]) c pat in
- (* Reorder canonically the substitution *)
- let find_binder x =
- try term_of_binder (Id.List.assoc x binders)
- with Not_found ->
- (* Happens for binders bound to Anonymous *)
- (* Find a better way to propagate Anonymous... *)
- DAst.make @@GVar x in
- List.fold_right (fun (x,(scl,typ)) (terms',termlists',binders') ->
+ (* Turning substitution based on binding/constr distinction into a
+ substitution based on entry productions *)
+ List.fold_right (fun (x,(scl,typ)) (terms',termlists',binders',binderlists') ->
match typ with
| NtnTypeConstr ->
let term = try Id.List.assoc x terms with Not_found -> raise No_match in
- ((term, scl)::terms',termlists',binders')
- | NtnTypeOnlyBinder ->
- ((find_binder x, scl)::terms',termlists',binders')
+ ((term, scl)::terms',termlists',binders',binderlists')
+ | NtnTypeBinder (NtnBinderParsedAsConstr _) ->
+ (match Id.List.assoc x binders with
+ | [pat] ->
+ let v = glob_constr_of_cases_pattern pat in
+ ((v,scl)::terms',termlists',binders',binderlists')
+ | _ -> raise No_match)
+ | NtnTypeBinder (NtnParsedAsIdent | NtnParsedAsPattern _) ->
+ (terms',termlists',(Id.List.assoc x binders,scl)::binders',binderlists')
| NtnTypeConstrList ->
- (terms',(Id.List.assoc x termlists,scl)::termlists',binders')
+ (terms',(Id.List.assoc x termlists,scl)::termlists',binders',binderlists')
| NtnTypeBinderList ->
let bl = try Id.List.assoc x binderlists with Not_found -> raise No_match in
- (terms',termlists',(bl, scl)::binders'))
- metas ([],[],[])
+ (terms',termlists',binders',(bl, scl)::binderlists'))
+ metas ([],[],[],[])
(* Matching cases pattern *)
@@ -1240,7 +1315,7 @@ let bind_env_cases_pattern (terms,x,termlists,y as sigma) var v =
(* TODO: handle the case of multiple occs in different scopes *)
(var,v)::terms,x,termlists,y
-let match_cases_pattern_list match_fun metas sigma rest x y iter termin lassoc =
+let match_cases_pattern_list match_fun metas sigma rest x y iter termin revert =
let rec aux sigma acc rest =
try
let metas = add_ldots_var (add_meta_term y metas) in
@@ -1251,10 +1326,10 @@ let match_cases_pattern_list match_fun metas sigma rest x y iter termin lassoc =
aux sigma (t::acc) rest
with No_match when not (List.is_empty acc) ->
acc, match_fun metas sigma rest termin in
- let l,(terms,onlybinders,termlists,binderlists as sigma) = aux sigma [] rest in
- (terms,onlybinders,(x,if lassoc then l else List.rev l)::termlists, binderlists)
+ let l,(terms,termlists,binders,binderlists as sigma) = aux sigma [] rest in
+ (terms,(x,if revert then l else List.rev l)::termlists,binders,binderlists)
-let rec match_cases_pattern metas (terms,(),termlists,() as sigma) a1 a2 =
+let rec match_cases_pattern metas (terms,termlists,(),() as sigma) a1 a2 =
match DAst.get a1, a2 with
| r1, NVar id2 when Id.List.mem_assoc id2 metas -> (bind_env_cases_pattern sigma id2 a1),(0,[])
| PatVar Anonymous, NHole _ -> sigma,(0,[])
@@ -1270,10 +1345,10 @@ let rec match_cases_pattern metas (terms,(),termlists,() as sigma) a1 a2 =
raise No_match
else
let l1',more_args = Util.List.chop le2 l1 in
- (List.fold_left2 (match_cases_pattern_no_more_args metas) sigma l1' l2),(le2,more_args)
- | r1, NList (x,y,iter,termin,lassoc) ->
+ (List.fold_left2 (match_cases_pattern_no_more_args metas) sigma l1' l2),(le2,more_args)
+ | r1, NList (x,y,iter,termin,revert) ->
(match_cases_pattern_list (match_cases_pattern_no_more_args)
- metas (terms,(),termlists,()) a1 x y iter termin lassoc),(0,[])
+ metas (terms,termlists,(),()) a1 x y iter termin revert),(0,[])
| _ -> raise No_match
and match_cases_pattern_no_more_args metas sigma a1 a2 =
@@ -1300,15 +1375,15 @@ let reorder_canonically_substitution terms termlists metas =
List.fold_right (fun (x,(scl,typ)) (terms',termlists') ->
match typ with
| NtnTypeConstr -> ((Id.List.assoc x terms, scl)::terms',termlists')
- | NtnTypeOnlyBinder -> assert false
+ | NtnTypeBinder _ -> assert false
| NtnTypeConstrList -> (terms',(Id.List.assoc x termlists,scl)::termlists')
| NtnTypeBinderList -> assert false)
metas ([],[])
let match_notation_constr_cases_pattern c (metas,pat) =
- let (terms,(),termlists,()),more_args = match_cases_pattern metas ([],(),[],()) c pat in
+ let (terms,termlists,(),()),more_args = match_cases_pattern metas ([],[],(),()) c pat in
reorder_canonically_substitution terms termlists metas, more_args
let match_notation_constr_ind_pattern ind args (metas,pat) =
- let (terms,(),termlists,()),more_args = match_ind_pattern metas ([],(),[],()) ind args pat in
+ let (terms,termlists,(),()),more_args = match_ind_pattern metas ([],[],(),()) ind args pat in
reorder_canonically_substitution terms termlists metas, more_args
diff --git a/interp/notation_ops.mli b/interp/notation_ops.mli
index 0904a4ea3..746f52e48 100644
--- a/interp/notation_ops.mli
+++ b/interp/notation_ops.mli
@@ -29,12 +29,15 @@ val ldots_var : Id.t
bound by the notation; also interpret recursive patterns *)
val notation_constr_of_glob_constr : notation_interp_env ->
- glob_constr -> notation_constr * reversibility_flag
+ glob_constr -> notation_constr * reversibility_status
(** Re-interpret a notation as a [glob_constr], taking care of binders *)
+val apply_cases_pattern : ?loc:Loc.t ->
+ (Id.t list * cases_pattern_disjunction) * Id.t -> glob_constr -> glob_constr
+
val glob_constr_of_notation_constr_with_binders : ?loc:Loc.t ->
- ('a -> Name.t -> 'a * Name.t) ->
+ ('a -> Name.t -> 'a * ((Id.t list * cases_pattern_disjunction) * Id.t) option * Name.t) ->
('a -> notation_constr -> glob_constr) ->
'a -> notation_constr -> glob_constr
@@ -49,6 +52,7 @@ exception No_match
val match_notation_constr : bool -> 'a glob_constr_g -> interpretation ->
('a glob_constr_g * subscopes) list * ('a glob_constr_g list * subscopes) list *
+ ('a cases_pattern_disjunction_g * subscopes) list *
('a extended_glob_local_binder_g list * subscopes) list
val match_notation_constr_cases_pattern :
diff --git a/interp/ppextend.ml b/interp/ppextend.ml
index ce19dd8a9..606196fcd 100644
--- a/interp/ppextend.ml
+++ b/interp/ppextend.ml
@@ -33,6 +33,7 @@ let ppcmd_of_cut = function
type unparsing =
| UnpMetaVar of int * parenRelation
+ | UnpBinderMetaVar of int * parenRelation
| UnpListMetaVar of int * parenRelation * unparsing list
| UnpBinderListMetaVar of int * bool * unparsing list
| UnpTerminal of string
diff --git a/interp/ppextend.mli b/interp/ppextend.mli
index 7b62a2074..77823e32a 100644
--- a/interp/ppextend.mli
+++ b/interp/ppextend.mli
@@ -26,6 +26,7 @@ val ppcmd_of_cut : ppcut -> Pp.t
type unparsing =
| UnpMetaVar of int * parenRelation
+ | UnpBinderMetaVar of int * parenRelation
| UnpListMetaVar of int * parenRelation * unparsing list
| UnpBinderListMetaVar of int * bool * unparsing list
| UnpTerminal of string
diff --git a/interp/reserve.ml b/interp/reserve.ml
index 22c5a2f5e..3e1a7dd9b 100644
--- a/interp/reserve.ml
+++ b/interp/reserve.ml
@@ -71,7 +71,7 @@ let reserve_revtable = Summary.ref KeyMap.empty ~name:"reserved-type-rev"
let notation_constr_key = function (* Rem: NApp(NRef ref,[]) stands for @ref *)
| NApp (NRef ref,args) -> RefKey(canonical_gr ref), Some (List.length args)
| NList (_,_,NApp (NRef ref,args),_,_)
- | NBinderList (_,_,NApp (NRef ref,args),_) -> RefKey (canonical_gr ref), Some (List.length args)
+ | NBinderList (_,_,NApp (NRef ref,args),_,_) -> RefKey (canonical_gr ref), Some (List.length args)
| NRef ref -> RefKey(canonical_gr ref), None
| _ -> Oth, None
@@ -84,7 +84,7 @@ let in_reserved : Id.t * notation_constr -> obj =
declare_object {(default_object "RESERVED-TYPE") with
cache_function = cache_reserved_type }
-let declare_reserved_type_binding (loc,id) t =
+let declare_reserved_type_binding {CAst.loc;v=id} t =
if not (Id.equal id (root_of_id id)) then
user_err ?loc ~hdr:"declare_reserved_type"
((Id.print id ++ str
diff --git a/interp/reserve.mli b/interp/reserve.mli
index 4fcef23c5..5899cd628 100644
--- a/interp/reserve.mli
+++ b/interp/reserve.mli
@@ -6,9 +6,8 @@
(* * GNU Lesser General Public License Version 2.1 *)
(************************************************************************)
-open Loc
open Names
open Notation_term
-val declare_reserved_type : Id.t located list -> notation_constr -> unit
+val declare_reserved_type : Misctypes.lident list -> notation_constr -> unit
val find_reserved_type : Id.t -> notation_constr
diff --git a/interp/stdarg.mli b/interp/stdarg.mli
index ed00fe296..ea1c63b89 100644
--- a/interp/stdarg.mli
+++ b/interp/stdarg.mli
@@ -41,7 +41,7 @@ val wit_intro_pattern : (constr_expr intro_pattern_expr located, glob_constr_and
val wit_ident : Id.t uniform_genarg_type
-val wit_var : (Id.t located, Id.t located, Id.t) genarg_type
+val wit_var : (lident, lident, Id.t) genarg_type
val wit_ref : (reference, global_reference located or_var, global_reference) genarg_type
@@ -76,7 +76,7 @@ val wit_red_expr :
(glob_constr_and_expr,evaluable_global_reference and_short_name or_var,glob_constr_pattern_and_expr) red_expr_gen,
(constr,evaluable_global_reference,constr_pattern) red_expr_gen) genarg_type
-val wit_clause_dft_concl : (Names.Id.t Loc.located Locus.clause_expr,Names.Id.t Loc.located Locus.clause_expr,Names.Id.t Locus.clause_expr) genarg_type
+val wit_clause_dft_concl : (lident Locus.clause_expr, lident Locus.clause_expr, Names.Id.t Locus.clause_expr) genarg_type
(** Aliases for compatibility *)
@@ -84,7 +84,7 @@ val wit_integer : int uniform_genarg_type
val wit_preident : string uniform_genarg_type
val wit_reference : (reference, global_reference located or_var, global_reference) genarg_type
val wit_global : (reference, global_reference located or_var, global_reference) genarg_type
-val wit_clause : (Names.Id.t Loc.located Locus.clause_expr,Names.Id.t Loc.located Locus.clause_expr,Names.Id.t Locus.clause_expr) genarg_type
+val wit_clause : (lident Locus.clause_expr, lident Locus.clause_expr, Names.Id.t Locus.clause_expr) genarg_type
val wit_quantified_hypothesis : quantified_hypothesis uniform_genarg_type
val wit_intropattern : (constr_expr intro_pattern_expr located, glob_constr_and_expr intro_pattern_expr located, intro_pattern) genarg_type
val wit_redexpr :
diff --git a/interp/topconstr.mli b/interp/topconstr.mli
index 9fc02461e..66d87707c 100644
--- a/interp/topconstr.mli
+++ b/interp/topconstr.mli
@@ -6,7 +6,6 @@
(* * GNU Lesser General Public License Version 2.1 *)
(************************************************************************)
-open Loc
open Names
open Constrexpr
@@ -15,7 +14,7 @@ val asymmetric_patterns : bool ref
[@@ocaml.deprecated "use Constrexpr_ops.asymmetric_patterns"]
(** Utilities on constr_expr *)
-val split_at_annot : local_binder_expr list -> Id.t located option -> local_binder_expr list * local_binder_expr list
+val split_at_annot : local_binder_expr list -> Misctypes.lident option -> local_binder_expr list * local_binder_expr list
[@@ocaml.deprecated "use Constrexpr_ops.split_at_annot"]
val ntn_loc : ?loc:Loc.t -> constr_notation_substitution -> string -> (int * int) list
diff --git a/intf/constrexpr.ml b/intf/constrexpr.ml
index fbf9e248a..5b51953bb 100644
--- a/intf/constrexpr.ml
+++ b/intf/constrexpr.ml
@@ -46,7 +46,7 @@ type prim_token =
type instance_expr = Misctypes.glob_level list
type cases_pattern_expr_r =
- | CPatAlias of cases_pattern_expr * Id.t
+ | CPatAlias of cases_pattern_expr * lname
| CPatCstr of reference
* cases_pattern_expr list option * cases_pattern_expr list
(** [CPatCstr (_, c, Some l1, l2)] represents (@c l1) l2 *)
@@ -68,14 +68,14 @@ and cases_pattern_notation_substitution =
and constr_expr_r =
| CRef of reference * instance_expr option
- | CFix of Id.t Loc.located * fix_expr list
- | CCoFix of Id.t Loc.located * cofix_expr list
- | CProdN of binder_expr list * constr_expr
- | CLambdaN of binder_expr list * constr_expr
- | CLetIn of Name.t Loc.located * constr_expr * constr_expr option * constr_expr
+ | CFix of lident * fix_expr list
+ | CCoFix of lident * cofix_expr list
+ | CProdN of local_binder_expr list * constr_expr
+ | CLambdaN of local_binder_expr list * constr_expr
+ | CLetIn of lname * constr_expr * constr_expr option * constr_expr
| CAppExpl of (proj_flag * reference * instance_expr option) * constr_expr list
| CApp of (proj_flag * constr_expr) *
- (constr_expr * explicitation Loc.located option) list
+ (constr_expr * explicitation CAst.t option) list
| CRecord of (reference * constr_expr) list
(* representation of the "let" and "match" constructs *)
@@ -84,9 +84,9 @@ and constr_expr_r =
* case_expr list
* branch_expr list (* branches *)
- | CLetTuple of Name.t Loc.located list * (Name.t Loc.located option * constr_expr option) *
+ | CLetTuple of lname list * (lname option * constr_expr option) *
constr_expr * constr_expr
- | CIf of constr_expr * (Name.t Loc.located option * constr_expr option)
+ | CIf of constr_expr * (lname option * constr_expr option)
* constr_expr * constr_expr
| CHole of Evar_kinds.t option * intro_pattern_naming_expr * Genarg.raw_generic_argument option
| CPatVar of patvar
@@ -101,21 +101,18 @@ and constr_expr_r =
and constr_expr = constr_expr_r CAst.t
and case_expr = constr_expr (* expression that is being matched *)
- * Name.t Loc.located option (* as-clause *)
+ * lname option (* as-clause *)
* cases_pattern_expr option (* in-clause *)
and branch_expr =
- (cases_pattern_expr list list * constr_expr) Loc.located
-
-and binder_expr =
- Name.t Loc.located list * binder_kind * constr_expr
+ (cases_pattern_expr list list * constr_expr) CAst.t
and fix_expr =
- Id.t Loc.located * (Id.t Loc.located option * recursion_order_expr) *
+ lident * (lident option * recursion_order_expr) *
local_binder_expr list * constr_expr * constr_expr
and cofix_expr =
- Id.t Loc.located * local_binder_expr list * constr_expr * constr_expr
+ lident * local_binder_expr list * constr_expr * constr_expr
and recursion_order_expr =
| CStructRec
@@ -124,14 +121,15 @@ and recursion_order_expr =
(** Anonymous defs allowed ?? *)
and local_binder_expr =
- | CLocalAssum of Name.t Loc.located list * binder_kind * constr_expr
- | CLocalDef of Name.t Loc.located * constr_expr * constr_expr option
- | CLocalPattern of (cases_pattern_expr * constr_expr option) Loc.located
+ | CLocalAssum of lname list * binder_kind * constr_expr
+ | CLocalDef of lname * constr_expr * constr_expr option
+ | CLocalPattern of (cases_pattern_expr * constr_expr option) CAst.t
and constr_notation_substitution =
constr_expr list * (** for constr subterms *)
constr_expr list list * (** for recursive notations *)
- local_binder_expr list list (** for binders subexpressions *)
+ cases_pattern_expr list * (** for binders *)
+ local_binder_expr list list (** for binder lists (recursive notations) *)
type constr_pattern_expr = constr_expr
diff --git a/intf/extend.ml b/intf/extend.ml
index 5552bed55..78f0aa117 100644
--- a/intf/extend.ml
+++ b/intf/extend.ml
@@ -29,29 +29,48 @@ type production_level =
| NextLevel
| NumLevel of int
-type ('lev,'pos) constr_entry_key_gen =
- | ETName | ETReference | ETBigint
- | ETBinder of bool
- | ETConstr of ('lev * 'pos)
- | ETPattern
+type constr_as_binder_kind =
+ | AsIdent
+ | AsIdentOrPattern
+ | AsStrictPattern
+
+(** User-level types used to tell how to parse or interpret of the non-terminal *)
+
+type 'a constr_entry_key_gen =
+ | ETName
+ | ETReference
+ | ETBigint
+ | ETBinder of bool (* open list of binders if true, closed list of binders otherwise *)
+ | ETConstr of 'a
+ | ETConstrAsBinder of constr_as_binder_kind * 'a
+ | ETPattern of bool * int option (* true = strict pattern, i.e. not a single variable *)
| ETOther of string * string
- | ETConstrList of ('lev * 'pos) * Tok.t list
- | ETBinderList of bool * Tok.t list
-(** Entries level (left-hand-side of grammar rules) *)
+(** Entries level (left-hand side of grammar rules) *)
type constr_entry_key =
- (int,unit) constr_entry_key_gen
-
-(** Entries used in productions (in right-hand-side of grammar rules) *)
-
-type constr_prod_entry_key =
- (production_level,production_position) constr_entry_key_gen
+ (production_level * production_position) constr_entry_key_gen
(** Entries used in productions, vernac side (e.g. "x bigint" or "x ident") *)
type simple_constr_prod_entry_key =
- (production_level,unit) constr_entry_key_gen
+ production_level option constr_entry_key_gen
+
+(** Entries used in productions (in right-hand-side of grammar rules), to parse non-terminals *)
+
+type binder_entry_kind = ETBinderOpen | ETBinderClosed of Tok.t list
+
+type binder_target = ForBinder | ForTerm
+
+type constr_prod_entry_key =
+ | ETProdName (* Parsed as a name (ident or _) *)
+ | ETProdReference (* Parsed as a global reference *)
+ | ETProdBigint (* Parsed as an (unbounded) integer *)
+ | ETProdConstr of (production_level * production_position) (* Parsed as constr or pattern *)
+ | ETProdPattern of int (* Parsed as pattern as a binder (as subpart of a constr) *)
+ | ETProdOther of string * string (* Intended for embedding custom entries in constr or pattern *)
+ | ETProdConstrList of (production_level * production_position) * Tok.t list (* Parsed as non-empty list of constr *)
+ | ETProdBinderList of binder_entry_kind (* Parsed as non-empty list of local binders *)
(** {5 AST for user-provided entries} *)
diff --git a/intf/genredexpr.ml b/intf/genredexpr.ml
index a8c37c620..bdf3242ca 100644
--- a/intf/genredexpr.ml
+++ b/intf/genredexpr.ml
@@ -8,8 +8,6 @@
(** Reduction expressions *)
-open Names
-
(** The parsing produces initially a list of [red_atom] *)
type 'a red_atom =
@@ -52,7 +50,7 @@ type ('a,'b,'c) red_expr_gen =
type ('a,'b,'c) may_eval =
| ConstrTerm of 'a
| ConstrEval of ('a,'b,'c) red_expr_gen * 'a
- | ConstrContext of Id.t Loc.located * 'a
+ | ConstrContext of Misctypes.lident * 'a
| ConstrTypeOf of 'a
open Libnames
diff --git a/intf/glob_term.ml b/intf/glob_term.ml
index 61bbe2c26..3f48fa547 100644
--- a/intf/glob_term.ml
+++ b/intf/glob_term.ml
@@ -105,7 +105,7 @@ type cases_pattern_disjunction = [ `any ] cases_pattern_disjunction_g
type 'a extended_glob_local_binder_r =
| GLocalAssum of Name.t * binding_kind * 'a glob_constr_g
| GLocalDef of Name.t * binding_kind * 'a glob_constr_g * 'a glob_constr_g option
- | GLocalPattern of ('a cases_pattern_g * Id.t list) * Id.t * binding_kind * 'a glob_constr_g
+ | GLocalPattern of ('a cases_pattern_disjunction_g * Id.t list) * Id.t * binding_kind * 'a glob_constr_g
and 'a extended_glob_local_binder_g = ('a extended_glob_local_binder_r, 'a) DAst.t
type extended_glob_local_binder = [ `any ] extended_glob_local_binder_g
diff --git a/intf/intf.mllib b/intf/intf.mllib
index 38a2a71cc..2b8960d3f 100644
--- a/intf/intf.mllib
+++ b/intf/intf.mllib
@@ -2,9 +2,9 @@ Constrexpr
Evar_kinds
Genredexpr
Locus
+Extend
Notation_term
Decl_kinds
-Extend
Glob_term
Misctypes
Pattern
diff --git a/intf/misctypes.ml b/intf/misctypes.ml
index 33e961419..aafd61b3c 100644
--- a/intf/misctypes.ml
+++ b/intf/misctypes.ml
@@ -8,7 +8,13 @@
open Names
-(** Basic types used both in [constr_expr] and in [glob_constr] *)
+(** Basic types used both in [constr_expr], [glob_constr], and [vernacexpr] *)
+
+(** Located identifiers and objects with syntax. *)
+
+type lident = Id.t CAst.t
+type lname = Name.t CAst.t
+type lstring = string CAst.t
(** Cases pattern variables *)
@@ -101,9 +107,9 @@ type 'a with_bindings = 'a * 'a bindings
type 'a or_var =
| ArgArg of 'a
- | ArgVar of Names.Id.t Loc.located
+ | ArgVar of lident
-type 'a and_short_name = 'a * Id.t Loc.located option
+type 'a and_short_name = 'a * lident option
type 'a or_by_notation =
| AN of 'a
@@ -134,7 +140,7 @@ type multi =
type 'a core_destruction_arg =
| ElimOnConstr of 'a
- | ElimOnIdent of Id.t Loc.located
+ | ElimOnIdent of lident
| ElimOnAnonHyp of int
type 'a destruction_arg =
diff --git a/intf/notation_term.ml b/intf/notation_term.ml
index cad6f4b82..86f5adbd7 100644
--- a/intf/notation_term.ml
+++ b/intf/notation_term.ml
@@ -25,11 +25,11 @@ type notation_constr =
| NVar of Id.t
| NApp of notation_constr * notation_constr list
| NHole of Evar_kinds.t * Misctypes.intro_pattern_naming_expr * Genarg.glob_generic_argument option
- | NList of Id.t * Id.t * notation_constr * notation_constr * bool
+ | NList of Id.t * Id.t * notation_constr * notation_constr * (* associativity: *) bool
(** Part only in [glob_constr] *)
| NLambda of Name.t * notation_constr * notation_constr
| NProd of Name.t * notation_constr * notation_constr
- | NBinderList of Id.t * Id.t * notation_constr * notation_constr
+ | NBinderList of Id.t * Id.t * notation_constr * notation_constr * (* associativity: *) bool
| NLetIn of Name.t * notation_constr * notation_constr option * notation_constr
| NCases of Constr.case_style * notation_constr option *
(notation_constr * (Name.t * (inductive * Name.t list) option)) list *
@@ -60,21 +60,31 @@ type subscopes = tmp_scope_name option * scope_name list
(** Type of the meta-variables of an notation_constr: in a recursive pattern x..y,
x carries the sequence of objects bound to the list x..y *)
+
+type notation_binder_source =
+ (* This accepts only pattern *)
+ (* NtnParsedAsPattern true means only strict pattern (no single variable) at printing *)
+ | NtnParsedAsPattern of bool
+ (* This accepts only ident *)
+ | NtnParsedAsIdent
+ (* This accepts ident, or pattern, or both *)
+ | NtnBinderParsedAsConstr of Extend.constr_as_binder_kind
+
type notation_var_instance_type =
- | NtnTypeConstr | NtnTypeOnlyBinder | NtnTypeConstrList | NtnTypeBinderList
+ | NtnTypeConstr | NtnTypeBinder of notation_binder_source | NtnTypeConstrList | NtnTypeBinderList
-(** Type of variables when interpreting a constr_expr as an notation_constr:
+(** Type of variables when interpreting a constr_expr as a notation_constr:
in a recursive pattern x..y, both x and y carry the individual type
of each element of the list x..y *)
type notation_var_internalization_type =
- | NtnInternTypeConstr | NtnInternTypeBinder | NtnInternTypeIdent
+ | NtnInternTypeAny | NtnInternTypeOnlyBinder
(** This characterizes to what a notation is interpreted to *)
type interpretation =
(Id.t * (subscopes * notation_var_instance_type)) list *
notation_constr
-type reversibility_flag = bool
+type reversibility_status = APrioriReversible | HasLtac | NonInjective of Id.t list
type notation_interp_env = {
ninterp_var_type : notation_var_internalization_type Id.Map.t;
@@ -95,7 +105,7 @@ type precedence = int
type parenRelation = L | E | Any | Prec of precedence
type tolerability = precedence * parenRelation
-type level = precedence * tolerability list * notation_var_internalization_type list
+type level = precedence * tolerability list * Extend.constr_entry_key list
(** Grammar rules for a notation *)
diff --git a/intf/vernacexpr.ml b/intf/vernacexpr.ml
index 8e0fe54c5..ba28eacea 100644
--- a/intf/vernacexpr.ml
+++ b/intf/vernacexpr.ml
@@ -6,19 +6,12 @@
(* * GNU Lesser General Public License Version 2.1 *)
(************************************************************************)
-open Loc
open Names
open Misctypes
open Constrexpr
-open Decl_kinds
open Libnames
(** Vernac expressions, produced by the parser *)
-
-type lident = Id.t located
-type lname = Name.t located
-type lstring = string located
-
type class_rawexpr = FunClass | SortClass | RefClass of reference or_by_notation
(* spiwack: I'm choosing, for now, to have [goal_selector] be a
@@ -40,7 +33,8 @@ type goal_reference =
| NthGoal of int
| GoalId of Id.t
-type univ_name_list = Name.t Loc.located list
+type univ_name_list = Universes.univ_name_list
+[@@ocaml.deprecated "Use [Universes.univ_name_list]"]
type printable =
| PrintTables
@@ -56,7 +50,7 @@ type printable =
| PrintMLLoadPath
| PrintMLModules
| PrintDebugGC
- | PrintName of reference or_by_notation * univ_name_list option
+ | PrintName of reference or_by_notation * Universes.univ_name_list option
| PrintGraph
| PrintClasses
| PrintTypeClasses
@@ -72,7 +66,7 @@ type printable =
| PrintScopes
| PrintScope of string
| PrintVisibility of string option
- | PrintAbout of reference or_by_notation * univ_name_list option * goal_selector option
+ | PrintAbout of reference or_by_notation * Universes.univ_name_list option * goal_selector option
| PrintImplicit of reference or_by_notation
| PrintAssumptions of bool * bool * reference or_by_notation
| PrintStrategy of reference or_by_notation option
@@ -164,7 +158,7 @@ type option_ref_value =
(** Identifier and optional list of bound universes and constraints. *)
-type universe_decl_expr = (Id.t Loc.located list, glob_constraint list) gen_universe_decl
+type universe_decl_expr = (lident list, glob_constraint list) gen_universe_decl
type ident_decl = lident * universe_decl_expr option
type name_decl = lname * universe_decl_expr option
@@ -177,7 +171,7 @@ type definition_expr =
* constr_expr option
type fixpoint_expr =
- ident_decl * (Id.t located option * recursion_order_expr) * local_binder_expr list * constr_expr * constr_expr option
+ ident_decl * (lident option * recursion_order_expr) * local_binder_expr list * constr_expr * constr_expr option
type cofixpoint_expr =
ident_decl * local_binder_expr list * constr_expr * constr_expr option
@@ -205,7 +199,7 @@ type inductive_expr =
type one_inductive_expr =
ident_decl * local_binder_expr list * constr_expr option * constructor_expr list
-type typeclass_constraint = name_decl * binding_kind * constr_expr
+type typeclass_constraint = name_decl * Decl_kinds.binding_kind * constr_expr
and typeclass_context = typeclass_constraint list
@@ -214,13 +208,14 @@ type proof_expr =
type syntax_modifier =
| SetItemLevel of string list * Extend.production_level
+ | SetItemLevelAsBinder of string list * Extend.constr_as_binder_kind * Extend.production_level option
| SetLevel of int
| SetAssoc of Extend.gram_assoc
| SetEntryType of string * Extend.simple_constr_prod_entry_key
| SetOnlyParsing
| SetOnlyPrinting
| SetCompatVersion of Flags.compat_version
- | SetFormat of string * string located
+ | SetFormat of string * lstring
type proof_end =
| Admitted
@@ -320,7 +315,7 @@ type vernac_implicit_status = Implicit | MaximallyImplicit | NotImplicit
type vernac_argument_status = {
name : Name.t;
recarg_like : bool;
- notation_scope : string Loc.located option;
+ notation_scope : string CAst.t option;
implicit_status : vernac_implicit_status;
}
@@ -340,15 +335,15 @@ type nonrec vernac_expr =
| VernacNotationAddFormat of string * string * string
(* Gallina *)
- | VernacDefinition of (discharge * definition_object_kind) * name_decl * definition_expr
- | VernacStartTheoremProof of theorem_kind * proof_expr list
+ | VernacDefinition of (Decl_kinds.discharge * Decl_kinds.definition_object_kind) * name_decl * definition_expr
+ | VernacStartTheoremProof of Decl_kinds.theorem_kind * proof_expr list
| VernacEndProof of proof_end
| VernacExactProof of constr_expr
- | VernacAssumption of (discharge * assumption_object_kind) *
+ | VernacAssumption of (Decl_kinds.discharge * Decl_kinds.assumption_object_kind) *
inline * (ident_decl list * constr_expr) with_coercion list
- | VernacInductive of cumulative_inductive_parsing_flag * private_flag * inductive_flag * (inductive_expr * decl_notation list) list
- | VernacFixpoint of discharge * (fixpoint_expr * decl_notation list) list
- | VernacCoFixpoint of discharge * (cofixpoint_expr * decl_notation list) list
+ | VernacInductive of cumulative_inductive_parsing_flag * Decl_kinds.private_flag * inductive_flag * (inductive_expr * decl_notation list) list
+ | VernacFixpoint of Decl_kinds.discharge * (fixpoint_expr * decl_notation list) list
+ | VernacCoFixpoint of Decl_kinds.discharge * (cofixpoint_expr * decl_notation list) list
| VernacScheme of (lident option * scheme) list
| VernacCombinedScheme of lident * lident list
| VernacUniverse of lident list
@@ -415,7 +410,7 @@ type nonrec vernac_expr =
| VernacCreateHintDb of string * bool
| VernacRemoveHints of string list * reference list
| VernacHints of string list * hints_expr
- | VernacSyntacticDefinition of Id.t located * (Id.t list * constr_expr) *
+ | VernacSyntacticDefinition of lident * (Id.t list * constr_expr) *
onlyparsing_flag
| VernacDeclareImplicits of reference or_by_notation *
(explicitation * bool * bool) list list
@@ -481,8 +476,8 @@ type vernac_control =
| VernacExpr of vernac_flag list * vernac_expr
(* boolean is true when the `-time` batch-mode command line flag was set.
the flag is used to print differently in `-time` vs `Time foo` *)
- | VernacTime of bool * vernac_control located
- | VernacRedirect of string * vernac_control located
+ | VernacTime of bool * vernac_control CAst.t
+ | VernacRedirect of string * vernac_control CAst.t
| VernacTimeout of int * vernac_control
| VernacFail of vernac_control
diff --git a/kernel/subtyping.ml b/kernel/subtyping.ml
index d0d5cb1d5..e95d5d2b5 100644
--- a/kernel/subtyping.ml
+++ b/kernel/subtyping.ml
@@ -118,6 +118,15 @@ let check_inductive cst env mp1 l info1 mp2 mib2 spec2 subst1 subst2 reso1 reso2
let env = check_polymorphic_instance error env auctx auctx' in
env, Univ.make_abstract_instance auctx'
| Cumulative_ind cumi, Cumulative_ind cumi' ->
+ (** Currently there is no way to control variance of inductive types, but
+ just in case we require that they are in a subtyping relation. *)
+ let () =
+ let v = ACumulativityInfo.variance cumi in
+ let v' = ACumulativityInfo.variance cumi' in
+ if not (Array.for_all2 Variance.check_subtype v' v) then
+ CErrors.anomaly Pp.(str "Variance of " ++ KerName.print kn1 ++
+ str " is not compatible with the one of " ++ KerName.print kn2)
+ in
let auctx = Univ.ACumulativityInfo.univ_context cumi in
let auctx' = Univ.ACumulativityInfo.univ_context cumi' in
let env = check_polymorphic_instance error env auctx auctx' in
diff --git a/kernel/univ.ml b/kernel/univ.ml
index fbb047364..c42b66749 100644
--- a/kernel/univ.ml
+++ b/kernel/univ.ml
@@ -759,6 +759,13 @@ struct
| Invariant, _ | _, Invariant -> Invariant
| Covariant, Covariant -> Covariant
+ let check_subtype x y = match x, y with
+ | (Irrelevant | Covariant | Invariant), Irrelevant -> true
+ | Irrelevant, Covariant -> false
+ | (Covariant | Invariant), Covariant -> true
+ | (Irrelevant | Covariant), Invariant -> false
+ | Invariant, Invariant -> true
+
let pr = function
| Irrelevant -> str "*"
| Covariant -> str "+"
diff --git a/kernel/univ.mli b/kernel/univ.mli
index c45ebe21c..74d1bfd3a 100644
--- a/kernel/univ.mli
+++ b/kernel/univ.mli
@@ -253,6 +253,9 @@ sig
A'] as opposed to [A' <= A]. *)
type t = Irrelevant | Covariant | Invariant
+ (** [check_subtype x y] holds if variance [y] is also an instance of [x] *)
+ val check_subtype : t -> t -> bool
+
val sup : t -> t -> t
val pr : t -> Pp.t
diff --git a/library/declaremods.ml b/library/declaremods.ml
index 28a04252a..291039d19 100644
--- a/library/declaremods.ml
+++ b/library/declaremods.ml
@@ -451,7 +451,7 @@ let intern_arg interp_modast (acc, cst) (idl,(typ,ann)) =
let env = Global.env () in
let sobjs = get_module_sobjs false env inl mty in
let mp0 = get_module_path mty in
- let fold acc (_, id) =
+ let fold acc {CAst.v=id} =
let dir = DirPath.make [id] in
let mbid = MBId.make lib_dir id in
let mp = MPbound mbid in
@@ -982,8 +982,7 @@ type 'modast module_interpretor =
Entries.module_struct_entry * Misctypes.module_kind * Univ.ContextSet.t
type 'modast module_params =
- (Id.t Loc.located list * ('modast * inline)) list
-
+ (lident list * ('modast * inline)) list
(** {6 Debug} *)
diff --git a/library/declaremods.mli b/library/declaremods.mli
index 0df55f34d..db2893376 100644
--- a/library/declaremods.mli
+++ b/library/declaremods.mli
@@ -16,7 +16,7 @@ type 'modast module_interpretor =
Entries.module_struct_entry * Misctypes.module_kind * Univ.ContextSet.t
type 'modast module_params =
- (Id.t Loc.located list * ('modast * inline)) list
+ (Misctypes.lident list * ('modast * inline)) list
(** [declare_module interp_modast id fargs typ exprs]
declares module [id], with structure constructed by [interp_modast]
diff --git a/parsing/egramcoq.ml b/parsing/egramcoq.ml
index ea6266dd4..cad837d08 100644
--- a/parsing/egramcoq.ml
+++ b/parsing/egramcoq.ml
@@ -226,14 +226,14 @@ type _ target =
type prod_info = production_level * production_position
type (_, _) entry =
-| TTName : ('self, Name.t Loc.located) entry
+| TTName : ('self, Misctypes.lname) entry
| TTReference : ('self, reference) entry
| TTBigint : ('self, Constrexpr.raw_natural_number) entry
-| TTBinder : ('self, local_binder_expr list) entry
| TTConstr : prod_info * 'r target -> ('r, 'r) entry
| TTConstrList : prod_info * Tok.t list * 'r target -> ('r, 'r list) entry
-| TTBinderListT : ('self, local_binder_expr list) entry
-| TTBinderListF : Tok.t list -> ('self, local_binder_expr list list) entry
+| TTPattern : int -> ('self, cases_pattern_expr) entry
+| TTOpenBinderList : ('self, local_binder_expr list) entry
+| TTClosedBinderList : Tok.t list -> ('self, local_binder_expr list list) entry
type _ any_entry = TTAny : ('s, 'r) entry -> 's any_entry
@@ -289,40 +289,34 @@ let symbol_of_entry : type s r. _ -> _ -> (s, r) entry -> (s, r) symbol = fun as
Alist1 (symbol_of_target typ' assoc from forpat)
| TTConstrList (typ', tkl, forpat) ->
Alist1sep (symbol_of_target typ' assoc from forpat, make_sep_rules tkl)
-| TTBinderListF [] -> Alist1 (Aentry Constr.binder)
-| TTBinderListF tkl -> Alist1sep (Aentry Constr.binder, make_sep_rules tkl)
+| TTPattern p -> Aentryl (Constr.pattern, p)
+| TTClosedBinderList [] -> Alist1 (Aentry Constr.binder)
+| TTClosedBinderList tkl -> Alist1sep (Aentry Constr.binder, make_sep_rules tkl)
| TTName -> Aentry Prim.name
-| TTBinder -> Aentry Constr.binder
-| TTBinderListT -> Aentry Constr.open_binders
+| TTOpenBinderList -> Aentry Constr.open_binders
| TTBigint -> Aentry Prim.bigint
| TTReference -> Aentry Constr.global
let interp_entry forpat e = match e with
-| ETName -> TTAny TTName
-| ETReference -> TTAny TTReference
-| ETBigint -> TTAny TTBigint
-| ETBinder true -> anomaly (Pp.str "Should occur only as part of BinderList.")
-| ETBinder false -> TTAny TTBinder
-| ETConstr p -> TTAny (TTConstr (p, forpat))
-| ETPattern -> assert false (** not used *)
-| ETOther _ -> assert false (** not used *)
-| ETConstrList (p, tkl) -> TTAny (TTConstrList (p, tkl, forpat))
-| ETBinderList (true, []) -> TTAny TTBinderListT
-| ETBinderList (true, _) -> assert false
-| ETBinderList (false, tkl) -> TTAny (TTBinderListF tkl)
-
-let constr_expr_of_name (loc,na) = CAst.make ?loc @@ match na with
- | Anonymous -> CHole (None,Misctypes.IntroAnonymous,None)
- | Name id -> CRef (Ident (Loc.tag ?loc id), None)
-
-let cases_pattern_expr_of_name (loc,na) = CAst.make ?loc @@ match na with
+| ETProdName -> TTAny TTName
+| ETProdReference -> TTAny TTReference
+| ETProdBigint -> TTAny TTBigint
+| ETProdConstr p -> TTAny (TTConstr (p, forpat))
+| ETProdPattern p -> TTAny (TTPattern p)
+| ETProdOther _ -> assert false (** not used *)
+| ETProdConstrList (p, tkl) -> TTAny (TTConstrList (p, tkl, forpat))
+| ETProdBinderList ETBinderOpen -> TTAny TTOpenBinderList
+| ETProdBinderList (ETBinderClosed tkl) -> TTAny (TTClosedBinderList tkl)
+
+let cases_pattern_expr_of_name { CAst.loc; v = na } = CAst.make ?loc @@ match na with
| Anonymous -> CPatAtom None
| Name id -> CPatAtom (Some (Ident (Loc.tag ?loc id)))
type 'r env = {
constrs : 'r list;
constrlists : 'r list list;
- binders : (local_binder_expr list * bool) list;
+ binders : cases_pattern_expr list;
+ binderlists : local_binder_expr list list;
}
let push_constr subst v = { subst with constrs = v :: subst.constrs }
@@ -332,12 +326,16 @@ match e with
| TTConstr _ -> push_constr subst v
| TTName ->
begin match forpat with
- | ForConstr -> push_constr subst (constr_expr_of_name v)
+ | ForConstr -> { subst with binders = cases_pattern_expr_of_name v :: subst.binders }
| ForPattern -> push_constr subst (cases_pattern_expr_of_name v)
end
-| TTBinder -> { subst with binders = (v, true) :: subst.binders }
-| TTBinderListT -> { subst with binders = (v, true) :: subst.binders }
-| TTBinderListF _ -> { subst with binders = (List.flatten v, false) :: subst.binders }
+| TTPattern _ ->
+ begin match forpat with
+ | ForConstr -> { subst with binders = v :: subst.binders }
+ | ForPattern -> push_constr subst v
+ end
+| TTOpenBinderList -> { subst with binderlists = v :: subst.binderlists }
+| TTClosedBinderList _ -> { subst with binderlists = List.flatten v :: subst.binderlists }
| TTBigint ->
begin match forpat with
| ForConstr -> push_constr subst (CAst.make @@ CPrim (Numeral (v,true)))
@@ -437,11 +435,9 @@ let rec pure_sublevels : type a b c. int option -> (a, b, c) rule -> int list =
let make_act : type r. r target -> _ -> r gen_eval = function
| ForConstr -> fun notation loc env ->
- let env = (env.constrs, env.constrlists, List.map fst env.binders) in
- CAst.make ~loc @@ CNotation (notation , env)
+ let env = (env.constrs, env.constrlists, env.binders, env.binderlists) in
+ CAst.make ~loc @@ CNotation (notation, env)
| ForPattern -> fun notation loc env ->
- let invalid = List.exists (fun (_, b) -> not b) env.binders in
- let () = if invalid then Constrexpr_ops.error_invalid_pattern_notation ~loc () in
let env = (env.constrs, env.constrlists) in
CAst.make ~loc @@ CPatNotation (notation, env, [])
@@ -457,7 +453,7 @@ let extend_constr state forpat ng =
let needed_levels, state = register_empty_levels state isforpat pure_sublevels in
let (pos,p4assoc,name,reinit), state = find_position state isforpat assoc level in
let empty_rules = List.map (prepare_empty_levels isforpat) needed_levels in
- let empty = { constrs = []; constrlists = []; binders = [] } in
+ let empty = { constrs = []; constrlists = []; binders = []; binderlists = [] } in
let act = ty_eval r (make_act forpat ng.notgram_notation) empty in
let rule = (name, p4assoc, [Rule (symbs, act)]) in
let r = ExtendRule (entry, reinit, (pos, [rule])) in
diff --git a/parsing/g_constr.ml4 b/parsing/g_constr.ml4
index db68a75e0..8a1e6d121 100644
--- a/parsing/g_constr.ml4
+++ b/parsing/g_constr.ml4
@@ -36,21 +36,21 @@ let mk_cast = function
let loc = Loc.merge_opt (constr_loc c) (constr_loc ty)
in CAst.make ?loc @@ CCast(c, CastConv ty)
-let binder_of_name expl (loc,na) =
- CLocalAssum ([loc, na], Default expl,
+let binder_of_name expl { CAst.loc = loc; v = na } =
+ CLocalAssum ([CAst.make ?loc na], Default expl,
CAst.make ?loc @@ CHole (Some (Evar_kinds.BinderType na), IntroAnonymous, None))
let binders_of_names l =
List.map (binder_of_name Explicit) l
-let mk_fixb (id,bl,ann,body,(loc,tyc)) =
+let mk_fixb (id,bl,ann,body,(loc,tyc)) : fix_expr =
let ty = match tyc with
Some ty -> ty
| None -> CAst.make @@ CHole (None, IntroAnonymous, None) in
(id,ann,bl,ty,body)
-let mk_cofixb (id,bl,ann,body,(loc,tyc)) =
- let _ = Option.map (fun (aloc,_) ->
+let mk_cofixb (id,bl,ann,body,(loc,tyc)) : cofix_expr =
+ let _ = Option.map (fun { CAst.loc = aloc } ->
CErrors.user_err ?loc:aloc
~hdr:"Constr:mk_cofixb"
(Pp.str"Annotation forbidden in cofix expression.")) (fst ann) in
@@ -61,10 +61,10 @@ let mk_cofixb (id,bl,ann,body,(loc,tyc)) =
let mk_fix(loc,kw,id,dcls) =
if kw then
- let fb = List.map mk_fixb dcls in
+ let fb : fix_expr list = List.map mk_fixb dcls in
CAst.make ~loc @@ CFix(id,fb)
else
- let fb = List.map mk_cofixb dcls in
+ let fb : cofix_expr list = List.map mk_cofixb dcls in
CAst.make ~loc @@ CCoFix(id,fb)
let mk_single_fix (loc,kw,dcl) =
@@ -120,7 +120,7 @@ let name_colon =
| _ -> err ())
| _ -> err ())
-let aliasvar = function { CAst.loc = loc; CAst.v = CPatAlias (_, id) } -> Some (loc,Name id) | _ -> None
+let aliasvar = function { CAst.v = CPatAlias (_, na) } -> Some na | _ -> None
GEXTEND Gram
GLOBAL: binder_constr lconstr constr operconstr universe_level sort sort_family
@@ -131,7 +131,7 @@ GEXTEND Gram
[ [ id = Prim.ident -> id ] ]
;
Prim.name:
- [ [ "_" -> Loc.tag ~loc:!@loc Anonymous ] ]
+ [ [ "_" -> CAst.make ~loc:!@loc Anonymous ] ]
;
global:
[ [ r = Prim.reference -> r ] ]
@@ -196,8 +196,9 @@ GEXTEND Gram
| "10" LEFTA
[ f=operconstr; args=LIST1 appl_arg -> CAst.make ~loc:(!@loc) @@ CApp((None,f),args)
| "@"; f=global; i = instance; args=LIST0 NEXT -> CAst.make ~loc:!@loc @@ CAppExpl((None,f,i),args)
- | "@"; (locid,id) = pattern_identref; args=LIST1 identref ->
- let args = List.map (fun x -> CAst.make @@ CRef (Ident x,None), None) args in
+ | "@"; lid = pattern_identref; args=LIST1 identref ->
+ let { CAst.loc = locid; v = id } = lid in
+ let args = List.map (fun x -> CAst.make @@ CRef (Ident Loc.(tag ?loc:x.CAst.loc x.CAst.v), None), None) args in
CAst.make ~loc:(!@loc) @@ CApp((None, CAst.make ?loc:locid @@ CPatVar id),args) ]
| "9"
[ ".."; c = operconstr LEVEL "0"; ".." ->
@@ -216,9 +217,11 @@ GEXTEND Gram
| "("; c = operconstr LEVEL "200"; ")" ->
(match c.CAst.v with
| CPrim (Numeral (n,true)) ->
- CAst.make ~loc:(!@loc) @@ CNotation("( _ )",([c],[],[]))
+ CAst.make ~loc:(!@loc) @@ CNotation("( _ )",([c],[],[],[]))
| _ -> c)
| "{|"; c = record_declaration; "|}" -> c
+ | "{"; c = binder_constr ; "}" ->
+ CAst.make ~loc:(!@loc) @@ CNotation(("{ _ }"),([c],[],[],[]))
| "`{"; c = operconstr LEVEL "200"; "}" ->
CAst.make ~loc:(!@loc) @@ CGeneralization (Implicit, None, c)
| "`("; c = operconstr LEVEL "200"; ")" ->
@@ -254,11 +257,11 @@ GEXTEND Gram
Option.map (mkCProdN ?loc:(fst ty) bl) (snd ty), c2)
| "let"; fx = single_fix; "in"; c = operconstr LEVEL "200" ->
let fixp = mk_single_fix fx in
- let (li,id) = match fixp.CAst.v with
+ let { CAst.loc = li; v = id } = match fixp.CAst.v with
CFix(id,_) -> id
| CCoFix(id,_) -> id
| _ -> assert false in
- CAst.make ~loc:!@loc @@ CLetIn((li,Name id),fixp,None,c)
+ CAst.make ~loc:!@loc @@ CLetIn( CAst.make ?loc:li @@ Name id,fixp,None,c)
| "let"; lb = ["("; l=LIST0 name SEP ","; ")" -> l | "()" -> []];
po = return_type;
":="; c1 = operconstr LEVEL "200"; "in";
@@ -267,17 +270,17 @@ GEXTEND Gram
| "let"; "'"; p=pattern; ":="; c1 = operconstr LEVEL "200";
"in"; c2 = operconstr LEVEL "200" ->
CAst.make ~loc:!@loc @@
- CCases (LetPatternStyle, None, [c1, None, None], [Loc.tag ~loc:!@loc ([[p]], c2)])
+ CCases (LetPatternStyle, None, [c1, None, None], [CAst.make ~loc:!@loc ([[p]], c2)])
| "let"; "'"; p=pattern; ":="; c1 = operconstr LEVEL "200";
rt = case_type; "in"; c2 = operconstr LEVEL "200" ->
CAst.make ~loc:!@loc @@
- CCases (LetPatternStyle, Some rt, [c1, aliasvar p, None], [Loc.tag ~loc:!@loc ([[p]], c2)])
+ CCases (LetPatternStyle, Some rt, [c1, aliasvar p, None], [CAst.make ~loc:!@loc ([[p]], c2)])
| "let"; "'"; p=pattern; "in"; t = pattern LEVEL "200";
":="; c1 = operconstr LEVEL "200"; rt = case_type;
"in"; c2 = operconstr LEVEL "200" ->
CAst.make ~loc:!@loc @@
- CCases (LetPatternStyle, Some rt, [c1, aliasvar p, Some t], [Loc.tag ~loc:!@loc ([[p]], c2)])
+ CCases (LetPatternStyle, Some rt, [c1, aliasvar p, Some t], [CAst.make ~loc:!@loc ([[p]], c2)])
| "if"; c=operconstr LEVEL "200"; po = return_type;
"then"; b1=operconstr LEVEL "200";
"else"; b2=operconstr LEVEL "200" ->
@@ -286,7 +289,7 @@ GEXTEND Gram
;
appl_arg:
[ [ id = lpar_id_coloneq; c=lconstr; ")" ->
- (c,Some (Loc.tag ~loc:!@loc @@ ExplByName id))
+ (c,Some (CAst.make ~loc:!@loc @@ ExplByName id))
| c=operconstr LEVEL "9" -> (c,None) ] ]
;
atomic_constr:
@@ -366,7 +369,7 @@ GEXTEND Gram
;
eqn:
[ [ pll = LIST1 mult_pattern SEP "|";
- "=>"; rhs = lconstr -> (Loc.tag ~loc:!@loc (pll,rhs)) ] ]
+ "=>"; rhs = lconstr -> (CAst.make ~loc:!@loc (pll,rhs)) ] ]
;
record_pattern:
[ [ id = global; ":="; pat = pattern -> (id, pat) ] ]
@@ -385,19 +388,9 @@ GEXTEND Gram
| "99" RIGHTA [ ]
| "90" RIGHTA [ ]
| "10" LEFTA
- [ p = pattern; "as"; id = ident ->
- CAst.make ~loc:!@loc @@ CPatAlias (p, id)
- | p = pattern; lp = LIST1 NEXT ->
- (let open CAst in match p with
- | { v = CPatAtom (Some r) } -> CAst.make ~loc:!@loc @@ CPatCstr (r, None, lp)
- | { v = CPatCstr (r, None, l2); loc } ->
- CErrors.user_err ?loc ~hdr:"compound_pattern"
- (Pp.str "Nested applications not supported.")
- | { v = CPatCstr (r, l1, l2) } -> CAst.make ~loc:!@loc @@ CPatCstr (r, l1 , l2@lp)
- | { v = CPatNotation (n, s, l) } -> CAst.make ~loc:!@loc @@ CPatNotation (n , s, l@lp)
- | _ -> CErrors.user_err
- ?loc:(cases_pattern_expr_loc p) ~hdr:"compound_pattern"
- (Pp.str "Such pattern cannot have arguments."))
+ [ p = pattern; "as"; na = name ->
+ CAst.make ~loc:!@loc @@ CPatAlias (p, na)
+ | p = pattern; lp = LIST1 NEXT -> mkAppPattern ~loc:!@loc p lp
| "@"; r = Prim.reference; lp = LIST0 NEXT ->
CAst.make ~loc:!@loc @@ CPatCstr (r, Some lp, []) ]
| "1" LEFTA
@@ -428,7 +421,8 @@ GEXTEND Gram
(fun na -> CLocalAssum (na::nal,Default Implicit,c))
| nal=LIST1 name; "}" ->
(fun na -> CLocalAssum (na::nal,Default Implicit,
- CAst.make ?loc:(Loc.merge_opt (fst na) (Some !@loc)) @@ CHole (Some (Evar_kinds.BinderType (snd na)), IntroAnonymous, None)))
+ CAst.make ?loc:(Loc.merge_opt na.CAst.loc (Some !@loc)) @@
+ CHole (Some (Evar_kinds.BinderType na.CAst.v), IntroAnonymous, None)))
| ":"; c=lconstr; "}" ->
(fun na -> CLocalAssum ([na],Default Implicit,c))
] ]
@@ -441,7 +435,7 @@ GEXTEND Gram
] ]
;
impl_name_head:
- [ [ id = impl_ident_head -> (Loc.tag ~loc:!@loc @@ Name id) ] ]
+ [ [ id = impl_ident_head -> (CAst.make ~loc:!@loc @@ Name id) ] ]
;
binders_fixannot:
[ [ na = impl_name_head; assum = impl_ident_tail; bl = binders_fixannot ->
@@ -461,7 +455,7 @@ GEXTEND Gram
| id = name; idl = LIST0 name; bl = binders ->
binders_of_names (id::idl) @ bl
| id1 = name; ".."; id2 = name ->
- [CLocalAssum ([id1;(Loc.tag ~loc:!@loc (Name ldots_var));id2],
+ [CLocalAssum ([id1;(CAst.make ~loc:!@loc (Name ldots_var));id2],
Default Explicit, CAst.make ~loc:!@loc @@ CHole (None, IntroAnonymous, None))]
| bl = closed_binder; bl' = binders ->
bl@bl'
@@ -503,17 +497,17 @@ GEXTEND Gram
| CPatCast (p, ty) -> (p, Some ty)
| _ -> (p, None)
in
- [CLocalPattern (Loc.tag ~loc:!@loc (p, ty))]
+ [CLocalPattern (CAst.make ~loc:!@loc (p, ty))]
] ]
;
typeclass_constraint:
- [ [ "!" ; c = operconstr LEVEL "200" -> (Loc.tag ~loc:!@loc Anonymous), true, c
+ [ [ "!" ; c = operconstr LEVEL "200" -> (CAst.make ~loc:!@loc Anonymous), true, c
| "{"; id = name; "}"; ":" ; expl = [ "!" -> true | -> false ] ; c = operconstr LEVEL "200" ->
id, expl, c
| iid=name_colon ; expl = [ "!" -> true | -> false ] ; c = operconstr LEVEL "200" ->
- (Loc.tag ~loc:!@loc iid), expl, c
+ (CAst.make ~loc:!@loc iid), expl, c
| c = operconstr LEVEL "200" ->
- (Loc.tag ~loc:!@loc Anonymous), false, c
+ (CAst.make ~loc:!@loc Anonymous), false, c
] ]
;
diff --git a/parsing/g_prim.ml4 b/parsing/g_prim.ml4
index 891c232ee..0b7efe739 100644
--- a/parsing/g_prim.ml4
+++ b/parsing/g_prim.ml4
@@ -43,13 +43,13 @@ GEXTEND Gram
[ [ LEFTQMARK; id = ident -> id ] ]
;
pattern_identref:
- [ [ id = pattern_ident -> Loc.tag ~loc:!@loc id ] ]
+ [ [ id = pattern_ident -> CAst.make ~loc:!@loc id ] ]
;
var: (* as identref, but interpret as a term identifier in ltac *)
- [ [ id = ident -> Loc.tag ~loc:!@loc id ] ]
+ [ [ id = ident -> CAst.make ~loc:!@loc id ] ]
;
identref:
- [ [ id = ident -> Loc.tag ~loc:!@loc id ] ]
+ [ [ id = ident -> CAst.make ~loc:!@loc id ] ]
;
field:
[ [ s = FIELD -> Id.of_string s ] ]
@@ -70,8 +70,8 @@ GEXTEND Gram
] ]
;
name:
- [ [ IDENT "_" -> Loc.tag ~loc:!@loc Anonymous
- | id = ident -> Loc.tag ~loc:!@loc @@ Name id ] ]
+ [ [ IDENT "_" -> CAst.make ~loc:!@loc Anonymous
+ | id = ident -> CAst.make ~loc:!@loc @@ Name id ] ]
;
reference:
[ [ id = ident; (l,id') = fields ->
@@ -95,7 +95,7 @@ GEXTEND Gram
] ]
;
ne_lstring:
- [ [ s = ne_string -> Loc.tag ~loc:!@loc s ] ]
+ [ [ s = ne_string -> CAst.make ~loc:!@loc s ] ]
;
dirpath:
[ [ id = ident; l = LIST0 field ->
@@ -105,7 +105,7 @@ GEXTEND Gram
[ [ s = STRING -> s ] ]
;
lstring:
- [ [ s = string -> (Loc.tag ~loc:!@loc s) ] ]
+ [ [ s = string -> (CAst.make ~loc:!@loc s) ] ]
;
integer:
[ [ i = INT -> my_int_of_string (!@loc) i
diff --git a/parsing/g_proofs.ml4 b/parsing/g_proofs.ml4
index 1c3ba7837..482373150 100644
--- a/parsing/g_proofs.ml4
+++ b/parsing/g_proofs.ml4
@@ -29,7 +29,7 @@ GEXTEND Gram
;
command:
[ [ IDENT "Goal"; c = lconstr ->
- VernacDefinition (Decl_kinds.(NoDischarge, Definition), ((Loc.tag ~loc:!@loc Names.Anonymous), None), ProveBody ([], c))
+ VernacDefinition (Decl_kinds.(NoDischarge, Definition), ((CAst.make ~loc:!@loc Names.Anonymous), None), ProveBody ([], c))
| IDENT "Proof" -> VernacProof (None,None)
| IDENT "Proof" ; IDENT "Mode" ; mn = string -> VernacProofMode mn
| IDENT "Proof"; c = lconstr -> VernacExactProof c
diff --git a/parsing/g_vernac.ml4 b/parsing/g_vernac.ml4
index d42b5f622..93e534e0b 100644
--- a/parsing/g_vernac.ml4
+++ b/parsing/g_vernac.ml4
@@ -115,7 +115,7 @@ GEXTEND Gram
;
located_vernac:
- [ [ v = vernac_control -> Loc.tag ~loc:!@loc v ] ]
+ [ [ v = vernac_control -> CAst.make ~loc:!@loc v ] ]
;
END
@@ -134,7 +134,7 @@ let test_plural_form_types loc kwd = function
| _ -> ()
let lname_of_lident : lident -> lname =
- Loc.map (fun s -> Name s)
+ CAst.map (fun s -> Name s)
let name_of_ident_decl : ident_decl -> name_decl =
on_fst lname_of_lident
@@ -629,12 +629,12 @@ GEXTEND Gram
VernacCanonical (ByNotation ntn)
| IDENT "Canonical"; IDENT "Structure"; qid = global; d = def_body ->
let s = coerce_reference_to_id qid in
- VernacDefinition ((NoDischarge,CanonicalStructure),((Loc.tag (Name s)),None),d)
+ VernacDefinition ((NoDischarge,CanonicalStructure),((CAst.make (Name s)),None),d)
(* Coercions *)
| IDENT "Coercion"; qid = global; d = def_body ->
let s = coerce_reference_to_id qid in
- VernacDefinition ((NoDischarge,Coercion),((Loc.tag (Name s)),None),d)
+ VernacDefinition ((NoDischarge,Coercion),((CAst.make (Name s)),None),d)
| IDENT "Identity"; IDENT "Coercion"; f = identref; ":";
s = class_rawexpr; ">->"; t = class_rawexpr ->
VernacIdentityCoercion (f, s, t)
@@ -745,7 +745,7 @@ GEXTEND Gram
;
argument_spec: [
[ b = OPT "!"; id = name ; s = OPT scope ->
- snd id, not (Option.is_empty b), Option.map (fun x -> Loc.tag ~loc:!@loc x) s
+ id.CAst.v, not (Option.is_empty b), Option.map (fun x -> CAst.make ~loc:!@loc x) s
]
];
(* List of arguments implicit status, scope, modifiers *)
@@ -758,7 +758,7 @@ GEXTEND Gram
| "/" -> [`Slash]
| "("; items = LIST1 argument_spec; ")"; sc = OPT scope ->
let f x = match sc, x with
- | None, x -> x | x, None -> Option.map (fun y -> Loc.tag ~loc:!@loc y) x
+ | None, x -> x | x, None -> Option.map (fun y -> CAst.make ~loc:!@loc y) x
| Some _, Some _ -> user_err Pp.(str "scope declared twice") in
List.map (fun (name,recarg_like,notation_scope) ->
`Id { name=name; recarg_like=recarg_like;
@@ -766,7 +766,7 @@ GEXTEND Gram
implicit_status = NotImplicit}) items
| "["; items = LIST1 argument_spec; "]"; sc = OPT scope ->
let f x = match sc, x with
- | None, x -> x | x, None -> Option.map (fun y -> Loc.tag ~loc:!@loc y) x
+ | None, x -> x | x, None -> Option.map (fun y -> CAst.make ~loc:!@loc y) x
| Some _, Some _ -> user_err Pp.(str "scope declared twice") in
List.map (fun (name,recarg_like,notation_scope) ->
`Id { name=name; recarg_like=recarg_like;
@@ -774,7 +774,7 @@ GEXTEND Gram
implicit_status = Implicit}) items
| "{"; items = LIST1 argument_spec; "}"; sc = OPT scope ->
let f x = match sc, x with
- | None, x -> x | x, None -> Option.map (fun y -> Loc.tag ~loc:!@loc y) x
+ | None, x -> x | x, None -> Option.map (fun y -> CAst.make ~loc:!@loc y) x
| Some _, Some _ -> user_err Pp.(str "scope declared twice") in
List.map (fun (name,recarg_like,notation_scope) ->
`Id { name=name; recarg_like=recarg_like;
@@ -784,11 +784,11 @@ GEXTEND Gram
];
(* Same as [argument_spec_block], but with only implicit status and names *)
more_implicits_block: [
- [ name = name -> [(snd name, Vernacexpr.NotImplicit)]
+ [ name = name -> [(name.CAst.v, Vernacexpr.NotImplicit)]
| "["; items = LIST1 name; "]" ->
- List.map (fun name -> (snd name, Vernacexpr.Implicit)) items
+ List.map (fun name -> (name.CAst.v, Vernacexpr.Implicit)) items
| "{"; items = LIST1 name; "}" ->
- List.map (fun name -> (snd name, Vernacexpr.MaximallyImplicit)) items
+ List.map (fun name -> (name.CAst.v, Vernacexpr.MaximallyImplicit)) items
]
];
strategy_level:
@@ -800,9 +800,9 @@ GEXTEND Gram
;
instance_name:
[ [ name = ident_decl; sup = OPT binders ->
- (let ((loc,id),l) = name in ((loc, Name id),l)),
+ (CAst.map (fun id -> Name id) (fst name), snd name),
(Option.default [] sup)
- | -> ((Loc.tag ~loc:!@loc Anonymous), None), [] ] ]
+ | -> ((CAst.make ~loc:!@loc Anonymous), None), [] ] ]
;
hint_info:
[ [ "|"; i = OPT natural; pat = OPT constr_pattern ->
@@ -1134,8 +1134,8 @@ GEXTEND Gram
| IDENT "Reserved"; IDENT "Infix"; s = ne_lstring;
l = [ "("; l = LIST1 syntax_modifier SEP ","; ")" -> l | -> [] ] ->
- let (loc,s) = s in
- VernacSyntaxExtension (true,((loc,"x '"^s^"' y"),l))
+ let s = CAst.map (fun s -> "x '"^s^"' y") s in
+ VernacSyntaxExtension (true,(s,l))
| IDENT "Reserved"; IDENT "Notation";
s = ne_lstring;
@@ -1166,14 +1166,16 @@ GEXTEND Gram
| IDENT "only"; IDENT "parsing" -> SetOnlyParsing
| IDENT "compat"; s = STRING ->
SetCompatVersion (parse_compat_version s)
- | IDENT "format"; s1 = [s = STRING -> Loc.tag ~loc:!@loc s];
- s2 = OPT [s = STRING -> Loc.tag ~loc:!@loc s] ->
+ | IDENT "format"; s1 = [s = STRING -> CAst.make ~loc:!@loc s];
+ s2 = OPT [s = STRING -> CAst.make ~loc:!@loc s] ->
begin match s1, s2 with
- | (_,k), Some s -> SetFormat(k,s)
+ | { CAst.v = k }, Some s -> SetFormat(k,s)
| s, None -> SetFormat ("text",s) end
| x = IDENT; ","; l = LIST1 [id = IDENT -> id ] SEP ","; "at";
lev = level -> SetItemLevel (x::l,lev)
| x = IDENT; "at"; lev = level -> SetItemLevel ([x],lev)
+ | x = IDENT; "at"; lev = level; b = constr_as_binder_kind -> SetItemLevelAsBinder ([x],b,Some lev)
+ | x = IDENT; b = constr_as_binder_kind -> SetItemLevelAsBinder ([x],b,None)
| x = IDENT; typ = syntax_extension_type -> SetEntryType (x,typ)
] ]
;
@@ -1181,7 +1183,20 @@ GEXTEND Gram
[ [ IDENT "ident" -> ETName | IDENT "global" -> ETReference
| IDENT "bigint" -> ETBigint
| IDENT "binder" -> ETBinder true
+ | IDENT "constr"; n = OPT at_level; b = constr_as_binder_kind -> ETConstrAsBinder (b,n)
+ | IDENT "pattern" -> ETPattern (false,None)
+ | IDENT "pattern"; "at"; IDENT "level"; n = natural -> ETPattern (false,Some n)
+ | IDENT "strict"; IDENT "pattern" -> ETPattern (true,None)
+ | IDENT "strict"; IDENT "pattern"; "at"; IDENT "level"; n = natural -> ETPattern (true,Some n)
| IDENT "closed"; IDENT "binder" -> ETBinder false
] ]
;
+ at_level:
+ [ [ "at"; n = level -> n ] ]
+ ;
+ constr_as_binder_kind:
+ [ [ "as"; IDENT "ident" -> AsIdent
+ | "as"; IDENT "pattern" -> AsIdentOrPattern
+ | "as"; IDENT "strict"; IDENT "pattern" -> AsStrictPattern ] ]
+ ;
END
diff --git a/parsing/pcoq.ml b/parsing/pcoq.ml
index 54e7949ae..ddb26d771 100644
--- a/parsing/pcoq.ml
+++ b/parsing/pcoq.ml
@@ -638,3 +638,15 @@ let () =
Grammar.register0 wit_constr (Constr.constr);
Grammar.register0 wit_red_expr (Vernac_.red_expr);
()
+
+(** Registering extra grammar *)
+
+type any_entry = AnyEntry : 'a Gram.entry -> any_entry
+
+let grammar_names : any_entry list String.Map.t ref = ref String.Map.empty
+
+let register_grammars_by_name name grams =
+ grammar_names := String.Map.add name grams !grammar_names
+
+let find_grammars_by_name name =
+ String.Map.find name !grammar_names
diff --git a/parsing/pcoq.mli b/parsing/pcoq.mli
index 75378d2c6..f36250176 100644
--- a/parsing/pcoq.mli
+++ b/parsing/pcoq.mli
@@ -192,17 +192,17 @@ module Prim :
open Libnames
val preident : string Gram.entry
val ident : Id.t Gram.entry
- val name : Name.t located Gram.entry
- val identref : Id.t located Gram.entry
+ val name : lname Gram.entry
+ val identref : lident Gram.entry
val ident_decl : ident_decl Gram.entry
val pattern_ident : Id.t Gram.entry
- val pattern_identref : Id.t located Gram.entry
+ val pattern_identref : lident Gram.entry
val base_ident : Id.t Gram.entry
val natural : int Gram.entry
val bigint : Constrexpr.raw_natural_number Gram.entry
val integer : int Gram.entry
val string : string Gram.entry
- val lstring : string located Gram.entry
+ val lstring : lstring Gram.entry
val qualid : qualid located Gram.entry
val fullyqualid : Id.t list located Gram.entry
val reference : reference Gram.entry
@@ -210,8 +210,8 @@ module Prim :
val smart_global : reference or_by_notation Gram.entry
val dirpath : DirPath.t Gram.entry
val ne_string : string Gram.entry
- val ne_lstring : string located Gram.entry
- val var : Id.t located Gram.entry
+ val ne_lstring : lstring Gram.entry
+ val var : lident Gram.entry
end
module Constr :
@@ -233,10 +233,10 @@ module Constr :
val binder : local_binder_expr list Gram.entry (* closed_binder or variable *)
val binders : local_binder_expr list Gram.entry (* list of binder *)
val open_binders : local_binder_expr list Gram.entry
- val binders_fixannot : (local_binder_expr list * (Id.t located option * recursion_order_expr)) Gram.entry
- val typeclass_constraint : (Name.t located * bool * constr_expr) Gram.entry
+ val binders_fixannot : (local_binder_expr list * (lident option * recursion_order_expr)) Gram.entry
+ val typeclass_constraint : (lname * bool * constr_expr) Gram.entry
val record_declaration : constr_expr Gram.entry
- val appl_arg : (constr_expr * explicitation located option) Gram.entry
+ val appl_arg : (constr_expr * explicitation CAst.t option) Gram.entry
end
module Module :
@@ -315,3 +315,10 @@ val (!@) : Ploc.t -> Loc.t
type frozen_t
val parser_summary_tag : frozen_t Summary.Dyn.tag
+
+(** Registering grammars by name *)
+
+type any_entry = AnyEntry : 'a Gram.entry -> any_entry
+
+val register_grammars_by_name : string -> any_entry list -> unit
+val find_grammars_by_name : string -> any_entry list
diff --git a/plugins/funind/glob_term_to_relation.ml b/plugins/funind/glob_term_to_relation.ml
index f7639d22d..22881c32c 100644
--- a/plugins/funind/glob_term_to_relation.ml
+++ b/plugins/funind/glob_term_to_relation.ml
@@ -1295,8 +1295,8 @@ let rec rebuild_return_type rt =
CAst.make ?loc @@ Constrexpr.CProdN(n,rebuild_return_type t')
| Constrexpr.CLetIn(na,v,t,t') ->
CAst.make ?loc @@ Constrexpr.CLetIn(na,v,t,rebuild_return_type t')
- | _ -> CAst.make ?loc @@ Constrexpr.CProdN([[Loc.tag Anonymous],
- Constrexpr.Default Decl_kinds.Explicit, rt],
+ | _ -> CAst.make ?loc @@ Constrexpr.CProdN([Constrexpr.CLocalAssum ([CAst.make Anonymous],
+ Constrexpr.Default Decl_kinds.Explicit, rt)],
CAst.make @@ Constrexpr.CSort(GType []))
let do_build_inductive
@@ -1351,12 +1351,12 @@ let do_build_inductive
(fun (n,t,typ) acc ->
match typ with
| Some typ ->
- CAst.make @@ Constrexpr.CLetIn((Loc.tag n),with_full_print (Constrextern.extern_glob_constr Id.Set.empty) t,
+ CAst.make @@ Constrexpr.CLetIn((CAst.make n),with_full_print (Constrextern.extern_glob_constr Id.Set.empty) t,
Some (with_full_print (Constrextern.extern_glob_constr Id.Set.empty) typ),
acc)
| None ->
CAst.make @@ Constrexpr.CProdN
- ([[(Loc.tag n)],Constrexpr_ops.default_binder_kind,with_full_print (Constrextern.extern_glob_constr Id.Set.empty) t],
+ ([Constrexpr.CLocalAssum([CAst.make n],Constrexpr_ops.default_binder_kind,with_full_print (Constrextern.extern_glob_constr Id.Set.empty) t)],
acc
)
)
@@ -1418,12 +1418,12 @@ let do_build_inductive
(fun (n,t,typ) acc ->
match typ with
| Some typ ->
- CAst.make @@ Constrexpr.CLetIn((Loc.tag n),with_full_print (Constrextern.extern_glob_constr Id.Set.empty) t,
+ CAst.make @@ Constrexpr.CLetIn((CAst.make n),with_full_print (Constrextern.extern_glob_constr Id.Set.empty) t,
Some (with_full_print (Constrextern.extern_glob_constr Id.Set.empty) typ),
acc)
| None ->
CAst.make @@ Constrexpr.CProdN
- ([[(Loc.tag n)],Constrexpr_ops.default_binder_kind,with_full_print (Constrextern.extern_glob_constr Id.Set.empty) t],
+ ([Constrexpr.CLocalAssum([CAst.make n],Constrexpr_ops.default_binder_kind,with_full_print (Constrextern.extern_glob_constr Id.Set.empty) t)],
acc
)
)
@@ -1450,18 +1450,18 @@ let do_build_inductive
(fun (n,t,typ) ->
match typ with
| Some typ ->
- Constrexpr.CLocalDef((Loc.tag n), Constrextern.extern_glob_constr Id.Set.empty t,
+ Constrexpr.CLocalDef((CAst.make n), Constrextern.extern_glob_constr Id.Set.empty t,
Some (with_full_print (Constrextern.extern_glob_constr Id.Set.empty) typ))
| None ->
Constrexpr.CLocalAssum
- ([(Loc.tag n)], Constrexpr_ops.default_binder_kind, Constrextern.extern_glob_constr Id.Set.empty t)
+ ([(CAst.make n)], Constrexpr_ops.default_binder_kind, Constrextern.extern_glob_constr Id.Set.empty t)
)
rels_params
in
let ext_rels_constructors =
Array.map (List.map
(fun (id,t) ->
- false,((Loc.tag id),
+ false,((CAst.make id),
with_full_print
(Constrextern.extern_glob_type Id.Set.empty) ((* zeta_normalize *) (alpha_rt rel_params_ids t))
)
@@ -1469,7 +1469,7 @@ let do_build_inductive
(rel_constructors)
in
let rel_ind i ext_rel_constructors =
- (((Loc.tag @@ relnames.(i)), None),
+ (((CAst.make @@ relnames.(i)), None),
rel_params,
Some rel_arities.(i),
ext_rel_constructors),[]
diff --git a/plugins/funind/glob_termops.ml b/plugins/funind/glob_termops.ml
index b4ca1073c..41eb48657 100644
--- a/plugins/funind/glob_termops.ml
+++ b/plugins/funind/glob_termops.ml
@@ -562,7 +562,7 @@ let resolve_and_replace_implicits ?(flags=Pretyping.all_and_fail_flags) ?(expect
(* we first (pseudo) understand [rt] and get back the computed evar_map *)
(* FIXME : JF (30/03/2017) I'm not completely sure to have split understand as needed.
If someone knows how to prevent solved existantial removal in understand, please do not hesitate to change the computation of [ctx] here *)
- let ctx,_ = Pretyping.ise_pretype_gen flags env sigma Glob_ops.empty_lvar expected_type rt in
+ let ctx,_,_ = Pretyping.ise_pretype_gen flags env sigma Glob_ops.empty_lvar expected_type rt in
let ctx, f = Evarutil.nf_evars_and_universes ctx in
(* then we map [rt] to replace the implicit holes by their values *)
diff --git a/plugins/funind/indfun.ml b/plugins/funind/indfun.ml
index 58154d310..e19fc9b62 100644
--- a/plugins/funind/indfun.ml
+++ b/plugins/funind/indfun.ml
@@ -155,7 +155,7 @@ let build_newrecursive
let sigma = Evd.from_env env0 in
let (rec_sign,rec_impls) =
List.fold_left
- (fun (env,impls) (((_,recname),_),bl,arityc,_) ->
+ (fun (env,impls) (({CAst.v=recname},_),bl,arityc,_) ->
let arityc = Constrexpr_ops.mkCProdN bl arityc in
let arity,ctx = Constrintern.interp_type env0 sigma arityc in
let evd = Evd.from_env env0 in
@@ -344,7 +344,7 @@ let generate_principle (evd:Evd.evar_map ref) pconstants on_error
is_general do_built (fix_rec_l:(Vernacexpr.fixpoint_expr * Vernacexpr.decl_notation list) list) recdefs interactive_proof
(continue_proof : int -> Names.Constant.t array -> EConstr.constr array -> int ->
Tacmach.tactic) : unit =
- let names = List.map (function (((_, name),_),_,_,_,_),_ -> name) fix_rec_l in
+ let names = List.map (function (({CAst.v=name},_),_,_,_,_),_ -> name) fix_rec_l in
let fun_bodies = List.map2 prepare_body fix_rec_l recdefs in
let funs_args = List.map fst fun_bodies in
let funs_types = List.map (function ((_,_,_,types,_),_) -> types) fix_rec_l in
@@ -365,7 +365,7 @@ let generate_principle (evd:Evd.evar_map ref) pconstants on_error
f_R_mut)
in
let fname_kn (((fname,_),_,_,_,_),_) =
- let f_ref = Ident fname in
+ let f_ref = Ident CAst.(with_loc_val (fun ?loc n -> (loc,n)) fname) in
locate_with_msg
(pr_reference f_ref++str ": Not an inductive type!")
locate_constant
@@ -404,7 +404,7 @@ let generate_principle (evd:Evd.evar_map ref) pconstants on_error
let register_struct is_rec (fixpoint_exprl:(Vernacexpr.fixpoint_expr * Vernacexpr.decl_notation list) list) =
match fixpoint_exprl with
- | [(((_,fname),pl),_,bl,ret_type,body),_] when not is_rec ->
+ | [(({CAst.v=fname},pl),_,bl,ret_type,body),_] when not is_rec ->
let body = match body with | Some body -> body | None -> user_err ~hdr:"Function" (str "Body of Function must be given") in
ComDefinition.do_definition
~program_mode:false
@@ -413,7 +413,7 @@ let register_struct is_rec (fixpoint_exprl:(Vernacexpr.fixpoint_expr * Vernacexp
bl None body (Some ret_type) (Lemmas.mk_hook (fun _ _ -> ()));
let evd,rev_pconstants =
List.fold_left
- (fun (evd,l) ((((_,fname),_),_,_,_,_),_) ->
+ (fun (evd,l) ((({CAst.v=fname},_),_,_,_,_),_) ->
let evd,c =
Evd.fresh_global
(Global.env ()) evd (Constrintern.locate_reference (Libnames.qualid_of_ident fname)) in
@@ -430,7 +430,7 @@ let register_struct is_rec (fixpoint_exprl:(Vernacexpr.fixpoint_expr * Vernacexp
ComFixpoint.do_fixpoint Global (Flags.is_universe_polymorphism ()) fixpoint_exprl;
let evd,rev_pconstants =
List.fold_left
- (fun (evd,l) ((((_,fname),_),_,_,_,_),_) ->
+ (fun (evd,l) ((({CAst.v=fname},_),_,_,_,_),_) ->
let evd,c =
Evd.fresh_global
(Global.env ()) evd (Constrintern.locate_reference (Libnames.qualid_of_ident fname)) in
@@ -460,7 +460,7 @@ let register_wf ?(is_mes=false) fname rec_impls wf_rel_expr wf_arg using_lemmas
let rec_arg_num =
let names =
List.map
- snd
+ CAst.(with_val (fun x -> x))
(Constrexpr_ops.names_of_local_assums args)
in
match wf_arg with
@@ -476,8 +476,8 @@ let register_wf ?(is_mes=false) fname rec_impls wf_rel_expr wf_arg using_lemmas
(None,(Ident (Loc.tag fname)),None) ,
(List.map
(function
- | _,Anonymous -> assert false
- | _,Name e -> (Constrexpr_ops.mkIdentC e)
+ | {CAst.v=Anonymous} -> assert false
+ | {CAst.v=Name e} -> (Constrexpr_ops.mkIdentC e)
)
(Constrexpr_ops.names_of_local_assums args)
)
@@ -515,7 +515,7 @@ let register_mes fname rec_impls wf_mes_expr wf_rel_expr_opt wf_arg using_lemmas
| None ->
begin
match args with
- | [Constrexpr.CLocalAssum ([(_,Name x)],k,t)] -> t,x
+ | [Constrexpr.CLocalAssum ([{CAst.v=Name x}],k,t)] -> t,x
| _ -> error "Recursive argument must be specified"
end
| Some wf_args ->
@@ -525,7 +525,7 @@ let register_mes fname rec_impls wf_mes_expr wf_rel_expr_opt wf_arg using_lemmas
(function
| Constrexpr.CLocalAssum(l,k,t) ->
List.exists
- (function (_,Name id) -> Id.equal id wf_args | _ -> false)
+ (function {CAst.v=Name id} -> Id.equal id wf_args | _ -> false)
l
| _ -> false
)
@@ -546,7 +546,7 @@ let register_mes fname rec_impls wf_mes_expr wf_rel_expr_opt wf_arg using_lemmas
let fun_from_mes =
let applied_mes =
Constrexpr_ops.mkAppC(wf_mes_expr,[Constrexpr_ops.mkIdentC wf_arg]) in
- Constrexpr_ops.mkLambdaC ([(Loc.tag @@ Name wf_arg)],Constrexpr_ops.default_binder_kind,wf_arg_type,applied_mes)
+ Constrexpr_ops.mkLambdaC ([CAst.make @@ Name wf_arg],Constrexpr_ops.default_binder_kind,wf_arg_type,applied_mes)
in
let wf_rel_from_mes =
Constrexpr_ops.mkAppC(Constrexpr_ops.mkRefC ltof,[wf_arg_type;fun_from_mes])
@@ -557,7 +557,7 @@ let register_mes fname rec_impls wf_mes_expr wf_rel_expr_opt wf_arg using_lemmas
let a = Names.Id.of_string "___a" in
let b = Names.Id.of_string "___b" in
Constrexpr_ops.mkLambdaC(
- [Loc.tag @@ Name a;Loc.tag @@ Name b],
+ [CAst.make @@ Name a; CAst.make @@ Name b],
Constrexpr.Default Explicit,
wf_arg_type,
Constrexpr_ops.mkAppC(wf_rel_expr,
@@ -591,11 +591,11 @@ and rebuild_nal aux bk bl' nal typ =
match nal,typ with
| _,{ CAst.v = CProdN([],typ) } -> rebuild_nal aux bk bl' nal typ
| [], _ -> rebuild_bl aux bl' typ
- | na::nal,{ CAst.v = CProdN((na'::nal',bk',nal't)::rest,typ') } ->
- if Name.equal (snd na) (snd na') || Name.is_anonymous (snd na')
+ | na::nal,{ CAst.v = CProdN(CLocalAssum(na'::nal',bk',nal't)::rest,typ') } ->
+ if Name.equal (na.CAst.v) (na'.CAst.v) || Name.is_anonymous (na'.CAst.v)
then
let assum = CLocalAssum([na],bk,nal't) in
- let new_rest = if nal' = [] then rest else ((nal',bk',nal't)::rest) in
+ let new_rest = if nal' = [] then rest else (CLocalAssum(nal',bk',nal't)::rest) in
rebuild_nal
(assum::aux)
bk
@@ -604,7 +604,7 @@ and rebuild_nal aux bk bl' nal typ =
(CAst.make @@ CProdN(new_rest,typ'))
else
let assum = CLocalAssum([na'],bk,nal't) in
- let new_rest = if nal' = [] then rest else ((nal',bk',nal't)::rest) in
+ let new_rest = if nal' = [] then rest else (CLocalAssum(nal',bk',nal't)::rest) in
rebuild_nal
(assum::aux)
bk
@@ -638,7 +638,7 @@ let do_generate_principle pconstants on_error register_built interactive_proof
let _is_struct =
match fixpoint_exprl with
| [((_,(wf_x,Constrexpr.CWfRec wf_rel),_,_,_),_) as fixpoint_expr] ->
- let (((((_,name),pl),_,args,types,body)),_) as fixpoint_expr =
+ let (((({CAst.v=name},pl),_,args,types,body)),_) as fixpoint_expr =
match recompute_binder_list [fixpoint_expr] with
| [e] -> e
| _ -> assert false
@@ -659,10 +659,10 @@ let do_generate_principle pconstants on_error register_built interactive_proof
true
in
if register_built
- then register_wf name rec_impls wf_rel (map_option snd wf_x) using_lemmas args types body pre_hook;
+ then register_wf name rec_impls wf_rel (map_option (fun x -> x.CAst.v) wf_x) using_lemmas args types body pre_hook;
false
|[((_,(wf_x,Constrexpr.CMeasureRec(wf_mes,wf_rel_opt)),_,_,_),_) as fixpoint_expr] ->
- let (((((_,name),_),_,args,types,body)),_) as fixpoint_expr =
+ let (((({CAst.v=name},_),_,args,types,body)),_) as fixpoint_expr =
match recompute_binder_list [fixpoint_expr] with
| [e] -> e
| _ -> assert false
@@ -683,7 +683,7 @@ let do_generate_principle pconstants on_error register_built interactive_proof
true
in
if register_built
- then register_mes name rec_impls wf_mes wf_rel_opt (map_option snd wf_x) using_lemmas args types body pre_hook;
+ then register_mes name rec_impls wf_mes wf_rel_opt (map_option (fun x -> x.CAst.v) wf_x) using_lemmas args types body pre_hook;
true
| _ ->
List.iter (function ((_na,(_,ord),_args,_body,_type),_not) ->
@@ -696,7 +696,7 @@ let do_generate_principle pconstants on_error register_built interactive_proof
fixpoint_exprl;
let fixpoint_exprl = recompute_binder_list fixpoint_exprl in
let fix_names =
- List.map (function ((((_,name),_),_,_,_,_),_) -> name) fixpoint_exprl
+ List.map (function ((({CAst.v=name},_),_,_,_,_),_) -> name) fixpoint_exprl
in
(* ok all the expressions are structural *)
let recdefs,rec_impls = build_newrecursive fixpoint_exprl in
@@ -731,10 +731,14 @@ let rec add_args id new_args = CAst.map (function
end
| CFix _ | CCoFix _ -> anomaly ~label:"add_args " (Pp.str "todo.")
| CProdN(nal,b1) ->
- CProdN(List.map (fun (nal,k,b2) -> (nal,k,add_args id new_args b2)) nal,
+ CProdN(List.map (function CLocalAssum (nal,k,b2) -> CLocalAssum (nal,k,add_args id new_args b2)
+ | CLocalDef (na,b1,t) -> CLocalDef (na,add_args id new_args b1,Option.map (add_args id new_args) t)
+ | CLocalPattern _ -> user_err (Pp.str "pattern with quote not allowed here.")) nal,
add_args id new_args b1)
| CLambdaN(nal,b1) ->
- CLambdaN(List.map (fun (nal,k,b2) -> (nal,k,add_args id new_args b2)) nal,
+ CLambdaN(List.map (function CLocalAssum (nal,k,b2) -> CLocalAssum (nal,k,add_args id new_args b2)
+ | CLocalDef (na,b1,t) -> CLocalDef (na,add_args id new_args b1,Option.map (add_args id new_args) t)
+ | CLocalPattern _ -> user_err (Pp.str "pattern with quote not allowed here.")) nal,
add_args id new_args b1)
| CLetIn(na,b1,t,b2) ->
CLetIn(na,add_args id new_args b1,Option.map (add_args id new_args) t,add_args id new_args b2)
@@ -753,7 +757,7 @@ let rec add_args id new_args = CAst.map (function
List.map (fun (b,na,b_option) ->
add_args id new_args b,
na, b_option) cel,
- List.map (fun (loc,(cpl,e)) -> Loc.tag ?loc @@ (cpl,add_args id new_args e)) cal
+ List.map CAst.(map (fun (cpl,e) -> (cpl,add_args id new_args e))) cal
)
| CLetTuple(nal,(na,b_option),b1,b2) ->
CLetTuple(nal,(na,Option.map (add_args id new_args) b_option),
@@ -793,7 +797,7 @@ let rec chop_n_arrow n t =
then t (* If we have already removed all the arrows then return the type *)
else (* If not we check the form of [t] *)
match t.CAst.v with
- | Constrexpr.CProdN(nal_ta',t') -> (* If we have a forall, to result are possible :
+ | Constrexpr.CProdN(nal_ta',t') -> (* If we have a forall, two results are possible :
either we need to discard more than the number of arrows contained
in this product declaration then we just recall [chop_n_arrow] on
the remaining number of arrow to chop and [t'] we discard it and
@@ -805,7 +809,7 @@ let rec chop_n_arrow n t =
let new_n =
let rec aux (n:int) = function
[] -> n
- | (nal,k,t'')::nal_ta' ->
+ | CLocalAssum(nal,k,t'')::nal_ta' ->
let nal_l = List.length nal in
if n >= nal_l
then
@@ -813,9 +817,10 @@ let rec chop_n_arrow n t =
else
let new_t' = CAst.make @@
Constrexpr.CProdN(
- ((snd (List.chop n nal)),k,t'')::nal_ta',t')
+ CLocalAssum((snd (List.chop n nal)),k,t'')::nal_ta',t')
in
raise (Stop new_t')
+ | _ -> anomaly (Pp.str "Not enough products.")
in
aux n nal_ta'
in
@@ -828,16 +833,13 @@ let rec chop_n_arrow n t =
let rec get_args b t : Constrexpr.local_binder_expr list *
Constrexpr.constr_expr * Constrexpr.constr_expr =
match b.CAst.v with
- | Constrexpr.CLambdaN ((nal_ta), b') ->
+ | Constrexpr.CLambdaN (CLocalAssum(nal,k,ta) as d::rest, b') ->
begin
- let n =
- (List.fold_left (fun n (nal,_,_) ->
- n+List.length nal) 0 nal_ta )
- in
- let nal_tas,b'',t'' = get_args b' (chop_n_arrow n t) in
- (List.map (fun (nal,k,ta) ->
- (Constrexpr.CLocalAssum (nal,k,ta))) nal_ta)@nal_tas, b'',t''
+ let n = List.length nal in
+ let nal_tas,b'',t'' = get_args (CAst.make ?loc:b.CAst.loc @@ Constrexpr.CLambdaN (rest,b')) (chop_n_arrow n t) in
+ d :: nal_tas, b'',t''
end
+ | Constrexpr.CLambdaN ([], b) -> [],b,t
| _ -> [],b,t
@@ -873,7 +875,7 @@ let make_graph (f_ref:global_reference) =
let l =
List.map
(fun (id,(n,recexp),bl,t,b) ->
- let loc, rec_id = Option.get n in
+ let { CAst.loc; v=rec_id } = Option.get n in
let new_args =
List.flatten
(List.map
@@ -881,7 +883,7 @@ let make_graph (f_ref:global_reference) =
| Constrexpr.CLocalDef (na,_,_)-> []
| Constrexpr.CLocalAssum (nal,_,_) ->
List.map
- (fun (loc,n) -> CAst.make ?loc @@
+ (fun {CAst.loc;v=n} -> CAst.make ?loc @@
CRef(Libnames.Ident(loc, Nameops.Name.get_id n),None))
nal
| Constrexpr.CLocalPattern _ -> assert false
@@ -889,21 +891,21 @@ let make_graph (f_ref:global_reference) =
nal_tas
)
in
- let b' = add_args (snd id) new_args b in
- ((((id,None), ( Some (Loc.tag rec_id),CStructRec),nal_tas@bl,t,Some b'),[]):(Vernacexpr.fixpoint_expr * Vernacexpr.decl_notation list))
+ let b' = add_args id.CAst.v new_args b in
+ ((((id,None), ( Some CAst.(make rec_id),CStructRec),nal_tas@bl,t,Some b'),[]):(Vernacexpr.fixpoint_expr * Vernacexpr.decl_notation list))
)
fixexprl
in
l
| _ ->
let id = Label.to_id (Constant.label c) in
- [(((Loc.tag id),None),(None,Constrexpr.CStructRec),nal_tas,t,Some b),[]]
+ [((CAst.make id,None),(None,Constrexpr.CStructRec),nal_tas,t,Some b),[]]
in
let mp,dp,_ = Constant.repr3 c in
do_generate_principle [c,Univ.Instance.empty] error_error false false expr_list;
(* We register the infos *)
List.iter
- (fun ((((_,id),_),_,_,_,_),_) -> add_Function false (Constant.make3 mp dp (Label.of_id id)))
+ (fun ((({CAst.v=id},_),_,_,_,_),_) -> add_Function false (Constant.make3 mp dp (Label.of_id id)))
expr_list)
let do_generate_principle = do_generate_principle [] warning_error true
diff --git a/plugins/ltac/coretactics.ml4 b/plugins/ltac/coretactics.ml4
index 7d2c4d082..794a28dd4 100644
--- a/plugins/ltac/coretactics.ml4
+++ b/plugins/ltac/coretactics.ml4
@@ -346,7 +346,7 @@ let () = register_list_tactical "solve" Tacticals.New.tclSOLVE
let initial_tacticals () =
let idn n = Id.of_string (Printf.sprintf "_%i" n) in
- let varn n = Reference (ArgVar (None, idn n)) in
+ let varn n = Reference (ArgVar (CAst.make (idn n))) in
let iter (s, t) = Tacenv.register_ltac false false (Id.of_string s) t in
List.iter iter [
"first", TacFun ([Name (idn 0)], TacML (None, (initial_entry "first", [varn 0])));
diff --git a/plugins/ltac/extraargs.ml4 b/plugins/ltac/extraargs.ml4
index 4c6d3c2d3..2eb1ef315 100644
--- a/plugins/ltac/extraargs.ml4
+++ b/plugins/ltac/extraargs.ml4
@@ -81,7 +81,7 @@ let pr_int_list_full _prc _prlc _prt l = pr_int_list l
let pr_occurrences _prc _prlc _prt l =
match l with
| ArgArg x -> pr_int_list x
- | ArgVar (loc, id) -> Id.print id
+ | ArgVar { CAst.loc = loc; v=id } -> Id.print id
let occurrences_of = function
| [] -> NoOccurrences
@@ -102,7 +102,7 @@ let int_list_of_VList v = match Value.to_list v with
let interp_occs ist gl l =
match l with
| ArgArg x -> x
- | ArgVar (_,id as locid) ->
+ | ArgVar ({ CAst.v = id } as locid) ->
(try int_list_of_VList (Id.Map.find id ist.lfun)
with Not_found | CannotCoerceTo _ -> [interp_int ist locid])
let interp_occs ist gl l =
@@ -188,7 +188,7 @@ END
type 'id gen_place= ('id * hyp_location_flag,unit) location
-type loc_place = Id.t Loc.located gen_place
+type loc_place = lident gen_place
type place = Id.t gen_place
let pr_gen_place pr_id = function
@@ -199,7 +199,7 @@ let pr_gen_place pr_id = function
| HypLocation (id,InHypValueOnly) ->
str "in (Value of " ++ pr_id id ++ str ")"
-let pr_loc_place _ _ _ = pr_gen_place (fun (_,id) -> Id.print id)
+let pr_loc_place _ _ _ = pr_gen_place (fun { CAst.v = id } -> Id.print id)
let pr_place _ _ _ = pr_gen_place Id.print
let pr_hloc = pr_loc_place () () ()
@@ -228,11 +228,11 @@ ARGUMENT EXTEND hloc
| [ "in" "|-" "*" ] ->
[ ConclLocation () ]
| [ "in" ident(id) ] ->
- [ HypLocation ((Loc.tag id),InHyp) ]
+ [ HypLocation ((CAst.make id),InHyp) ]
| [ "in" "(" "Type" "of" ident(id) ")" ] ->
- [ HypLocation ((Loc.tag id),InHypTypeOnly) ]
+ [ HypLocation ((CAst.make id),InHypTypeOnly) ]
| [ "in" "(" "Value" "of" ident(id) ")" ] ->
- [ HypLocation ((Loc.tag id),InHypValueOnly) ]
+ [ HypLocation ((CAst.make id),InHypValueOnly) ]
END
diff --git a/plugins/ltac/extraargs.mli b/plugins/ltac/extraargs.mli
index 00668ddc7..000c3d2fb 100644
--- a/plugins/ltac/extraargs.mli
+++ b/plugins/ltac/extraargs.mli
@@ -50,7 +50,7 @@ val lglob : constr_expr Pcoq.Gram.entry
type 'id gen_place= ('id * Locus.hyp_location_flag,unit) location
-type loc_place = Id.t Loc.located gen_place
+type loc_place = lident gen_place
type place = Id.t gen_place
val wit_hloc : (loc_place, loc_place, place) Genarg.genarg_type
@@ -77,6 +77,6 @@ val retroknowledge_field : Retroknowledge.field Pcoq.Gram.entry
val wit_retroknowledge_field : (Retroknowledge.field, unit, unit) Genarg.genarg_type
val wit_in_clause :
- (Id.t Loc.located Locus.clause_expr,
- Id.t Loc.located Locus.clause_expr,
- Id.t Locus.clause_expr) Genarg.genarg_type
+ (lident Locus.clause_expr,
+ lident Locus.clause_expr,
+ Id.t Locus.clause_expr) Genarg.genarg_type
diff --git a/plugins/ltac/extratactics.ml4 b/plugins/ltac/extratactics.ml4
index 286f9d95d..10be8a842 100644
--- a/plugins/ltac/extratactics.ml4
+++ b/plugins/ltac/extratactics.ml4
@@ -71,7 +71,7 @@ END
let induction_arg_of_quantified_hyp = function
| AnonHyp n -> None,ElimOnAnonHyp n
- | NamedHyp id -> None,ElimOnIdent (Loc.tag id)
+ | NamedHyp id -> None,ElimOnIdent (CAst.make id)
(* Versions *_main must come first!! so that "1" is interpreted as a
ElimOnAnonHyp and not as a "constr", and "id" is interpreted as a
diff --git a/plugins/ltac/g_ltac.ml4 b/plugins/ltac/g_ltac.ml4
index 9ef819569..85c9fc5fd 100644
--- a/plugins/ltac/g_ltac.ml4
+++ b/plugins/ltac/g_ltac.ml4
@@ -37,10 +37,10 @@ let genarg_of_uconstr c = in_gen (rawwit Stdarg.wit_uconstr) c
let in_tac tac = in_gen (rawwit Tacarg.wit_ltac) tac
let reference_to_id = function
- | Libnames.Ident (loc, id) -> (loc, id)
+ | Libnames.Ident (loc, id) -> CAst.make ?loc id
| Libnames.Qualid (loc,_) ->
- CErrors.user_err ?loc
- (str "This expression should be a simple identifier.")
+ CErrors.user_err ?loc
+ (str "This expression should be a simple identifier.")
let tactic_mode = Gram.entry_create "vernac:tactic_command"
@@ -196,7 +196,7 @@ GEXTEND Gram
verbose most of the time. *)
fresh_id:
[ [ s = STRING -> ArgArg s (*| id = ident -> ArgVar (!@loc,id)*)
- | qid = qualid -> let (_pth,id) = Libnames.repr_qualid (snd qid) in ArgVar (Loc.tag ~loc:!@loc id) ] ]
+ | qid = qualid -> let (_pth,id) = Libnames.repr_qualid (snd qid) in ArgVar (CAst.make ~loc:!@loc id) ] ]
;
constr_eval:
[ [ IDENT "eval"; rtc = red_expr; "in"; c = Constr.constr ->
@@ -225,12 +225,12 @@ GEXTEND Gram
| l = ident -> Name.Name l ] ]
;
let_clause:
- [ [ (l,id) = identref; ":="; te = tactic_expr ->
- ((l,Name id), arg_of_expr te)
- | na = ["_" -> (Some !@loc,Anonymous)]; ":="; te = tactic_expr ->
+ [ [ idr = identref; ":="; te = tactic_expr ->
+ (CAst.map (fun id -> Name id) idr, arg_of_expr te)
+ | na = ["_" -> CAst.make ~loc:!@loc Anonymous]; ":="; te = tactic_expr ->
(na, arg_of_expr te)
- | (l,id) = identref; args = LIST1 input_fun; ":="; te = tactic_expr ->
- ((l,Name id), arg_of_expr (TacFun(args,te))) ] ]
+ | idr = identref; args = LIST1 input_fun; ":="; te = tactic_expr ->
+ (CAst.map (fun id -> Name id) idr, arg_of_expr (TacFun(args,te))) ] ]
;
match_pattern:
[ [ IDENT "context"; oid = OPT Constr.ident;
@@ -483,7 +483,7 @@ let pr_ltac_ref = Libnames.pr_reference
let pr_tacdef_body tacdef_body =
let id, redef, body =
match tacdef_body with
- | TacticDefinition ((_,id), body) -> Id.print id, false, body
+ | TacticDefinition ({CAst.v=id}, body) -> Id.print id, false, body
| TacticRedefinition (id, body) -> pr_ltac_ref id, true, body
in
let idl, body =
@@ -504,7 +504,7 @@ END
VERNAC COMMAND FUNCTIONAL EXTEND VernacDeclareTacticDefinition
| [ "Ltac" ne_ltac_tacdef_body_list_sep(l, "with") ] => [
VtSideff (List.map (function
- | TacticDefinition ((_,r),_) -> r
+ | TacticDefinition ({CAst.v=r},_) -> r
| TacticRedefinition (Ident (_,r),_) -> r
| TacticRedefinition (Qualid (_,q),_) -> snd(repr_qualid q)) l), VtLater
] -> [ fun ~atts ~st -> let open Vernacinterp in
diff --git a/plugins/ltac/g_tactic.ml4 b/plugins/ltac/g_tactic.ml4
index d792d4ff7..338d61e6f 100644
--- a/plugins/ltac/g_tactic.ml4
+++ b/plugins/ltac/g_tactic.ml4
@@ -115,24 +115,26 @@ let mk_fix_tac (loc,id,bl,ann,ty) =
match bl,ann with
[([_],_,_)], None -> 1
| _, Some x ->
- let ids = List.map snd (List.flatten (List.map pi1 bl)) in
- (try List.index Names.Name.equal (snd x) ids
+ let ids = List.map (fun x -> x.CAst.v) (List.flatten (List.map (fun (nal,_,_) -> nal) bl)) in
+ (try List.index Names.Name.equal x.CAst.v ids
with Not_found -> user_err Pp.(str "No such fix variable."))
| _ -> user_err Pp.(str "Cannot guess decreasing argument of fix.") in
+ let bl = List.map (fun (nal,bk,t) -> CLocalAssum (nal,bk,t)) bl in
(id,n, CAst.make ~loc @@ CProdN(bl,ty))
let mk_cofix_tac (loc,id,bl,ann,ty) =
- let _ = Option.map (fun (aloc,_) ->
- user_err ~loc:aloc
+ let _ = Option.map (fun { CAst.loc = aloc } ->
+ user_err ?loc:aloc
~hdr:"Constr:mk_cofix_tac"
(Pp.str"Annotation forbidden in cofix expression.")) ann in
+ let bl = List.map (fun (nal,bk,t) -> CLocalAssum (nal,bk,t)) bl in
(id,CAst.make ~loc @@ CProdN(bl,ty))
(* Functions overloaded by quotifier *)
let destruction_arg_of_constr (c,lbind as clbind) = match lbind with
| NoBindings ->
begin
- try ElimOnIdent (Constrexpr_ops.constr_loc c,snd(Constrexpr_ops.coerce_to_id c))
+ try ElimOnIdent (CAst.make ?loc:(Constrexpr_ops.constr_loc c) (Constrexpr_ops.coerce_to_id c).CAst.v)
with e when CErrors.noncritical e -> ElimOnConstr clbind
end
| _ -> ElimOnConstr clbind
@@ -150,6 +152,7 @@ let mkTacCase with_evar = function
(* Reinterpret ident as notations for variables in the context *)
(* because we don't know if they are quantified or not *)
| [(clear,ElimOnIdent id),(None,None),None],None ->
+ let id = CAst.(id.loc, id.v) in
TacCase (with_evar,(clear,(CAst.make @@ CRef (Ident id,None),NoBindings)))
| ic ->
if List.exists (function ((_, ElimOnAnonHyp _),_,_) -> true | _ -> false) (fst ic)
@@ -159,15 +162,15 @@ let mkTacCase with_evar = function
let rec mkCLambdaN_simple_loc ?loc bll c =
match bll with
- | ((loc1,_)::_ as idl,bk,t) :: bll ->
- CAst.make ?loc @@ CLambdaN ([idl,bk,t],mkCLambdaN_simple_loc ?loc:(Loc.merge_opt loc1 loc) bll c)
+ | ({CAst.loc = loc1}::_ as idl,bk,t) :: bll ->
+ CAst.make ?loc @@ CLambdaN ([CLocalAssum (idl,bk,t)],mkCLambdaN_simple_loc ?loc:(Loc.merge_opt loc1 loc) bll c)
| ([],_,_) :: bll -> mkCLambdaN_simple_loc ?loc bll c
| [] -> c
let mkCLambdaN_simple bl c = match bl with
| [] -> c
| h :: _ ->
- let loc = Loc.merge_opt (fst (List.hd (pi1 h))) (Constrexpr_ops.constr_loc c) in
+ let loc = Loc.merge_opt (List.hd (pi1 h)).CAst.loc (Constrexpr_ops.constr_loc c) in
mkCLambdaN_simple_loc ?loc bl c
let loc_of_ne_list l = Loc.merge_opt (fst (List.hd l)) (fst (List.last l))
@@ -379,15 +382,20 @@ GEXTEND Gram
;
hypident:
[ [ id = id_or_meta ->
- id,InHyp
+ let id : Misctypes.lident = id in
+ id,InHyp
| "("; IDENT "type"; IDENT "of"; id = id_or_meta; ")" ->
- id,InHypTypeOnly
+ let id : Misctypes.lident = id in
+ id,InHypTypeOnly
| "("; IDENT "value"; IDENT "of"; id = id_or_meta; ")" ->
- id,InHypValueOnly
+ let id : Misctypes.lident = id in
+ id,InHypValueOnly
] ]
;
hypident_occ:
- [ [ (id,l)=hypident; occs=occs -> ((occs,id),l) ] ]
+ [ [ (id,l)=hypident; occs=occs ->
+ let id : Misctypes.lident = id in
+ ((occs,id),l) ] ]
;
in_clause:
[ [ "*"; occs=occs ->
@@ -431,7 +439,8 @@ GEXTEND Gram
| -> true ]]
;
simple_binder:
- [ [ na=name -> ([na],Default Explicit, CAst.make ~loc:!@loc @@ CHole (Some (Evar_kinds.BinderType (snd na)), IntroAnonymous, None))
+ [ [ na=name -> ([na],Default Explicit, CAst.make ~loc:!@loc @@
+ CHole (Some (Evar_kinds.BinderType na.CAst.v), IntroAnonymous, None))
| "("; nal=LIST1 name; ":"; c=lconstr; ")" -> (nal,Default Explicit,c)
] ]
;
@@ -563,28 +572,34 @@ GEXTEND Gram
TacAtom (Loc.tag ~loc:!@loc @@ TacLetTac (true,na,c,p,false,e))
(* Alternative syntax for "pose proof c as id" *)
- | IDENT "assert"; test_lpar_id_coloneq; "("; (loc,id) = identref; ":=";
+ | IDENT "assert"; test_lpar_id_coloneq; "("; lid = identref; ":=";
c = lconstr; ")" ->
- TacAtom (Loc.tag ~loc:!@loc @@ TacAssert (false,true,None,Some (Loc.tag ~loc:!@loc @@ IntroNaming (IntroIdentifier id)),c))
- | IDENT "eassert"; test_lpar_id_coloneq; "("; (loc,id) = identref; ":=";
+ let { CAst.loc = loc; v = id } = lid in
+ TacAtom (Loc.tag ?loc @@ TacAssert (false,true,None,Some (Loc.tag ?loc @@ IntroNaming (IntroIdentifier id)),c))
+ | IDENT "eassert"; test_lpar_id_coloneq; "("; lid = identref; ":=";
c = lconstr; ")" ->
- TacAtom (Loc.tag ~loc:!@loc @@ TacAssert (true,true,None,Some (Loc.tag ~loc:!@loc @@ IntroNaming (IntroIdentifier id)),c))
+ let { CAst.loc = loc; v = id } = lid in
+ TacAtom (Loc.tag ?loc @@ TacAssert (true,true,None,Some (Loc.tag ?loc @@ IntroNaming (IntroIdentifier id)),c))
(* Alternative syntax for "assert c as id by tac" *)
- | IDENT "assert"; test_lpar_id_colon; "("; (loc,id) = identref; ":";
+ | IDENT "assert"; test_lpar_id_colon; "("; lid = identref; ":";
c = lconstr; ")"; tac=by_tactic ->
- TacAtom (Loc.tag ~loc:!@loc @@ TacAssert (false,true,Some tac,Some (Loc.tag ~loc:!@loc @@ IntroNaming (IntroIdentifier id)),c))
- | IDENT "eassert"; test_lpar_id_colon; "("; (loc,id) = identref; ":";
+ let { CAst.loc = loc; v = id } = lid in
+ TacAtom (Loc.tag ?loc @@ TacAssert (false,true,Some tac,Some (Loc.tag ?loc @@ IntroNaming (IntroIdentifier id)),c))
+ | IDENT "eassert"; test_lpar_id_colon; "("; lid = identref; ":";
c = lconstr; ")"; tac=by_tactic ->
- TacAtom (Loc.tag ~loc:!@loc @@ TacAssert (true,true,Some tac,Some (Loc.tag ~loc:!@loc @@ IntroNaming (IntroIdentifier id)),c))
+ let { CAst.loc = loc; v = id } = lid in
+ TacAtom (Loc.tag ?loc @@ TacAssert (true,true,Some tac,Some (Loc.tag ?loc @@ IntroNaming (IntroIdentifier id)),c))
(* Alternative syntax for "enough c as id by tac" *)
- | IDENT "enough"; test_lpar_id_colon; "("; (loc,id) = identref; ":";
+ | IDENT "enough"; test_lpar_id_colon; "("; lid = identref; ":";
c = lconstr; ")"; tac=by_tactic ->
- TacAtom (Loc.tag ~loc:!@loc @@ TacAssert (false,false,Some tac,Some (Loc.tag ~loc:!@loc @@ IntroNaming (IntroIdentifier id)),c))
- | IDENT "eenough"; test_lpar_id_colon; "("; (loc,id) = identref; ":";
+ let { CAst.loc = loc; v = id } = lid in
+ TacAtom (Loc.tag ?loc @@ TacAssert (false,false,Some tac,Some (Loc.tag ?loc @@ IntroNaming (IntroIdentifier id)),c))
+ | IDENT "eenough"; test_lpar_id_colon; "("; lid = identref; ":";
c = lconstr; ")"; tac=by_tactic ->
- TacAtom (Loc.tag ~loc:!@loc @@ TacAssert (true,false,Some tac,Some (Loc.tag ~loc:!@loc @@ IntroNaming (IntroIdentifier id)),c))
+ let { CAst.loc = loc; v = id } = lid in
+ TacAtom (Loc.tag ?loc @@ TacAssert (true,false,Some tac,Some (Loc.tag ?loc @@ IntroNaming (IntroIdentifier id)),c))
| IDENT "assert"; c = constr; ipat = as_ipat; tac = by_tactic ->
TacAtom (Loc.tag ~loc:!@loc @@ TacAssert (false,true,Some tac,ipat,c))
diff --git a/plugins/ltac/pltac.mli b/plugins/ltac/pltac.mli
index 048dcc8e9..ecb0b5796 100644
--- a/plugins/ltac/pltac.mli
+++ b/plugins/ltac/pltac.mli
@@ -9,7 +9,6 @@
(** Ltac parsing entries *)
open Loc
-open Names
open Pcoq
open Libnames
open Constrexpr
@@ -20,7 +19,7 @@ open Misctypes
val open_constr : constr_expr Gram.entry
val constr_with_bindings : constr_expr with_bindings Gram.entry
val bindings : constr_expr bindings Gram.entry
-val hypident : (Id.t located * Locus.hyp_location_flag) Gram.entry
+val hypident : (lident * Locus.hyp_location_flag) Gram.entry
val constr_may_eval : (constr_expr,reference or_by_notation,constr_expr) may_eval Gram.entry
val constr_eval : (constr_expr,reference or_by_notation,constr_expr) may_eval Gram.entry
val uconstr : constr_expr Gram.entry
@@ -29,8 +28,8 @@ val destruction_arg : constr_expr with_bindings destruction_arg Gram.entry
val int_or_var : int or_var Gram.entry
val simple_tactic : raw_tactic_expr Gram.entry
val simple_intropattern : constr_expr intro_pattern_expr located Gram.entry
-val in_clause : Names.Id.t Loc.located Locus.clause_expr Gram.entry
-val clause_dft_concl : Names.Id.t Loc.located Locus.clause_expr Gram.entry
+val in_clause : lident Locus.clause_expr Gram.entry
+val clause_dft_concl : lident Locus.clause_expr Gram.entry
val tactic_arg : raw_tactic_arg Gram.entry
val tactic_expr : raw_tactic_expr Gram.entry
val binder_tactic : raw_tactic_expr Gram.entry
diff --git a/plugins/ltac/pptactic.ml b/plugins/ltac/pptactic.ml
index e5ff47356..3bc9f2aa0 100644
--- a/plugins/ltac/pptactic.ml
+++ b/plugins/ltac/pptactic.ml
@@ -161,7 +161,7 @@ let string_of_genarg_arg (ArgumentType arg) =
(keyword "eval" ++ brk (1,1) ++
pr_red_expr (prc,prlc,pr2,pr3) r ++ spc () ++
keyword "in" ++ spc() ++ prc c)
- | ConstrContext ((_,id),c) ->
+ | ConstrContext ({CAst.v=id},c) ->
hov 0
(keyword "context" ++ spc () ++ pr_id id ++ spc () ++
str "[ " ++ prlc c ++ str " ]")
@@ -353,9 +353,10 @@ let string_of_genarg_arg (ArgumentType arg) =
let rec strip_ty acc n ty =
match ty.CAst.v with
Constrexpr.CProdN(bll,a) ->
- let nb =
- List.fold_left (fun i (nal,_,_) -> i + List.length nal) 0 bll in
- let bll = List.map (fun (x, _, y) -> x, y) bll in
+ let bll = List.map (function
+ | CLocalAssum (nal,_,t) -> nal,t
+ | _ -> user_err Pp.(str "Cannot translate fix tactic: not only products")) bll in
+ let nb = List.fold_left (fun i (nal,t) -> i + List.length nal) 0 bll in
if nb >= n then (List.rev (bll@acc)), a
else strip_ty (bll@acc) (n-nb) a
| _ -> user_err Pp.(str "Cannot translate fix tactic: not enough products") in
@@ -363,7 +364,7 @@ let string_of_genarg_arg (ArgumentType arg) =
let pr_ltac_or_var pr = function
| ArgArg x -> pr x
- | ArgVar (loc,id) -> pr_with_comments ?loc (pr_id id)
+ | ArgVar {CAst.loc;v=id} -> pr_with_comments ?loc (pr_id id)
let pr_ltac_constant kn =
if !Flags.in_debugger then KerName.print kn
@@ -403,7 +404,7 @@ let string_of_genarg_arg (ArgumentType arg) =
let pr_as_name = function
| Anonymous -> mt ()
- | Name id -> spc () ++ keyword "as" ++ spc () ++ pr_lident (Loc.tag id)
+ | Name id -> spc () ++ keyword "as" ++ spc () ++ pr_lident (CAst.make id)
let pr_pose_as_style prc na c =
spc() ++ prc c ++ pr_as_name na
@@ -495,12 +496,12 @@ let string_of_genarg_arg (ArgumentType arg) =
let pr_core_destruction_arg prc prlc = function
| ElimOnConstr c -> pr_with_bindings prc prlc c
- | ElimOnIdent (loc,id) -> pr_with_comments ?loc (pr_id id)
+ | ElimOnIdent {CAst.loc;v=id} -> pr_with_comments ?loc (pr_id id)
| ElimOnAnonHyp n -> int n
let pr_destruction_arg prc prlc (clear_flag,h) =
pr_clear_flag clear_flag (pr_core_destruction_arg prc prlc) h
-
+
let pr_inversion_kind = function
| SimpleInversion -> primitive "simple inversion"
| FullInversion -> primitive "inversion"
@@ -683,7 +684,7 @@ let pr_goal_selector ~toplevel s =
(* match t with
| CHole _ -> spc() ++ prlist_with_sep spc (pr_lname) nal
| _ ->*)
- let s = prlist_with_sep spc pr_lname nal ++ str ":" ++ pr.pr_lconstr t in
+ let s = prlist_with_sep spc Ppconstr.pr_lname nal ++ str ":" ++ pr.pr_lconstr t in
spc() ++ hov 1 (str"(" ++ s ++ str")") in
let pr_fix_tac (id,n,c) =
@@ -691,10 +692,10 @@ let pr_goal_selector ~toplevel s =
(nal,ty)::bll ->
if n <= List.length nal then
match List.chop (n-1) nal with
- _, (_,Name id) :: _ -> id, (nal,ty)::bll
- | bef, (loc,Anonymous) :: aft ->
+ _, {CAst.v=Name id} :: _ -> id, (nal,ty)::bll
+ | bef, {CAst.loc;v=Anonymous} :: aft ->
let id = next_ident_away (Id.of_string"y") avoid in
- id, ((bef@(loc,Name id)::aft, ty)::bll)
+ id, ((bef@(CAst.make ?loc @@ Name id)::aft, ty)::bll)
| _ -> assert false
else
let (id,bll') = set_nth_name avoid (n-List.length nal) bll in
@@ -704,7 +705,7 @@ let pr_goal_selector ~toplevel s =
let names =
List.fold_left
(fun ln (nal,_) -> List.fold_left
- (fun ln na -> match na with (_,Name id) -> Id.Set.add id ln | _ -> ln)
+ (fun ln na -> match na with { CAst.v=Name id } -> Id.Set.add id ln | _ -> ln)
ln nal)
Id.Set.empty bll in
let idarg,bll = set_nth_name names n bll in
@@ -1086,7 +1087,7 @@ let pr_goal_selector ~toplevel s =
if Int.equal n 0 then (List.rev acc, (ty,None)) else
match DAst.get ty with
Glob_term.GProd(na,Explicit,a,b) ->
- strip_ty (([Loc.tag na],(a,None))::acc) (n-1) b
+ strip_ty (([CAst.make na],(a,None))::acc) (n-1) b
| _ -> user_err Pp.(str "Cannot translate fix tactic: not enough products") in
strip_ty [] n ty
@@ -1157,7 +1158,7 @@ let pr_goal_selector ~toplevel s =
if n=0 then (List.rev acc, EConstr.of_constr ty) else
match Constr.kind ty with
| Constr.Prod(na,a,b) ->
- strip_ty (([Loc.tag na],EConstr.of_constr a)::acc) (n-1) b
+ strip_ty (([CAst.make na],EConstr.of_constr a)::acc) (n-1) b
| _ -> user_err Pp.(str "Cannot translate fix tactic: not enough products") in
strip_ty [] n ty
@@ -1317,7 +1318,7 @@ let () =
register_basic_print0 wit_ref
pr_reference (pr_or_var (pr_located pr_global)) pr_global;
register_basic_print0 wit_ident pr_id pr_id pr_id;
- register_basic_print0 wit_var (pr_located pr_id) (pr_located pr_id) pr_id;
+ register_basic_print0 wit_var pr_lident pr_lident pr_id;
register_print0
wit_intro_pattern
(lift (Miscprint.pr_intro_pattern pr_constr_expr))
@@ -1327,7 +1328,7 @@ let () =
wit_clause_dft_concl
(lift (pr_clauses (Some true) pr_lident))
(lift (pr_clauses (Some true) pr_lident))
- (fun c -> Genprint.TopPrinterBasic (fun () -> pr_clauses (Some true) (fun id -> pr_lident (Loc.tag id)) c))
+ (fun c -> Genprint.TopPrinterBasic (fun () -> pr_clauses (Some true) (fun id -> pr_lident (CAst.make id)) c))
;
Genprint.register_print0
wit_constr
diff --git a/plugins/ltac/rewrite.ml b/plugins/ltac/rewrite.ml
index acd7a30c4..e73a18b79 100644
--- a/plugins/ltac/rewrite.ml
+++ b/plugins/ltac/rewrite.ml
@@ -1773,7 +1773,7 @@ let rec strategy_of_ast = function
let mkappc s l = CAst.make @@ CAppExpl ((None,(Libnames.Ident (Loc.tag @@ Id.of_string s)),None),l)
let declare_an_instance n s args =
- (((Loc.tag @@ Name n),None), Explicit,
+ (((CAst.make @@ Name n),None), Explicit,
CAst.make @@ CAppExpl ((None, Qualid (Loc.tag @@ qualid_of_string s),None),
args))
@@ -2006,7 +2006,7 @@ let add_morphism glob binders m s n =
let poly = Flags.is_universe_polymorphism () in
let instance_id = add_suffix n "_Proper" in
let instance =
- (((Loc.tag @@ Name instance_id),None), Explicit,
+ (((CAst.make @@ Name instance_id),None), Explicit,
CAst.make @@ CAppExpl (
(None, Qualid (Loc.tag @@ Libnames.qualid_of_string "Coq.Classes.Morphisms.Proper"),None),
[cHole; s; m]))
diff --git a/plugins/ltac/tacentries.ml b/plugins/ltac/tacentries.ml
index ee84be541..4313456a4 100644
--- a/plugins/ltac/tacentries.ml
+++ b/plugins/ltac/tacentries.ml
@@ -374,7 +374,7 @@ let add_ml_tactic_notation name ~level prods =
in
let ids = List.map_filter get_id prods in
let entry = { mltac_name = name; mltac_index = len - i - 1 } in
- let map id = Reference (Misctypes.ArgVar (Loc.tag id)) in
+ let map id = Reference (Misctypes.ArgVar (CAst.make id)) in
let tac = TacML (Loc.tag (entry, List.map map ids)) in
add_glob_tactic_notation false ~level prods true ids tac
in
@@ -431,11 +431,11 @@ let warn_unusable_identifier =
let register_ltac local tacl =
let map tactic_body =
match tactic_body with
- | Tacexpr.TacticDefinition ((loc,id), body) ->
+ | Tacexpr.TacticDefinition ({CAst.loc;v=id}, body) ->
let kn = Lib.make_kn id in
let id_pp = Id.print id in
let () = if is_defined_tac kn then
- CErrors.user_err ?loc
+ CErrors.user_err ?loc
(str "There is already an Ltac named " ++ id_pp ++ str".")
in
let is_shadowed =
@@ -545,11 +545,10 @@ let print_located_tactic qid =
(** Grammar *)
let () =
- let open Metasyntax in
let entries = [
AnyEntry Pltac.tactic_expr;
AnyEntry Pltac.binder_tactic;
AnyEntry Pltac.simple_tactic;
AnyEntry Pltac.tactic_arg;
] in
- register_grammar "tactic" entries
+ register_grammars_by_name "tactic" entries
diff --git a/plugins/ltac/tacexpr.mli b/plugins/ltac/tacexpr.mli
index ccd555b61..146d8300d 100644
--- a/plugins/ltac/tacexpr.mli
+++ b/plugins/ltac/tacexpr.mli
@@ -41,7 +41,7 @@ type goal_selector = Vernacexpr.goal_selector =
type 'a core_destruction_arg = 'a Misctypes.core_destruction_arg =
| ElimOnConstr of 'a
- | ElimOnIdent of Id.t located
+ | ElimOnIdent of lident
| ElimOnAnonHyp of int
type 'a destruction_arg =
@@ -85,8 +85,8 @@ type 'a match_pattern =
(* Type of hypotheses for a Match Context rule *)
type 'a match_context_hyps =
- | Hyp of Name.t located * 'a match_pattern
- | Def of Name.t located * 'a match_pattern * 'a match_pattern
+ | Hyp of lname * 'a match_pattern
+ | Def of lname * 'a match_pattern * 'a match_pattern
(* Type of a Match rule for Match Context and Match *)
type ('a,'t) match_rule =
@@ -254,7 +254,7 @@ and 'a gen_tactic_expr =
| TacFail of global_flag * int or_var * 'n message_token list
| TacInfo of 'a gen_tactic_expr
| TacLetIn of rec_flag *
- (Name.t located * 'a gen_tactic_arg) list *
+ (lname * 'a gen_tactic_arg) list *
'a gen_tactic_expr
| TacMatch of lazy_flag *
'a gen_tactic_expr *
@@ -300,7 +300,7 @@ type g_trm = glob_constr_and_expr
type g_pat = glob_constr_pattern_and_expr
type g_cst = evaluable_global_reference and_short_name or_var
type g_ref = ltac_constant located or_var
-type g_nam = Id.t located
+type g_nam = lident
type g_dispatch = <
term:g_trm;
@@ -328,7 +328,7 @@ type r_trm = constr_expr
type r_pat = constr_pattern_expr
type r_cst = reference or_by_notation
type r_ref = reference
-type r_nam = Id.t located
+type r_nam = lident
type r_lev = rlevel
type r_dispatch = <
@@ -357,7 +357,7 @@ type t_trm = EConstr.constr
type t_pat = constr_pattern
type t_cst = evaluable_global_reference
type t_ref = ltac_constant located
-type t_nam = Id.t
+type t_nam = Id.t
type t_dispatch = <
term:t_trm;
@@ -391,5 +391,5 @@ type ltac_call_kind =
type ltac_trace = ltac_call_kind Loc.located list
type tacdef_body =
- | TacticDefinition of Id.t Loc.located * raw_tactic_expr (* indicates that user employed ':=' in Ltac body *)
+ | TacticDefinition of lident * raw_tactic_expr (* indicates that user employed ':=' in Ltac body *)
| TacticRedefinition of reference * raw_tactic_expr (* indicates that user employed '::=' in Ltac body *)
diff --git a/plugins/ltac/tacintern.ml b/plugins/ltac/tacintern.ml
index ebffde441..22ec6c5b1 100644
--- a/plugins/ltac/tacintern.ml
+++ b/plugins/ltac/tacintern.ml
@@ -6,12 +6,13 @@
(* * GNU Lesser General Public License Version 2.1 *)
(************************************************************************)
-open Pattern
open Pp
+open CErrors
+open CAst
+open Pattern
open Genredexpr
open Glob_term
open Tacred
-open CErrors
open Util
open Names
open Libnames
@@ -73,11 +74,11 @@ let strict_check = ref false
let adjust_loc loc = if !strict_check then None else loc
(* Globalize a name which must be bound -- actually just check it is bound *)
-let intern_hyp ist (loc,id as locid) =
+let intern_hyp ist ({loc;v=id} as locid) =
if not !strict_check then
locid
else if find_ident id ist then
- Loc.tag id
+ make id
else
Pretype_errors.error_var_not_found ?loc id
@@ -89,7 +90,8 @@ let intern_int_or_var = intern_or_var (fun (n : int) -> n)
let intern_string_or_var = intern_or_var (fun (s : string) -> s)
let intern_global_reference ist = function
- | Ident (loc,id) when find_var id ist -> ArgVar (loc,id)
+ | Ident (loc,id) when find_var id ist ->
+ ArgVar CAst.(make ?loc id)
| r ->
let loc,_ as lqid = qualid_of_reference r in
try ArgArg (loc,locate_global_with_alias lqid)
@@ -99,7 +101,7 @@ let intern_ltac_variable ist = function
| Ident (loc,id) ->
if find_var id ist then
(* A local variable of any type *)
- ArgVar (loc,id)
+ ArgVar CAst.(make ?loc id)
else raise Not_found
| _ ->
raise Not_found
@@ -249,7 +251,7 @@ and intern_or_and_intro_pattern lf ist = function
IntroOrPattern (List.map (List.map (intern_intro_pattern lf ist)) ll)
let intern_or_and_intro_pattern_loc lf ist = function
- | ArgVar (_,id) as x ->
+ | ArgVar {v=id} as x ->
if find_var id ist then x
else user_err Pp.(str "Disjunctive/conjunctive introduction pattern expected.")
| ArgArg (loc,l) -> ArgArg (loc,intern_or_and_intro_pattern lf ist l)
@@ -261,18 +263,18 @@ let intern_intro_pattern_naming_loc lf ist (loc,pat) =
let intern_destruction_arg ist = function
| clear,ElimOnConstr c -> clear,ElimOnConstr (intern_constr_with_bindings ist c)
| clear,ElimOnAnonHyp n as x -> x
- | clear,ElimOnIdent (loc,id) ->
+ | clear,ElimOnIdent {loc;v=id} ->
if !strict_check then
(* If in a defined tactic, no intros-until *)
let c, p = intern_constr ist (CAst.make @@ CRef (Ident (Loc.tag id), None)) in
match DAst.get c with
- | GVar id -> clear,ElimOnIdent (c.CAst.loc,id)
+ | GVar id -> clear,ElimOnIdent CAst.(make ?loc:c.loc id)
| _ -> clear,ElimOnConstr ((c, p), NoBindings)
else
- clear,ElimOnIdent (loc,id)
+ clear,ElimOnIdent CAst.(make ?loc id)
let short_name = function
- | AN (Ident (loc,id)) when not !strict_check -> Some (loc,id)
+ | AN (Ident (loc,id)) when not !strict_check -> Some CAst.(make ?loc id)
| _ -> None
let intern_evaluable_global_reference ist r =
@@ -292,9 +294,9 @@ let intern_evaluable_reference_or_by_notation ist = function
(* Globalize a reduction expression *)
let intern_evaluable ist = function
- | AN (Ident (loc,id)) when find_var id ist -> ArgVar (loc,id)
+ | AN (Ident (loc,id)) when find_var id ist -> ArgVar CAst.(make ?loc id)
| AN (Ident (loc,id)) when not !strict_check && find_hyp id ist ->
- ArgArg (EvalVarRef id, Some (loc,id))
+ ArgArg (EvalVarRef id, Some CAst.(make ?loc id))
| r ->
let e = intern_evaluable_reference_or_by_notation ist r in
let na = short_name r in
@@ -370,7 +372,7 @@ let intern_typed_pattern_or_ref_with_occurrences ist (l,p) =
Inr (bound_names,(c,None),dummy_pat) in
(l, match p with
| Inl r -> interp_ref r
- | Inr { CAst.v = CAppExpl((None,r,None),[]) } ->
+ | Inr { v = CAppExpl((None,r,None),[]) } ->
(* We interpret similarly @ref and ref *)
interp_ref (AN r)
| Inr c ->
@@ -400,8 +402,8 @@ let intern_red_expr ist = function
| Lazy f -> Lazy (intern_flag ist f)
| Pattern l -> Pattern (List.map (intern_constr_with_occurrences ist) l)
| Simpl (f,o) ->
- Simpl (intern_flag ist f,
- Option.map (intern_typed_pattern_or_ref_with_occurrences ist) o)
+ Simpl (intern_flag ist f,
+ Option.map (intern_typed_pattern_or_ref_with_occurrences ist) o)
| CbvVm o -> CbvVm (Option.map (intern_typed_pattern_or_ref_with_occurrences ist) o)
| CbvNative o -> CbvNative (Option.map (intern_typed_pattern_or_ref_with_occurrences ist) o)
| (Red _ | Hnf | ExtraRedExpr _ as r ) -> r
@@ -438,7 +440,7 @@ let intern_pattern ist ?(as_type=false) ltacvars = function
let intern_constr_may_eval ist = function
| ConstrEval (r,c) -> ConstrEval (intern_red_expr ist r,intern_constr ist c)
| ConstrContext (locid,c) ->
- ConstrContext (intern_hyp ist locid,intern_constr ist c)
+ ConstrContext (intern_hyp ist locid,intern_constr ist c)
| ConstrTypeOf c -> ConstrTypeOf (intern_constr ist c)
| ConstrTerm c -> ConstrTerm (intern_constr ist c)
@@ -452,12 +454,12 @@ let opt_cons accu = function
(* Reads the hypotheses of a "match goal" rule *)
let rec intern_match_goal_hyps ist ?(as_type=false) lfun = function
- | (Hyp ((_,na) as locna,mp))::tl ->
+ | (Hyp ({v=na} as locna,mp))::tl ->
let ido, metas1, pat = intern_pattern ist ~as_type:true lfun mp in
let lfun, metas2, hyps = intern_match_goal_hyps ist lfun tl in
let lfun' = name_cons (opt_cons lfun ido) na in
lfun', metas1@metas2, Hyp (locna,pat)::hyps
- | (Def ((_,na) as locna,mv,mp))::tl ->
+ | (Def ({v=na} as locna,mv,mp))::tl ->
let ido, metas1, patv = intern_pattern ist ~as_type:false lfun mv in
let ido', metas2, patt = intern_pattern ist ~as_type:true lfun mp in
let lfun, metas3, hyps = intern_match_goal_hyps ist ~as_type lfun tl in
@@ -467,7 +469,7 @@ let rec intern_match_goal_hyps ist ?(as_type=false) lfun = function
(* Utilities *)
let extract_let_names lrc =
- let fold accu ((loc, name), _) =
+ let fold accu ({loc;v=name}, _) =
Nameops.Name.fold_right (fun id accu ->
if Id.Set.mem id accu then user_err ?loc
~hdr:"glob_tactic" (str "This variable is bound several times.")
@@ -813,7 +815,7 @@ let notation_subst bindings tac =
let fold id c accu =
let loc = Glob_ops.loc_of_glob_constr (fst c) in
let c = ConstrMayEval (ConstrTerm c) in
- ((loc, Name id), c) :: accu
+ (CAst.make ?loc @@ Name id, c) :: accu
in
let bindings = Id.Map.fold fold bindings [] in
(** This is theoretically not correct due to potential variable capture, but
diff --git a/plugins/ltac/tacintern.mli b/plugins/ltac/tacintern.mli
index e3a4d5c79..8021dc715 100644
--- a/plugins/ltac/tacintern.mli
+++ b/plugins/ltac/tacintern.mli
@@ -47,7 +47,7 @@ val intern_constr_with_bindings :
glob_sign -> constr_expr * constr_expr bindings ->
glob_constr_and_expr * glob_constr_and_expr bindings
-val intern_hyp : glob_sign -> Id.t Loc.located -> Id.t Loc.located
+val intern_hyp : glob_sign -> lident -> lident
(** Adds a globalization function for extra generic arguments *)
diff --git a/plugins/ltac/tacinterp.ml b/plugins/ltac/tacinterp.ml
index f2720954d..79b5c1622 100644
--- a/plugins/ltac/tacinterp.ml
+++ b/plugins/ltac/tacinterp.ml
@@ -9,6 +9,7 @@
open Constrintern
open Patternops
open Pp
+open CAst
open Genredexpr
open Glob_term
open Glob_ops
@@ -363,16 +364,16 @@ let error_ltac_variable ?loc id env v s =
strbrk "which cannot be coerced to " ++ str s ++ str".")
(* Raise Not_found if not in interpretation sign *)
-let try_interp_ltac_var coerce ist env (loc,id) =
+let try_interp_ltac_var coerce ist env {loc;v=id} =
let v = Id.Map.find id ist.lfun in
try coerce v with CannotCoerceTo s -> error_ltac_variable ?loc id env v s
let interp_ltac_var coerce ist env locid =
try try_interp_ltac_var coerce ist env locid
- with Not_found -> anomaly (str "Detected '" ++ Id.print (snd locid) ++ str "' as ltac var at interning time.")
+ with Not_found -> anomaly (str "Detected '" ++ Id.print locid.v ++ str "' as ltac var at interning time.")
let interp_ident ist env sigma id =
- try try_interp_ltac_var (coerce_var_to_ident false env sigma) ist (Some (env,sigma)) (Loc.tag id)
+ try try_interp_ltac_var (coerce_var_to_ident false env sigma) ist (Some (env,sigma)) (make id)
with Not_found -> id
(* Interprets an optional identifier, bound or fresh *)
@@ -381,25 +382,25 @@ let interp_name ist env sigma = function
| Name id -> Name (interp_ident ist env sigma id)
let interp_intro_pattern_var loc ist env sigma id =
- try try_interp_ltac_var (coerce_to_intro_pattern env sigma) ist (Some (env,sigma)) (loc,id)
+ try try_interp_ltac_var (coerce_to_intro_pattern env sigma) ist (Some (env,sigma)) (make ?loc id)
with Not_found -> IntroNaming (IntroIdentifier id)
let interp_intro_pattern_naming_var loc ist env sigma id =
- try try_interp_ltac_var (coerce_to_intro_pattern_naming env sigma) ist (Some (env,sigma)) (loc,id)
+ try try_interp_ltac_var (coerce_to_intro_pattern_naming env sigma) ist (Some (env,sigma)) (make ?loc id)
with Not_found -> IntroIdentifier id
-let interp_int ist locid =
+let interp_int ist ({loc;v=id} as locid) =
try try_interp_ltac_var coerce_to_int ist None locid
with Not_found ->
- user_err ?loc:(fst locid) ~hdr:"interp_int"
- (str "Unbound variable " ++ Id.print (snd locid) ++ str".")
+ user_err ?loc ~hdr:"interp_int"
+ (str "Unbound variable " ++ Id.print id ++ str".")
let interp_int_or_var ist = function
| ArgVar locid -> interp_int ist locid
| ArgArg n -> n
let interp_int_or_var_as_list ist = function
- | ArgVar (_,id as locid) ->
+ | ArgVar ({v=id} as locid) ->
(try coerce_to_int_or_var_list (Id.Map.find id ist.lfun)
with Not_found | CannotCoerceTo _ -> [ArgArg (interp_int ist locid)])
| ArgArg n as x -> [x]
@@ -408,7 +409,7 @@ let interp_int_or_var_list ist l =
List.flatten (List.map (interp_int_or_var_as_list ist) l)
(* Interprets a bound variable (especially an existing hypothesis) *)
-let interp_hyp ist env sigma (loc,id as locid) =
+let interp_hyp ist env sigma ({loc;v=id} as locid) =
(* Look first in lfun for a value coercible to a variable *)
try try_interp_ltac_var (coerce_to_hyp env sigma) ist (Some (env,sigma)) locid
with Not_found ->
@@ -416,7 +417,7 @@ let interp_hyp ist env sigma (loc,id as locid) =
if is_variable env id then id
else Loc.raise ?loc (Logic.RefinerError (env, sigma, Logic.NoSuchHyp id))
-let interp_hyp_list_as_list ist env sigma (loc,id as x) =
+let interp_hyp_list_as_list ist env sigma ({loc;v=id} as x) =
try coerce_to_hyp_list env sigma (Id.Map.find id ist.lfun)
with Not_found | CannotCoerceTo _ -> [interp_hyp ist env sigma x]
@@ -425,8 +426,8 @@ let interp_hyp_list ist env sigma l =
let interp_reference ist env sigma = function
| ArgArg (_,r) -> r
- | ArgVar (loc, id) ->
- try try_interp_ltac_var (coerce_to_reference env sigma) ist (Some (env,sigma)) (loc, id)
+ | ArgVar {loc;v=id} ->
+ try try_interp_ltac_var (coerce_to_reference env sigma) ist (Some (env,sigma)) (make ?loc id)
with Not_found ->
try
VarRef (get_id (Environ.lookup_named id env))
@@ -439,7 +440,7 @@ let try_interp_evaluable env (loc, id) =
| _ -> error_not_evaluable (VarRef id)
let interp_evaluable ist env sigma = function
- | ArgArg (r,Some (loc,id)) ->
+ | ArgArg (r,Some {loc;v=id}) ->
(* Maybe [id] has been introduced by Intro-like tactics *)
begin
try try_interp_evaluable env (loc, id)
@@ -449,8 +450,8 @@ let interp_evaluable ist env sigma = function
| _ -> error_global_not_found ?loc (qualid_of_ident id)
end
| ArgArg (r,None) -> r
- | ArgVar (loc, id) ->
- try try_interp_ltac_var (coerce_to_evaluable_ref env sigma) ist (Some (env,sigma)) (loc, id)
+ | ArgVar {loc;v=id} ->
+ try try_interp_ltac_var (coerce_to_evaluable_ref env sigma) ist (Some (env,sigma)) (make ?loc id)
with Not_found ->
try try_interp_evaluable env (loc, id)
with Not_found -> error_global_not_found ?loc (qualid_of_ident id)
@@ -521,9 +522,9 @@ let default_fresh_id = Id.of_string "H"
let interp_fresh_id ist env sigma l =
let extract_ident ist env sigma id =
try try_interp_ltac_var (coerce_to_ident_not_fresh env sigma)
- ist (Some (env,sigma)) (Loc.tag id)
+ ist (Some (env,sigma)) (make id)
with Not_found -> id in
- let ids = List.map_filter (function ArgVar (_, id) -> Some id | _ -> None) l in
+ let ids = List.map_filter (function ArgVar {v=id} -> Some id | _ -> None) l in
let avoid = match TacStore.get ist.extra f_avoid_ids with
| None -> Id.Set.empty
| Some l -> l
@@ -535,7 +536,7 @@ let interp_fresh_id ist env sigma l =
let s =
String.concat "" (List.map (function
| ArgArg s -> s
- | ArgVar (_,id) -> Id.to_string (extract_ident ist env sigma id)) l) in
+ | ArgVar {v=id} -> Id.to_string (extract_ident ist env sigma id)) l) in
let s = if CLexer.is_keyword s then s^"0" else s in
Id.of_string s in
Tactics.fresh_id_in_env avoid id env
@@ -701,7 +702,7 @@ let interp_constr_with_occurrences ist env sigma (occs,c) =
let interp_closed_typed_pattern_with_occurrences ist env sigma (occs, a) =
let p = match a with
- | Inl (ArgVar (loc,id)) ->
+ | Inl (ArgVar {loc;v=id}) ->
(* This is the encoding of an ltac var supposed to be bound
prioritary to an evaluable reference and otherwise to a constr
(it is an encoding to satisfy the "union" type given to Simpl) *)
@@ -710,7 +711,7 @@ let interp_closed_typed_pattern_with_occurrences ist env sigma (occs, a) =
with CannotCoerceTo _ ->
let c = coerce_to_closed_constr env x in
Inr (pattern_of_constr env sigma (EConstr.to_constr sigma c)) in
- (try try_interp_ltac_var coerce_eval_ref_or_constr ist (Some (env,sigma)) (loc,id)
+ (try try_interp_ltac_var coerce_eval_ref_or_constr ist (Some (env,sigma)) (make ?loc id)
with Not_found ->
error_global_not_found ?loc (qualid_of_ident id))
| Inl (ArgArg _ as b) -> Inl (interp_evaluable ist env sigma b)
@@ -756,7 +757,7 @@ let interp_may_eval f ist env sigma = function
let (sigma,c_interp) = f ist env sigma c in
let (redfun, _) = Redexpr.reduction_of_red_expr env redexp in
redfun env sigma c_interp
- | ConstrContext ((loc,s),c) ->
+ | ConstrContext ({loc;v=s},c) ->
(try
let (sigma,ic) = f ist env sigma c in
let ctxt = coerce_to_constr_context (Id.Map.find s ist.lfun) in
@@ -821,7 +822,7 @@ let message_of_value v =
let interp_message_token ist = function
| MsgString s -> Ftactic.return (str s)
| MsgInt n -> Ftactic.return (int n)
- | MsgIdent (loc,id) ->
+ | MsgIdent {loc;v=id} ->
let v = try Some (Id.Map.find id ist.lfun) with Not_found -> None in
match v with
| None -> Ftactic.lift (Tacticals.New.tclZEROMSG (Id.print id ++ str" not found."))
@@ -881,7 +882,7 @@ let interp_intro_pattern_naming_option ist env sigma = function
let interp_or_and_intro_pattern_option ist env sigma = function
| None -> sigma, None
- | Some (ArgVar (loc,id)) ->
+ | Some (ArgVar {loc;v=id}) ->
(match interp_intro_pattern_var loc ist env sigma id with
| IntroAction (IntroOrAndPattern l) -> sigma, Some (loc,l)
| _ ->
@@ -906,14 +907,14 @@ let interp_binding_name ist env sigma = function
(* If a name is bound, it has to be a quantified hypothesis *)
(* user has to use other names for variables if these ones clash with *)
(* a name intented to be used as a (non-variable) identifier *)
- try try_interp_ltac_var (coerce_to_quantified_hypothesis sigma) ist (Some (env,sigma)) (Loc.tag id)
+ try try_interp_ltac_var (coerce_to_quantified_hypothesis sigma) ist (Some (env,sigma)) (make id)
with Not_found -> NamedHyp id
let interp_declared_or_quantified_hypothesis ist env sigma = function
| AnonHyp n -> AnonHyp n
| NamedHyp id ->
try try_interp_ltac_var
- (coerce_to_decl_or_quant_hyp env sigma) ist (Some (env,sigma)) (Loc.tag id)
+ (coerce_to_decl_or_quant_hyp env sigma) ist (Some (env,sigma)) (make id)
with Not_found -> NamedHyp id
let interp_binding ist env sigma (loc,(b,c)) =
@@ -924,7 +925,7 @@ let interp_bindings ist env sigma = function
| NoBindings ->
sigma, NoBindings
| ImplicitBindings l ->
- let sigma, l = interp_open_constr_list ist env sigma l in
+ let sigma, l = interp_open_constr_list ist env sigma l in
sigma, ImplicitBindings l
| ExplicitBindings l ->
let sigma, l = List.fold_left_map (interp_binding ist env) sigma l in
@@ -959,14 +960,14 @@ let interp_destruction_arg ist gl arg =
interp_open_constr_with_bindings ist env sigma c
end
| keep,ElimOnAnonHyp n as x -> x
- | keep,ElimOnIdent (loc,id) ->
+ | keep,ElimOnIdent {loc;v=id} ->
let error () = user_err ?loc
(strbrk "Cannot coerce " ++ Id.print id ++
strbrk " neither to a quantified hypothesis nor to a term.")
in
let try_cast_id id' =
if Tactics.is_quantified_hypothesis id' gl
- then keep,ElimOnIdent (loc,id')
+ then keep,ElimOnIdent CAst.(make ?loc id')
else
(keep, ElimOnConstr begin fun env sigma ->
try (sigma, (constr_of_id env id', NoBindings))
@@ -994,7 +995,7 @@ let interp_destruction_arg ist gl arg =
with Not_found ->
(* We were in non strict (interactive) mode *)
if Tactics.is_quantified_hypothesis id gl then
- keep,ElimOnIdent (loc,id)
+ keep,ElimOnIdent CAst.(make ?loc id)
else
let c = (DAst.make ?loc @@ GVar id,Some (CAst.make @@ CRef (Ident (loc,id),None))) in
let f env sigma =
@@ -1043,11 +1044,11 @@ let cons_and_check_name id l =
else id::l
let rec read_match_goal_hyps lfun ist env sigma lidh = function
- | (Hyp ((loc,na) as locna,mp))::tl ->
+ | (Hyp ({loc;v=na} as locna,mp))::tl ->
let lidh' = Name.fold_right cons_and_check_name na lidh in
Hyp (locna,read_pattern lfun ist env sigma mp)::
(read_match_goal_hyps lfun ist env sigma lidh' tl)
- | (Def ((loc,na) as locna,mv,mp))::tl ->
+ | (Def ({loc;v=na} as locna,mv,mp))::tl ->
let lidh' = Name.fold_right cons_and_check_name na lidh in
Def (locna,read_pattern lfun ist env sigma mv, read_pattern lfun ist env sigma mp)::
(read_match_goal_hyps lfun ist env sigma lidh' tl)
@@ -1112,7 +1113,7 @@ let rec val_interp ist ?(appl=UnnamedAppl) (tac:glob_tactic_expr) : Val.t Ftacti
in
Tactic_debug.debug_prompt lev tac eval
| _ -> value_interp ist >>= fun v -> return (name_vfun appl v)
-
+
and eval_tactic ist tac : unit Proofview.tactic = match tac with
| TacAtom (loc,t) ->
@@ -1248,7 +1249,7 @@ and force_vrec ist v : Val.t Ftactic.t =
and interp_ltac_reference ?loc' mustbetac ist r : Val.t Ftactic.t =
match r with
- | ArgVar (loc,id) ->
+ | ArgVar {loc;v=id} ->
let v =
try Id.Map.find id ist.lfun
with Not_found -> in_gen (topwit wit_var) id
@@ -1416,7 +1417,7 @@ and tactic_of_value ist vle =
and interp_letrec ist llc u =
Proofview.tclUNIT () >>= fun () -> (* delay for the effects of [lref], just in case. *)
let lref = ref ist.lfun in
- let fold accu ((_, na), b) =
+ let fold accu ({v=na}, b) =
let v = of_tacvalue (VRec (lref, TacArg (Loc.tag b))) in
Name.fold_right (fun id -> Id.Map.add id v) na accu
in
@@ -1431,7 +1432,7 @@ and interp_letin ist llc u =
| [] ->
let ist = { ist with lfun } in
val_interp ist u
- | ((_, na), body) :: defs ->
+ | ({v=na}, body) :: defs ->
Ftactic.bind (interp_tacarg ist body) (fun v ->
fold (Name.fold_right (fun id -> Id.Map.add id v) na lfun) defs)
in
diff --git a/plugins/ltac/tacinterp.mli b/plugins/ltac/tacinterp.mli
index 5f2723a1e..2d448e832 100644
--- a/plugins/ltac/tacinterp.mli
+++ b/plugins/ltac/tacinterp.mli
@@ -75,7 +75,7 @@ val interp_redexp : Environ.env -> Evd.evar_map -> raw_red_expr -> Evd.evar_map
(** Interprets tactic expressions *)
val interp_hyp : interp_sign -> Environ.env -> Evd.evar_map ->
- Id.t Loc.located -> Id.t
+ lident -> Id.t
val interp_glob_closure : interp_sign -> Environ.env -> Evd.evar_map ->
?kind:Pretyping.typing_constraint -> ?pattern_mode:bool -> glob_constr_and_expr ->
@@ -125,9 +125,9 @@ val hide_interp : bool -> raw_tactic_expr -> unit Proofview.tactic option -> uni
(** Internals that can be useful for syntax extensions. *)
val interp_ltac_var : (value -> 'a) -> interp_sign ->
- (Environ.env * Evd.evar_map) option -> Id.t Loc.located -> 'a
+ (Environ.env * Evd.evar_map) option -> lident -> 'a
-val interp_int : interp_sign -> Id.t Loc.located -> int
+val interp_int : interp_sign -> lident -> int
val interp_int_or_var : interp_sign -> int or_var -> int
diff --git a/plugins/ltac/tactic_debug.mli b/plugins/ltac/tactic_debug.mli
index 2475e41f9..dce6f5558 100644
--- a/plugins/ltac/tactic_debug.mli
+++ b/plugins/ltac/tactic_debug.mli
@@ -74,7 +74,7 @@ val db_logic_failure : debug_info -> exn -> unit Proofview.NonLogical.t
(** Prints a logic failure message for a rule *)
val db_breakpoint : debug_info ->
- Id.t Loc.located message_token list -> unit Proofview.NonLogical.t
+ Misctypes.lident message_token list -> unit Proofview.NonLogical.t
val extract_ltac_trace :
?loc:Loc.t -> Tacexpr.ltac_trace -> Pp.t option Loc.located
diff --git a/plugins/ltac/tactic_matching.ml b/plugins/ltac/tactic_matching.ml
index e87951dd7..6bf9215e0 100644
--- a/plugins/ltac/tactic_matching.ml
+++ b/plugins/ltac/tactic_matching.ml
@@ -306,9 +306,9 @@ module PatternMatching (E:StaticEnvironment) = struct
[pat] is [Hyp _] or [Def _]. *)
let hyp_match pat hyps =
match pat with
- | Hyp ((_,hypname),typepat) ->
+ | Hyp ({CAst.v=hypname},typepat) ->
hyp_match_type hypname typepat hyps
- | Def ((_,hypname),bodypat,typepat) ->
+ | Def ({CAst.v=hypname},bodypat,typepat) ->
hyp_match_body_and_type hypname bodypat typepat hyps
(** [hyp_pattern_list_match pats hyps lhs], matches the list of
diff --git a/plugins/ltac/tauto.ml b/plugins/ltac/tauto.ml
index 01d3f79c7..5ce30c3d7 100644
--- a/plugins/ltac/tauto.ml
+++ b/plugins/ltac/tauto.ml
@@ -255,10 +255,10 @@ let tauto_power_flags = {
}
let with_flags flags _ ist =
- let f = (Loc.tag @@ Id.of_string "f") in
- let x = (Loc.tag @@ Id.of_string "x") in
+ let f = CAst.make @@ Id.of_string "f" in
+ let x = CAst.make @@ Id.of_string "x" in
let arg = Val.Dyn (tag_tauto_flags, flags) in
- let ist = { ist with lfun = Id.Map.add (snd x) arg ist.lfun } in
+ let ist = { ist with lfun = Id.Map.add x.CAst.v arg ist.lfun } in
eval_tactic_ist ist (TacArg (Loc.tag @@ TacCall (Loc.tag (ArgVar f, [Reference (ArgVar x)]))))
let register_tauto_tactic tac name0 args =
diff --git a/plugins/omega/PreOmega.v b/plugins/omega/PreOmega.v
index 8da45e0ad..93103e026 100644
--- a/plugins/omega/PreOmega.v
+++ b/plugins/omega/PreOmega.v
@@ -26,7 +26,7 @@ Local Open Scope Z_scope.
- on Z: Z.min, Z.max, Z.abs, Z.sgn are translated in term of <= < =
- on nat: + * - S O pred min max Pos.to_nat N.to_nat Z.abs_nat
- on positive: Zneg Zpos xI xO xH + * - Pos.succ Pos.pred Pos.min Pos.max Pos.of_succ_nat
- - on N: N0 Npos + * - N.succ N.min N.max N.of_nat Z.abs_N
+ - on N: N0 Npos + * - N.pred N.succ N.min N.max N.of_nat Z.abs_N
*)
@@ -391,6 +391,10 @@ Ltac zify_N_op :=
| H : context [ Z.of_N (N.sub ?a ?b) ] |- _ => rewrite (N2Z.inj_sub_max a b) in H
| |- context [ Z.of_N (N.sub ?a ?b) ] => rewrite (N2Z.inj_sub_max a b)
+ (* pred -> minus ... -1 -> Z.max (Z.sub ... -1) 0 *)
+ | H : context [ Z.of_N (N.pred ?a) ] |- _ => rewrite (N.pred_sub a) in H
+ | |- context [ Z.of_N (N.pred ?a) ] => rewrite (N.pred_sub a)
+
(* N.succ -> Z.succ *)
| H : context [ Z.of_N (N.succ ?a) ] |- _ => rewrite (N2Z.inj_succ a) in H
| |- context [ Z.of_N (N.succ ?a) ] => rewrite (N2Z.inj_succ a)
diff --git a/plugins/quote/g_quote.ml4 b/plugins/quote/g_quote.ml4
index 40897d62f..55dc7f580 100644
--- a/plugins/quote/g_quote.ml4
+++ b/plugins/quote/g_quote.ml4
@@ -22,7 +22,7 @@ let x = Id.of_string "x"
let make_cont (k : Val.t) (c : EConstr.t) =
let c = Tacinterp.Value.of_constr c in
- let tac = TacCall (Loc.tag (ArgVar (Loc.tag cont), [Reference (ArgVar (Loc.tag x))])) in
+ let tac = TacCall (Loc.tag (ArgVar CAst.(make cont), [Reference (ArgVar CAst.(make x))])) in
let ist = { lfun = Id.Map.add cont k (Id.Map.singleton x c); extra = TacStore.empty; } in
Tacinterp.eval_tactic_ist ist (TacArg (Loc.tag tac))
diff --git a/plugins/setoid_ring/newring.ml b/plugins/setoid_ring/newring.ml
index e3e749b75..125afb1a0 100644
--- a/plugins/setoid_ring/newring.ml
+++ b/plugins/setoid_ring/newring.ml
@@ -166,12 +166,12 @@ let ltac_call tac (args:glob_tactic_arg list) =
(* Calling a locally bound tactic *)
let ltac_lcall tac args =
- TacArg(Loc.tag @@ TacCall (Loc.tag (ArgVar(Loc.tag @@ Id.of_string tac),args)))
+ TacArg(Loc.tag @@ TacCall (Loc.tag (ArgVar CAst.(make @@ Id.of_string tac),args)))
let ltac_apply (f : Value.t) (args: Tacinterp.Value.t list) =
let fold arg (i, vars, lfun) =
let id = Id.of_string ("x" ^ string_of_int i) in
- let x = Reference (ArgVar (Loc.tag id)) in
+ let x = Reference (ArgVar CAst.(make id)) in
(succ i, x :: vars, Id.Map.add id arg lfun)
in
let (_, args, lfun) = List.fold_right fold args (0, [], Id.Map.empty) in
@@ -206,7 +206,7 @@ let get_res =
let exec_tactic env evd n f args =
let fold arg (i, vars, lfun) =
let id = Id.of_string ("x" ^ string_of_int i) in
- let x = Reference (ArgVar (Loc.tag id)) in
+ let x = Reference (ArgVar CAst.(make id)) in
(succ i, x :: vars, Id.Map.add id (Value.of_constr arg) lfun)
in
let (_, args, lfun) = List.fold_right fold args (0, [], Id.Map.empty) in
diff --git a/plugins/ssr/ssrcommon.ml b/plugins/ssr/ssrcommon.ml
index 9822da1c7..4ae746288 100644
--- a/plugins/ssr/ssrcommon.ml
+++ b/plugins/ssr/ssrcommon.ml
@@ -268,7 +268,7 @@ let interp_wit wit ist gl x =
sigma, Tacinterp.Value.cast (topwit wit) arg
let interp_hyp ist gl (SsrHyp (loc, id)) =
- let s, id' = interp_wit wit_var ist gl (loc, id) in
+ let s, id' = interp_wit wit_var ist gl CAst.(make ?loc id) in
if not_section_id id' then s, SsrHyp (loc, id') else
hyp_err ?loc "Can't clear section hypothesis " id'
@@ -835,9 +835,9 @@ let rec mkCHoles ?loc n =
if n <= 0 then [] else (CAst.make ?loc @@ CHole (None, IntroAnonymous, None)) :: mkCHoles ?loc (n - 1)
let mkCHole loc = CAst.make ?loc @@ CHole (None, IntroAnonymous, None)
let mkCLambda ?loc name ty t = CAst.make ?loc @@
- CLambdaN ([[loc, name], Default Explicit, ty], t)
+ CLambdaN ([CLocalAssum([CAst.make ?loc name], Default Explicit, ty)], t)
let mkCArrow ?loc ty t = CAst.make ?loc @@
- CProdN ([[Loc.tag Anonymous], Default Explicit, ty], t)
+ CProdN ([CLocalAssum([CAst.make Anonymous], Default Explicit, ty)], t)
let mkCCast ?loc t ty = CAst.make ?loc @@ CCast (t, CastConv ty)
let rec isCHoles = function { CAst.v = CHole _ } :: cl -> isCHoles cl | cl -> cl = []
@@ -855,7 +855,7 @@ let pf_interp_ty ?(resolve_typeclasses=false) ist gl ty =
| _, (_, Some ty) ->
let rec force_type ty = CAst.(map (function
| CProdN (abs, t) ->
- n_binders := !n_binders + List.length (List.flatten (List.map pi1 abs));
+ n_binders := !n_binders + List.length (List.flatten (List.map (function CLocalAssum (nal,_,_) -> nal | CLocalDef (na,_,_) -> [na] | CLocalPattern _ -> (* We count a 'pat for 1; TO BE CHECKED *) [CAst.make Name.Anonymous]) abs));
CProdN (abs, force_type t)
| CLetIn (n, v, oty, t) -> incr n_binders; CLetIn (n, v, oty, force_type t)
| _ -> (mkCCast ty (mkCType None)).v)) ty in
diff --git a/plugins/ssr/ssrparser.ml4 b/plugins/ssr/ssrparser.ml4
index 46403aef3..0d8044f19 100644
--- a/plugins/ssr/ssrparser.ml4
+++ b/plugins/ssr/ssrparser.ml4
@@ -130,7 +130,7 @@ let pr_ssrhyp _ _ _ = pr_hyp
let wit_ssrhyprep = add_genarg "ssrhyprep" pr_hyp
let intern_hyp ist (SsrHyp (loc, id) as hyp) =
- let _ = Tacintern.intern_genarg ist (in_gen (rawwit wit_var) (loc, id)) in
+ let _ = Tacintern.intern_genarg ist (in_gen (rawwit wit_var) CAst.(make ?loc id)) in
if not_section_id id then hyp else
hyp_err ?loc "Can't clear section hypothesis " id
@@ -316,7 +316,7 @@ END
let pr_index = function
- | Misctypes.ArgVar (_, id) -> pr_id id
+ | Misctypes.ArgVar {CAst.v=id} -> pr_id id
| Misctypes.ArgArg n when n > 0 -> int n
| _ -> mt ()
let pr_ssrindex _ _ _ = pr_index
@@ -330,13 +330,13 @@ let mk_index ?loc = function
| iv -> iv
let interp_index ist gl idx =
- Tacmach.project gl,
+ Tacmach.project gl,
match idx with
| Misctypes.ArgArg _ -> idx
- | Misctypes.ArgVar (loc, id) ->
+ | Misctypes.ArgVar id ->
let i =
try
- let v = Id.Map.find id ist.Tacinterp.lfun in
+ let v = Id.Map.find id.CAst.v ist.Tacinterp.lfun in
begin match Tacinterp.Value.to_int v with
| Some i -> i
| None ->
@@ -350,8 +350,8 @@ let interp_index ist gl idx =
end
| None -> raise Not_found
end end
- with _ -> CErrors.user_err ?loc (str"Index not a number") in
- Misctypes.ArgArg (check_index ?loc i)
+ with _ -> CErrors.user_err ?loc:id.CAst.loc (str"Index not a number") in
+ Misctypes.ArgArg (check_index ?loc:id.CAst.loc i)
open Pltac
@@ -1014,22 +1014,22 @@ let rec mkBstruct i = function
| [] -> []
let rec format_local_binders h0 bl0 = match h0, bl0 with
- | BFvar :: h, CLocalAssum ([_, x], _, _) :: bl ->
+ | BFvar :: h, CLocalAssum ([{CAst.v=x}], _, _) :: bl ->
Bvar x :: format_local_binders h bl
| BFdecl _ :: h, CLocalAssum (lxs, _, t) :: bl ->
- Bdecl (List.map snd lxs, t) :: format_local_binders h bl
- | BFdef :: h, CLocalDef ((_, x), v, oty) :: bl ->
+ Bdecl (List.map (fun x -> x.CAst.v) lxs, t) :: format_local_binders h bl
+ | BFdef :: h, CLocalDef ({CAst.v=x}, v, oty) :: bl ->
Bdef (x, oty, v) :: format_local_binders h bl
| _ -> []
let rec format_constr_expr h0 c0 = let open CAst in match h0, c0 with
- | BFvar :: h, { v = CLambdaN ([[_, x], _, _], c) } ->
+ | BFvar :: h, { v = CLambdaN ([CLocalAssum([{CAst.v=x}], _, _)], c) } ->
let bs, c' = format_constr_expr h c in
Bvar x :: bs, c'
- | BFdecl _:: h, { v = CLambdaN ([lxs, _, t], c) } ->
+ | BFdecl _:: h, { v = CLambdaN ([CLocalAssum(lxs, _, t)], c) } ->
let bs, c' = format_constr_expr h c in
- Bdecl (List.map snd lxs, t) :: bs, c'
- | BFdef :: h, { v = CLetIn((_, x), v, oty, c) } ->
+ Bdecl (List.map (fun x -> x.CAst.v) lxs, t) :: bs, c'
+ | BFdef :: h, { v = CLetIn({CAst.v=x}, v, oty, c) } ->
let bs, c' = format_constr_expr h c in
Bdef (x, oty, v) :: bs, c'
| [BFcast], { v = CCast (c, CastConv t) } ->
@@ -1037,7 +1037,7 @@ let rec format_constr_expr h0 c0 = let open CAst in match h0, c0 with
| BFrec (has_str, has_cast) :: h,
{ v = CFix ( _, [_, (Some locn, CStructRec), bl, t, c]) } ->
let bs = format_local_binders h bl in
- let bstr = if has_str then [Bstruct (Name (snd locn))] else [] in
+ let bstr = if has_str then [Bstruct (Name locn.CAst.v)] else [] in
bs @ bstr @ (if has_cast then [Bcast t] else []), c
| BFrec (_, has_cast) :: h, { v = CCoFix ( _, [_, bl, t, c]) } ->
format_local_binders h bl @ (if has_cast then [Bcast t] else []), c
@@ -1156,29 +1156,29 @@ ARGUMENT EXTEND ssrbvar TYPED AS constr PRINTED BY pr_ssrbvar
END
let bvar_lname = let open CAst in function
- | { v = CRef (Ident (loc, id), _) } -> Loc.tag ?loc @@ Name id
- | { loc = loc } -> Loc.tag ?loc Anonymous
+ | { v = CRef (Ident (loc, id), _) } -> CAst.make ?loc @@ Name id
+ | { loc = loc } -> CAst.make ?loc Anonymous
let pr_ssrbinder prc _ _ (_, c) = prc c
ARGUMENT EXTEND ssrbinder TYPED AS ssrfwdfmt * constr PRINTED BY pr_ssrbinder
| [ ssrbvar(bv) ] ->
- [ let xloc, _ as x = bvar_lname bv in
+ [ let { CAst.loc=xloc } as x = bvar_lname bv in
(FwdPose, [BFvar]),
- CAst.make ~loc @@ CLambdaN ([[x],Default Explicit,mkCHole xloc],mkCHole (Some loc)) ]
+ CAst.make ~loc @@ CLambdaN ([CLocalAssum([x],Default Explicit,mkCHole xloc)],mkCHole (Some loc)) ]
| [ "(" ssrbvar(bv) ")" ] ->
- [ let xloc, _ as x = bvar_lname bv in
+ [ let { CAst.loc=xloc } as x = bvar_lname bv in
(FwdPose, [BFvar]),
- CAst.make ~loc @@ CLambdaN ([[x],Default Explicit,mkCHole xloc],mkCHole (Some loc)) ]
+ CAst.make ~loc @@ CLambdaN ([CLocalAssum([x],Default Explicit,mkCHole xloc)],mkCHole (Some loc)) ]
| [ "(" ssrbvar(bv) ":" lconstr(t) ")" ] ->
[ let x = bvar_lname bv in
(FwdPose, [BFdecl 1]),
- CAst.make ~loc @@ CLambdaN ([[x], Default Explicit, t], mkCHole (Some loc)) ]
+ CAst.make ~loc @@ CLambdaN ([CLocalAssum([x], Default Explicit, t)], mkCHole (Some loc)) ]
| [ "(" ssrbvar(bv) ne_ssrbvar_list(bvs) ":" lconstr(t) ")" ] ->
[ let xs = List.map bvar_lname (bv :: bvs) in
let n = List.length xs in
(FwdPose, [BFdecl n]),
- CAst.make ~loc @@ CLambdaN ([xs, Default Explicit, t], mkCHole (Some loc)) ]
+ CAst.make ~loc @@ CLambdaN ([CLocalAssum (xs, Default Explicit, t)], mkCHole (Some loc)) ]
| [ "(" ssrbvar(id) ":" lconstr(t) ":=" lconstr(v) ")" ] ->
[ (FwdPose,[BFdef]), CAst.make ~loc @@ CLetIn (bvar_lname id, v, Some t, mkCHole (Some loc)) ]
| [ "(" ssrbvar(id) ":=" lconstr(v) ")" ] ->
@@ -1191,7 +1191,7 @@ GEXTEND Gram
[ ["of" | "&"]; c = operconstr LEVEL "99" ->
let loc = !@loc in
(FwdPose, [BFvar]),
- CAst.make ~loc @@ CLambdaN ([[Loc.tag ~loc Anonymous],Default Explicit,c],mkCHole (Some loc)) ]
+ CAst.make ~loc @@ CLambdaN ([CLocalAssum ([CAst.make ~loc Anonymous],Default Explicit,c)],mkCHole (Some loc)) ]
];
END
@@ -1217,7 +1217,7 @@ let push_binders c2 bs =
| ct -> loop false ct bs
let rec fix_binders = let open CAst in function
- | (_, { v = CLambdaN ([xs, _, t], _) } ) :: bs ->
+ | (_, { v = CLambdaN ([CLocalAssum(xs, _, t)], _) } ) :: bs ->
CLocalAssum (xs, Default Explicit, t) :: fix_binders bs
| (_, { v = CLetIn (x, v, oty, _) } ) :: bs ->
CLocalDef (x, v, oty) :: fix_binders bs
@@ -1250,13 +1250,13 @@ END
let pr_ssrfixfwd _ _ _ (id, fwd) = str " fix " ++ pr_id id ++ pr_fwd fwd
let bvar_locid = function
- | { CAst.v = CRef (Ident (loc, id), _) } -> loc, id
+ | { CAst.v = CRef (Ident (loc, id), _) } -> CAst.make ?loc id
| _ -> CErrors.user_err (Pp.str "Missing identifier after \"(co)fix\"")
ARGUMENT EXTEND ssrfixfwd TYPED AS ident * ssrfwd PRINTED BY pr_ssrfixfwd
| [ "fix" ssrbvar(bv) ssrbinder_list(bs) ssrstruct(sid) ssrfwd(fwd) ] ->
- [ let (_, id) as lid = bvar_locid bv in
+ [ let { CAst.v=id } as lid = bvar_locid bv in
let (fk, h), (ck, (rc, oc)) = fwd in
let c = Option.get oc in
let has_cast, t', c' = match format_constr_expr h c with
@@ -1265,8 +1265,10 @@ ARGUMENT EXTEND ssrfixfwd TYPED AS ident * ssrfwd PRINTED BY pr_ssrfixfwd
let lb = fix_binders bs in
let has_struct, i =
let rec loop = function
- (l', Name id') :: _ when Option.equal Id.equal sid (Some id') -> true, (l', id')
- | [l', Name id'] when sid = None -> false, (l', id')
+ | {CAst.loc=l'; v=Name id'} :: _ when Option.equal Id.equal sid (Some id') ->
+ true, CAst.make ?loc:l' id'
+ | [{CAst.loc=l';v=Name id'}] when sid = None ->
+ false, CAst.make ?loc:l' id'
| _ :: bn -> loop bn
| [] -> CErrors.user_err (Pp.str "Bad structural argument") in
loop (names_of_local_assums lb) in
@@ -1282,7 +1284,7 @@ let pr_ssrcofixfwd _ _ _ (id, fwd) = str " cofix " ++ pr_id id ++ pr_fwd fwd
ARGUMENT EXTEND ssrcofixfwd TYPED AS ssrfixfwd PRINTED BY pr_ssrcofixfwd
| [ "cofix" ssrbvar(bv) ssrbinder_list(bs) ssrfwd(fwd) ] ->
- [ let _, id as lid = bvar_locid bv in
+ [ let { CAst.v=id } as lid = bvar_locid bv in
let (fk, h), (ck, (rc, oc)) = fwd in
let c = Option.get oc in
let has_cast, t', c' = match format_constr_expr h c with
@@ -1323,18 +1325,18 @@ END
let intro_id_to_binder = List.map (function
| IPatId id ->
- let xloc, _ as x = bvar_lname (mkCVar id) in
+ let { CAst.loc=xloc } as x = bvar_lname (mkCVar id) in
(FwdPose, [BFvar]),
- CAst.make @@ CLambdaN ([[x], Default Explicit, mkCHole xloc],
+ CAst.make @@ CLambdaN ([CLocalAssum([x], Default Explicit, mkCHole xloc)],
mkCHole None)
| _ -> anomaly "non-id accepted as binder")
let binder_to_intro_id = CAst.(List.map (function
- | (FwdPose, [BFvar]), { v = CLambdaN ([ids,_,_],_) }
- | (FwdPose, [BFdecl _]), { v = CLambdaN ([ids,_,_],_) } ->
- List.map (function (_, Name id) -> IPatId id | _ -> IPatAnon One) ids
- | (FwdPose, [BFdef]), { v = CLetIn ((_,Name id),_,_,_) } -> [IPatId id]
- | (FwdPose, [BFdef]), { v = CLetIn ((_,Anonymous),_,_,_) } -> [IPatAnon One]
+ | (FwdPose, [BFvar]), { v = CLambdaN ([CLocalAssum(ids,_,_)],_) }
+ | (FwdPose, [BFdecl _]), { v = CLambdaN ([CLocalAssum(ids,_,_)],_) } ->
+ List.map (function {v=Name id} -> IPatId id | _ -> IPatAnon One) ids
+ | (FwdPose, [BFdef]), { v = CLetIn ({v=Name id},_,_,_) } -> [IPatId id]
+ | (FwdPose, [BFdef]), { v = CLetIn ({v=Anonymous},_,_,_) } -> [IPatAnon One]
| _ -> anomaly "ssrbinder is not a binder"))
let pr_ssrhavefwdwbinders _ _ prt (tr,((hpats, (fwd, hint)))) =
@@ -1405,7 +1407,7 @@ let ssrorelse = Gram.entry_create "ssrorelse"
GEXTEND Gram
GLOBAL: ssrorelse ssrseqarg;
ssrseqidx: [
- [ test_ssrseqvar; id = Prim.ident -> ArgVar (Loc.tag ~loc:!@loc id)
+ [ test_ssrseqvar; id = Prim.ident -> ArgVar (CAst.make ~loc:!@loc id)
| n = Prim.natural -> ArgArg (check_index ~loc:!@loc n)
] ];
ssrswap: [[ IDENT "first" -> !@loc, true | IDENT "last" -> !@loc, false ]];
diff --git a/plugins/ssr/ssrvernac.ml4 b/plugins/ssr/ssrvernac.ml4
index d74ad06b3..8e6e0347f 100644
--- a/plugins/ssr/ssrvernac.ml4
+++ b/plugins/ssr/ssrvernac.ml4
@@ -74,14 +74,14 @@ let frozen_lexer = CLexer.get_keyword_state () ;;
let no_ct = None, None and no_rt = None in
let aliasvar = function
- | [[{ CAst.v = CPatAlias (_, id); loc }]] -> Some (loc,Name id)
+ | [[{ CAst.v = CPatAlias (_, na); loc }]] -> Some na
| _ -> None in
let mk_cnotype mp = aliasvar mp, None in
let mk_ctype mp t = aliasvar mp, Some t in
let mk_rtype t = Some t in
-let mk_dthen ?loc (mp, ct, rt) c = (Loc.tag ?loc (mp, c)), ct, rt in
+let mk_dthen ?loc (mp, ct, rt) c = (CAst.make ?loc (mp, c)), ct, rt in
let mk_let ?loc rt ct mp c1 =
- CAst.make ?loc @@ CCases (LetPatternStyle, rt, ct, [Loc.tag ?loc (mp, c1)]) in
+ CAst.make ?loc @@ CCases (LetPatternStyle, rt, ct, [CAst.make ?loc (mp, c1)]) in
let mk_pat c (na, t) = (c, na, t) in
GEXTEND Gram
GLOBAL: binder_constr;
@@ -94,14 +94,16 @@ GEXTEND Gram
] ];
ssr_dthen: [[ dp = ssr_dpat; "then"; c = lconstr -> mk_dthen ~loc:!@loc dp c ]];
ssr_elsepat: [[ "else" -> [[CAst.make ~loc:!@loc @@ CPatAtom None]] ]];
- ssr_else: [[ mp = ssr_elsepat; c = lconstr -> Loc.tag ~loc:!@loc (mp, c) ]];
+ ssr_else: [[ mp = ssr_elsepat; c = lconstr -> CAst.make ~loc:!@loc (mp, c) ]];
binder_constr: [
[ "if"; c = operconstr LEVEL "200"; "is"; db1 = ssr_dthen; b2 = ssr_else ->
let b1, ct, rt = db1 in CAst.make ~loc:!@loc @@ CCases (MatchStyle, rt, [mk_pat c ct], [b1; b2])
| "if"; c = operconstr LEVEL "200";"isn't";db1 = ssr_dthen; b2 = ssr_else ->
let b1, ct, rt = db1 in
- let b1, b2 =
- let (l1, (p1, r1)), (l2, (p2, r2)) = b1, b2 in (l1, (p1, r2)), (l2, (p2, r1)) in
+ let b1, b2 = let open CAst in
+ let {loc=l1; v=(p1, r1)}, {loc=l2; v=(p2, r2)} = b1, b2 in
+ (make ?loc:l1 (p1, r2), make ?loc:l2 (p2, r1))
+ in
CAst.make ~loc:!@loc @@ CCases (MatchStyle, rt, [mk_pat c ct], [b1; b2])
| "let"; ":"; mp = ssr_mpat; ":="; c = lconstr; "in"; c1 = lconstr ->
mk_let ~loc:!@loc no_rt [mk_pat c no_ct] mp c1
@@ -118,7 +120,7 @@ GEXTEND Gram
GLOBAL: closed_binder;
closed_binder: [
[ ["of" | "&"]; c = operconstr LEVEL "99" ->
- [CLocalAssum ([Loc.tag ~loc:!@loc Anonymous], Default Explicit, c)]
+ [CLocalAssum ([CAst.make ~loc:!@loc Anonymous], Default Explicit, c)]
] ];
END
(* }}} *)
@@ -298,7 +300,7 @@ let interp_search_notation ?loc tag okey =
let rec sub () = function
| NVar x when List.mem_assoc x nvars -> DAst.make ?loc @@ GPatVar (FirstOrderPatVar x)
| c ->
- glob_constr_of_notation_constr_with_binders ?loc (fun _ x -> (), x) sub () c in
+ glob_constr_of_notation_constr_with_binders ?loc (fun _ x -> (), None, x) sub () c in
let _, npat = Patternops.pattern_of_glob_constr (sub () body) in
Search.GlobSearchSubPattern npat
@@ -553,7 +555,7 @@ GEXTEND Gram
let s = coerce_reference_to_id qid in
Vernacexpr.VernacDefinition
((Decl_kinds.NoDischarge,Decl_kinds.CanonicalStructure),
- ((Loc.tag (Name s)),None), d)
+ ((CAst.make (Name s)),None), d)
]];
END
@@ -584,10 +586,10 @@ END
GEXTEND Gram
GLOBAL: hloc;
hloc: [
- [ "in"; "("; "Type"; "of"; id = ident; ")" ->
- Tacexpr.HypLocation ((Loc.tag id), Locus.InHypTypeOnly)
- | "in"; "("; IDENT "Value"; "of"; id = ident; ")" ->
- Tacexpr.HypLocation ((Loc.tag id), Locus.InHypValueOnly)
+ [ "in"; "("; "Type"; "of"; id = ident; ")" ->
+ Tacexpr.HypLocation (CAst.make id, Locus.InHypTypeOnly)
+ | "in"; "("; IDENT "Value"; "of"; id = ident; ")" ->
+ Tacexpr.HypLocation (CAst.make id, Locus.InHypValueOnly)
] ];
END
diff --git a/plugins/ssrmatching/ssrmatching.ml4 b/plugins/ssrmatching/ssrmatching.ml4
index 7d0584a00..73e212365 100644
--- a/plugins/ssrmatching/ssrmatching.ml4
+++ b/plugins/ssrmatching/ssrmatching.ml4
@@ -137,9 +137,9 @@ let destGLambda c = match DAst.get c with GLambda (Name id, _, _, c) -> (id, c)
let isGHole c = match DAst.get c with GHole _ -> true | _ -> false
let mkCHole ~loc = CAst.make ?loc @@ CHole (None, IntroAnonymous, None)
let mkCLambda ?loc name ty t = CAst.make ?loc @@
- CLambdaN ([[Loc.tag ?loc name], Default Explicit, ty], t)
+ CLambdaN ([CLocalAssum([CAst.make ?loc name], Default Explicit, ty)], t)
let mkCLetIn ?loc name bo t = CAst.make ?loc @@
- CLetIn ((Loc.tag ?loc name), bo, None, t)
+ CLetIn ((CAst.make ?loc name), bo, None, t)
let mkCCast ?loc t ty = CAst.make ?loc @@ CCast (t, dC ty)
(** Constructors for rawconstr *)
let mkRHole = DAst.make @@ GHole (InternalHole, IntroAnonymous, None)
@@ -916,7 +916,7 @@ let glob_cpattern gs p =
| k, (v, Some t) as orig ->
if k = 'x' then glob_ssrterm gs ('(', (v, Some t)) else
match t.CAst.v with
- | CNotation("( _ in _ )", ([t1; t2], [], [])) ->
+ | CNotation("( _ in _ )", ([t1; t2], [], [], [])) ->
(try match glob t1, glob t2 with
| (r1, None), (r2, None) -> encode k "In" [r1;r2]
| (r1, Some _), (r2, Some _) when isCVar t1 ->
@@ -924,11 +924,11 @@ let glob_cpattern gs p =
| (r1, Some _), (r2, Some _) -> encode k "In" [r1; r2]
| _ -> CErrors.anomaly (str"where are we?.")
with _ when isCVar t1 -> encode k "In" [bind_in t1 t2])
- | CNotation("( _ in _ in _ )", ([t1; t2; t3], [], [])) ->
+ | CNotation("( _ in _ in _ )", ([t1; t2; t3], [], [], [])) ->
check_var t2; encode k "In" [fst (glob t1); bind_in t2 t3]
- | CNotation("( _ as _ )", ([t1; t2], [], [])) ->
+ | CNotation("( _ as _ )", ([t1; t2], [], [], [])) ->
encode k "As" [fst (glob t1); fst (glob t2)]
- | CNotation("( _ as _ in _ )", ([t1; t2; t3], [], [])) ->
+ | CNotation("( _ as _ in _ )", ([t1; t2; t3], [], [], [])) ->
check_var t2; encode k "As" [fst (glob t1); bind_in t2 t3]
| _ -> glob_ssrterm gs orig
;;
diff --git a/pretyping/cases.ml b/pretyping/cases.ml
index 311c1c09e..a0434f927 100644
--- a/pretyping/cases.ml
+++ b/pretyping/cases.ml
@@ -450,11 +450,6 @@ let current_pattern eqn =
| pat::_ -> pat
| [] -> anomaly (Pp.str "Empty list of patterns.")
-let alias_of_pat = DAst.with_val (function
- | PatVar name -> name
- | PatCstr(_,_,name) -> name
- )
-
let remove_current_pattern eqn =
match eqn.patterns with
| pat::pats ->
diff --git a/pretyping/glob_ops.ml b/pretyping/glob_ops.ml
index a21137a05..25817478e 100644
--- a/pretyping/glob_ops.ml
+++ b/pretyping/glob_ops.ml
@@ -19,6 +19,16 @@ open Ltac_pretype
let cases_pattern_loc c = c.CAst.loc
+let alias_of_pat pat = DAst.with_val (function
+ | PatVar name -> name
+ | PatCstr(_,_,name) -> name
+ ) pat
+
+let set_pat_alias id = DAst.map (function
+ | PatVar Anonymous -> PatVar (Name id)
+ | PatCstr (cstr,patl,Anonymous) -> PatCstr (cstr,patl,Name id)
+ | pat -> assert false)
+
let cases_predicate_names tml =
List.flatten (List.map (function
| (tm,(na,None)) -> [na]
@@ -452,6 +462,10 @@ let rec rename_glob_vars l c = force @@ DAst.map_with_loc (fun ?loc -> function
(**********************************************************************)
(* Conversion from glob_constr to cases pattern, if possible *)
+let is_gvar id c = match DAst.get c with
+| GVar id' -> Id.equal id id'
+| _ -> false
+
let rec cases_pattern_of_glob_constr na = DAst.map (function
| GVar id ->
begin match na with
@@ -468,6 +482,9 @@ let rec cases_pattern_of_glob_constr na = DAst.map (function
PatCstr (cstr,List.map (cases_pattern_of_glob_constr Anonymous) l,na)
| _ -> raise Not_found
end
+ | GLetIn (Name id as na',b,None,e) when is_gvar id e && na = Anonymous ->
+ (* A canonical encoding of aliases *)
+ DAst.get (cases_pattern_of_glob_constr na' b)
| _ -> raise Not_found
)
@@ -503,23 +520,34 @@ let add_patterns_for_params_remove_local_defs (ind,j) l =
drop_local_defs typi l in
Util.List.addn nparams (DAst.make @@ PatVar Anonymous) l
+let add_alias ?loc na c =
+ match na with
+ | Anonymous -> c
+ | Name id -> GLetIn (na,DAst.make ?loc c,None,DAst.make ?loc (GVar id))
+
(* Turn a closed cases pattern into a glob_constr *)
-let rec glob_constr_of_closed_cases_pattern_aux x = DAst.map_with_loc (fun ?loc -> function
- | PatCstr (cstr,[],Anonymous) -> GRef (ConstructRef cstr,None)
- | PatCstr (cstr,l,Anonymous) ->
+let rec glob_constr_of_cases_pattern_aux isclosed x = DAst.map_with_loc (fun ?loc -> function
+ | PatCstr (cstr,[],na) -> add_alias ?loc na (GRef (ConstructRef cstr,None))
+ | PatCstr (cstr,l,na) ->
let ref = DAst.make ?loc @@ GRef (ConstructRef cstr,None) in
let l = add_patterns_for_params_remove_local_defs cstr l in
- GApp (ref, List.map glob_constr_of_closed_cases_pattern_aux l)
+ add_alias ?loc na (GApp (ref, List.map (glob_constr_of_cases_pattern_aux isclosed) l))
+ | PatVar (Name id) when not isclosed ->
+ GVar id
+ | PatVar Anonymous when not isclosed ->
+ GHole (Evar_kinds.QuestionMark (Define false,Anonymous),Misctypes.IntroAnonymous,None)
| _ -> raise Not_found
) x
let glob_constr_of_closed_cases_pattern p = match DAst.get p with
| PatCstr (cstr,l,na) ->
let loc = p.CAst.loc in
- na,glob_constr_of_closed_cases_pattern_aux (DAst.make ?loc @@ PatCstr (cstr,l,Anonymous))
+ na,glob_constr_of_cases_pattern_aux true (DAst.make ?loc @@ PatCstr (cstr,l,Anonymous))
| _ ->
raise Not_found
+let glob_constr_of_cases_pattern p = glob_constr_of_cases_pattern_aux false p
+
(**********************************************************************)
(* Interpreting ltac variables *)
diff --git a/pretyping/glob_ops.mli b/pretyping/glob_ops.mli
index 9dd7068cb..0d9fb1f45 100644
--- a/pretyping/glob_ops.mli
+++ b/pretyping/glob_ops.mli
@@ -13,6 +13,10 @@ open Glob_term
val cases_pattern_eq : 'a cases_pattern_g -> 'a cases_pattern_g -> bool
+val alias_of_pat : 'a cases_pattern_g -> Name.t
+
+val set_pat_alias : Id.t -> 'a cases_pattern_g -> 'a cases_pattern_g
+
val cast_type_eq : ('a -> 'a -> bool) ->
'a Misctypes.cast_type -> 'a Misctypes.cast_type -> bool
@@ -78,10 +82,14 @@ val map_pattern : (glob_constr -> glob_constr) ->
Take the current alias as parameter,
@raise Not_found if translation is impossible *)
-val cases_pattern_of_glob_constr : Name.t -> glob_constr -> cases_pattern
+val cases_pattern_of_glob_constr : Name.t -> 'a glob_constr_g -> 'a cases_pattern_g
val glob_constr_of_closed_cases_pattern : 'a cases_pattern_g -> Name.t * 'a glob_constr_g
+(** A canonical encoding of cases pattern into constr such that
+ composed with [cases_pattern_of_glob_constr Anonymous] gives identity *)
+val glob_constr_of_cases_pattern : 'a cases_pattern_g -> 'a glob_constr_g
+
val add_patterns_for_params_remove_local_defs : constructor -> 'a cases_pattern_g list -> 'a cases_pattern_g list
val ltac_interp_name : Ltac_pretype.ltac_var_map -> Name.t -> Name.t
diff --git a/pretyping/pretyping.ml b/pretyping/pretyping.ml
index 8809558ff..6700748eb 100644
--- a/pretyping/pretyping.ml
+++ b/pretyping/pretyping.ml
@@ -378,10 +378,10 @@ let check_evars_are_solved env current_sigma init_sigma =
let frozen = frozen_and_pending_holes (init_sigma, current_sigma) in
check_evars_are_solved env current_sigma frozen
-let process_inference_flags flags env initial_sigma (sigma,c) =
+let process_inference_flags flags env initial_sigma (sigma,c,cty) =
let sigma = solve_remaining_evars flags env sigma initial_sigma in
let c = if flags.expand_evars then nf_evar sigma c else c in
- sigma,c
+ sigma,c,cty
let adjust_evar_source evdref na c =
match na, kind !evdref c with
@@ -1173,15 +1173,18 @@ let ise_pretype_gen flags env sigma lvar kind c =
let env = make_env env sigma in
let evdref = ref sigma in
let k0 = Context.Rel.length (rel_context env) in
- let c' = match kind with
+ let c', c'_ty = match kind with
| WithoutTypeConstraint ->
- (pretype k0 flags.use_typeclasses empty_tycon env evdref lvar c).uj_val
+ let j = pretype k0 flags.use_typeclasses empty_tycon env evdref lvar c in
+ j.uj_val, j.uj_type
| OfType exptyp ->
- (pretype k0 flags.use_typeclasses (mk_tycon exptyp) env evdref lvar c).uj_val
+ let j = pretype k0 flags.use_typeclasses (mk_tycon exptyp) env evdref lvar c in
+ j.uj_val, j.uj_type
| IsType ->
- (pretype_type k0 flags.use_typeclasses empty_valcon env evdref lvar c).utj_val
+ let tj = pretype_type k0 flags.use_typeclasses empty_valcon env evdref lvar c in
+ tj.utj_val, mkSort tj.utj_type
in
- process_inference_flags flags env.ExtraEnv.env sigma (!evdref,c')
+ process_inference_flags flags env.ExtraEnv.env sigma (!evdref,c',c'_ty)
let default_inference_flags fail = {
use_typeclasses = true;
@@ -1201,7 +1204,7 @@ let all_and_fail_flags = default_inference_flags true
let all_no_fail_flags = default_inference_flags false
let ise_pretype_gen_ctx flags env sigma lvar kind c =
- let evd, c = ise_pretype_gen flags env sigma lvar kind c in
+ let evd, c, _ = ise_pretype_gen flags env sigma lvar kind c in
let evd, f = Evarutil.nf_evars_and_universes evd in
f (EConstr.Unsafe.to_constr c), Evd.evar_universe_context evd
@@ -1213,12 +1216,15 @@ let understand
env sigma c =
ise_pretype_gen_ctx flags env sigma empty_lvar expected_type c
-let understand_tcc ?(flags=all_no_fail_flags) env sigma ?(expected_type=WithoutTypeConstraint) c =
- let (sigma, c) = ise_pretype_gen flags env sigma empty_lvar expected_type c in
- (sigma, c)
+let understand_tcc_ty ?(flags=all_no_fail_flags) env sigma ?(expected_type=WithoutTypeConstraint) c =
+ ise_pretype_gen flags env sigma empty_lvar expected_type c
+
+let understand_tcc ?flags env sigma ?expected_type c =
+ let sigma, c, _ = understand_tcc_ty ?flags env sigma ?expected_type c in
+ sigma, c
let understand_ltac flags env sigma lvar kind c =
- let (sigma, c) = ise_pretype_gen flags env sigma lvar kind c in
+ let (sigma, c, _) = ise_pretype_gen flags env sigma lvar kind c in
(sigma, c)
let pretype k0 resolve_tc typcon env evdref lvar t =
diff --git a/pretyping/pretyping.mli b/pretyping/pretyping.mli
index fe10be9e7..864768fe5 100644
--- a/pretyping/pretyping.mli
+++ b/pretyping/pretyping.mli
@@ -58,6 +58,11 @@ val all_and_fail_flags : inference_flags
val understand_tcc : ?flags:inference_flags -> env -> evar_map ->
?expected_type:typing_constraint -> glob_constr -> evar_map * constr
+(** As [understand_tcc] but also returns the type of the elaborated term.
+ The [expand_evars] flag is not applied to the type (only to the term). *)
+val understand_tcc_ty : ?flags:inference_flags -> env -> evar_map ->
+ ?expected_type:typing_constraint -> glob_constr -> evar_map * constr * types
+
(** More general entry point with evars from ltac *)
(** Generic call to the interpreter from glob_constr to constr
@@ -116,7 +121,7 @@ val pretype_type :
val ise_pretype_gen :
inference_flags -> env -> evar_map ->
- ltac_var_map -> typing_constraint -> glob_constr -> evar_map * constr
+ ltac_var_map -> typing_constraint -> glob_constr -> evar_map * constr * types
(**/**)
diff --git a/pretyping/univdecls.ml b/pretyping/univdecls.ml
index 3cf32d7ff..89f1185a9 100644
--- a/pretyping/univdecls.ml
+++ b/pretyping/univdecls.ml
@@ -6,12 +6,11 @@
(* * GNU Lesser General Public License Version 2.1 *)
(************************************************************************)
-open Names
open CErrors
(** Local universes and constraints declarations *)
type universe_decl =
- (Id.t Loc.located list, Univ.Constraint.t) Misctypes.gen_universe_decl
+ (Misctypes.lident list, Univ.Constraint.t) Misctypes.gen_universe_decl
let default_univ_decl =
let open Misctypes in
@@ -34,9 +33,9 @@ let interp_univ_constraints env evd cstrs =
in
List.fold_left interp (evd,Univ.Constraint.empty) cstrs
-let interp_univ_decl env decl =
+let interp_univ_decl env decl =
let open Misctypes in
- let pl = decl.univdecl_instance in
+ let pl : lident list = decl.univdecl_instance in
let evd = Evd.from_ctx (Evd.make_evar_universe_context env (Some pl)) in
let evd, cstrs = interp_univ_constraints env evd decl.univdecl_constraints in
let decl = { univdecl_instance = pl;
diff --git a/pretyping/univdecls.mli b/pretyping/univdecls.mli
index 0c3b749cb..706d3a157 100644
--- a/pretyping/univdecls.mli
+++ b/pretyping/univdecls.mli
@@ -8,7 +8,7 @@
(** Local universe and constraint declarations. *)
type universe_decl =
- (Names.Id.t Loc.located list, Univ.Constraint.t) Misctypes.gen_universe_decl
+ (Misctypes.lident list, Univ.Constraint.t) Misctypes.gen_universe_decl
val default_univ_decl : universe_decl
diff --git a/printing/ppconstr.ml b/printing/ppconstr.ml
index 1146b42a0..3c7095505 100644
--- a/printing/ppconstr.ml
+++ b/printing/ppconstr.ml
@@ -10,6 +10,7 @@
open CErrors
open Util
open Pp
+open CAst
open Names
open Nameops
open Libnames
@@ -86,8 +87,8 @@ let tag_var = tag Tag.variable
open Notation
- let print_hunks n pr pr_binders (terms, termlists, binders) unps =
- let env = ref terms and envlist = ref termlists and bll = ref binders in
+ let print_hunks n pr pr_patt pr_binders (terms, termlists, binders, binderlists) unps =
+ let env = ref terms and envlist = ref termlists and bl = ref binders and bll = ref binderlists in
let pop r = let a = List.hd !r in r := List.tl !r; a in
let return unp pp1 pp2 = (tag_unparsing unp pp1) ++ pp2 in
(* Warning:
@@ -102,6 +103,11 @@ let tag_var = tag Tag.variable
let pp2 = aux l in
let pp1 = pr (n, prec) c in
return unp pp1 pp2
+ | UnpBinderMetaVar (_, prec) as unp :: l ->
+ let c = pop bl in
+ let pp2 = aux l in
+ let pp1 = pr_patt (n, prec) c in
+ return unp pp1 pp2
| UnpListMetaVar (_, prec, sl) as unp :: l ->
let cl = pop envlist in
let pp1 = prlist_with_sep (fun () -> aux sl) (pr (n,prec)) cl in
@@ -127,9 +133,9 @@ let tag_var = tag Tag.variable
in
aux unps
- let pr_notation pr pr_binders s env =
+ let pr_notation pr pr_patt pr_binders s env =
let unpl, level = find_notation_printing_rule s in
- print_hunks level pr pr_binders env unpl, level
+ print_hunks level pr pr_patt pr_binders env unpl, level
let pr_delimiters key strm =
strm ++ str ("%"^key)
@@ -146,7 +152,7 @@ let tag_var = tag Tag.variable
if !Flags.beautify && not (Int.equal n 0) then comment (CLexer.extract_comments n)
else mt()
- let pr_with_comments ?loc pp = pr_located (fun x -> x) (Loc.tag ?loc pp)
+ let pr_with_comments ?loc pp = pr_located (fun x -> x) (loc, pp)
let pr_sep_com sep f c = pr_with_comments ?loc:(constr_loc c) (sep() ++ f c)
@@ -215,28 +221,28 @@ let tag_var = tag Tag.variable
let pr_expl_args pr (a,expl) =
match expl with
| None -> pr (lapp,L) a
- | Some (_,ExplByPos (n,_id)) ->
+ | Some {v=ExplByPos (n,_id)} ->
anomaly (Pp.str "Explicitation by position not implemented.")
- | Some (_,ExplByName id) ->
+ | Some {v=ExplByName id} ->
str "(" ++ pr_id id ++ str ":=" ++ pr ltop a ++ str ")"
let pr_opt_type_spc pr = function
| { CAst.v = CHole (_,Misctypes.IntroAnonymous,_) } -> mt ()
| t -> str " :" ++ pr_sep_com (fun()->brk(1,2)) (pr ltop) t
- let pr_lident (loc,id) =
+ let pr_lident {loc; v=id} =
match loc with
| None -> pr_id id
| Some loc -> let (b,_) = Loc.unloc loc in
- pr_located pr_id @@ Loc.tag ~loc:(Loc.make_loc (b,b + String.length (Id.to_string id))) id
+ pr_located pr_id (Some (Loc.make_loc (b,b + String.length (Id.to_string id))), id)
let pr_lname = function
- | (loc,Name id) -> pr_lident (loc,id)
- | lna -> pr_located Name.print lna
+ | {CAst.loc; v=Name id} -> pr_lident CAst.(make ?loc id)
+ | x -> pr_ast Name.print x
let pr_or_var pr = function
| ArgArg x -> pr x
- | ArgVar (loc,s) -> pr_lident (loc,s)
+ | ArgVar id -> pr_lident id
let pr_prim_token = function
| Numeral (n,s) -> str (if s then n else "-"^n)
@@ -263,8 +269,8 @@ let tag_var = tag Tag.variable
in
str "{| " ++ prlist_with_sep pr_semicolon pp l ++ str " |}", lpatrec
- | CPatAlias (p, id) ->
- pr_patt mt (las,E) p ++ str " as " ++ pr_id id, las
+ | CPatAlias (p, na) ->
+ pr_patt mt (las,E) p ++ str " as " ++ pr_lname na, las
| CPatCstr (c, None, []) ->
pr_reference c, latom
@@ -292,7 +298,7 @@ let tag_var = tag Tag.variable
pr_patt (fun()->str"(") (max_int,E) p ++ str")", latom
| CPatNotation (s,(l,ll),args) ->
- let strm_not, l_not = pr_notation (pr_patt mt) (fun _ _ _ -> mt()) s (l,ll,[]) in
+ let strm_not, l_not = pr_notation (pr_patt mt) (fun _ _ -> mt ()) (fun _ _ _ -> mt()) s (l,ll,[],[]) in
(if List.is_empty args||prec_less l_not (lapp,L) then strm_not else surround strm_not)
++ prlist (pr_patt spc (lapp,L)) args, if not (List.is_empty args) then lapp else l_not
@@ -310,7 +316,7 @@ let tag_var = tag Tag.variable
let pr_patt = pr_patt mt
- let pr_eqn pr (loc,(pl,rhs)) =
+ let pr_eqn pr {loc;v=(pl,rhs)} =
spc() ++ hov 4
(pr_with_comments ?loc
(str "| " ++
@@ -318,12 +324,12 @@ let tag_var = tag Tag.variable
++ str " =>") ++
pr_sep_com spc (pr ltop) rhs))
- let begin_of_binder l_bi =
+ let begin_of_binder l_bi =
let b_loc l = fst (Option.cata Loc.unloc (0,0) l) in
match l_bi with
- | CLocalDef((loc,_),_,_) -> b_loc loc
- | CLocalAssum((loc,_)::_,_,_) -> b_loc loc
- | CLocalPattern(loc,(_,_)) -> b_loc loc
+ | CLocalDef({loc},_,_) -> b_loc loc
+ | CLocalAssum({loc}::_,_,_) -> b_loc loc
+ | CLocalPattern{loc} -> b_loc loc
| _ -> assert false
let begin_of_binders = function
@@ -345,12 +351,12 @@ let tag_var = tag Tag.variable
| Generalized (b, b', t') ->
assert (match b with Implicit -> true | _ -> false);
begin match nal with
- |[loc,Anonymous] ->
+ |[{loc; v=Anonymous}] ->
hov 1 (str"`" ++ (surround_impl b'
((if t' then str "!" else mt ()) ++ pr t)))
- |[loc,Name id] ->
+ |[{loc; v=Name id}] ->
hov 1 (str "`" ++ (surround_impl b'
- (pr_lident (loc,id) ++ str " : " ++
+ (pr_lident CAst.(make ?loc id) ++ str " : " ++
(if t' then str "!" else mt()) ++ pr t)))
|_ -> anomaly (Pp.str "List of generalized binders have alwais one element.")
end
@@ -370,7 +376,7 @@ let tag_var = tag Tag.variable
surround (pr_lname na ++
pr_opt_no_spc (fun t -> str " :" ++ ws 1 ++ pr_c t) topt ++
str" :=" ++ spc() ++ pr_c c)
- | CLocalPattern (loc,(p,tyo)) ->
+ | CLocalPattern {CAst.loc; v = p,tyo} ->
let p = pr_patt lsimplepatt p in
match tyo with
| None ->
@@ -394,68 +400,6 @@ let tag_var = tag Tag.variable
if is_open then pr_delimited_binders pr_com_at sep pr_c
else pr_undelimited_binders sep pr_c
- let rec extract_prod_binders = let open CAst in function
- (* | CLetIn (loc,na,b,c) as x ->
- let bl,c = extract_prod_binders c in
- if bl = [] then [], x else CLocalDef (na,b) :: bl, c*)
- | { v = CProdN ([],c) } ->
- extract_prod_binders c
- | { loc; v = CProdN ([[_,Name id],bk,t],
- { v = CCases (LetPatternStyle,None, [{ v = CRef (Ident (_,id'),None)},None,None],[(_,([[p]],b))])} ) }
- when Id.equal id id' && not (Id.Set.mem id (free_vars_of_constr_expr b)) ->
- let bl,c = extract_prod_binders b in
- CLocalPattern (loc, (p,None)) :: bl, c
- | { loc; v = CProdN ((nal,bk,t)::bl,c) } ->
- let bl,c = extract_prod_binders (CAst.make ?loc @@ CProdN(bl,c)) in
- CLocalAssum (nal,bk,t) :: bl, c
- | c -> [], c
-
- let rec extract_lam_binders ce = let open CAst in match ce.v with
- (* | CLetIn (loc,na,b,c) as x ->
- let bl,c = extract_lam_binders c in
- if bl = [] then [], x else CLocalDef (na,b) :: bl, c*)
- | CLambdaN ([],c) ->
- extract_lam_binders c
- | CLambdaN ([[_,Name id],bk,t],
- { v = CCases (LetPatternStyle,None, [{ v = CRef (Ident (_,id'),None)},None,None],[(_,([[p]],b))])} )
- when Id.equal id id' && not (Id.Set.mem id (free_vars_of_constr_expr b)) ->
- let bl,c = extract_lam_binders b in
- CLocalPattern (ce.loc,(p,None)) :: bl, c
- | CLambdaN ((nal,bk,t)::bl,c) ->
- let bl,c = extract_lam_binders (CAst.make ?loc:ce.loc @@ CLambdaN(bl,c)) in
- CLocalAssum (nal,bk,t) :: bl, c
- | _ -> [], ce
-
- let split_lambda = CAst.with_loc_val (fun ?loc -> function
- | CLambdaN ([[na],bk,t],c) -> (na,t,c)
- | CLambdaN (([na],bk,t)::bl,c) -> (na,t, CAst.make ?loc @@ CLambdaN(bl,c))
- | CLambdaN ((na::nal,bk,t)::bl,c) -> (na,t, CAst.make ?loc @@ CLambdaN((nal,bk,t)::bl,c))
- | _ -> anomaly (Pp.str "ill-formed fixpoint body.")
- )
-
- let rename na na' t c =
- match (na,na') with
- | (_,Name id), (_,Name id') ->
- (na',t,replace_vars_constr_expr (Id.Map.singleton id id') c)
- | (_,Name id), (_,Anonymous) -> (na,t,c)
- | _ -> (na',t,c)
-
- let split_product na' = CAst.with_loc_val (fun ?loc -> function
- | CProdN ([[na],bk,t],c) -> rename na na' t c
- | CProdN (([na],bk,t)::bl,c) -> rename na na' t (CAst.make ?loc @@ CProdN(bl,c))
- | CProdN ((na::nal,bk,t)::bl,c) ->
- rename na na' t (CAst.make ?loc @@ CProdN((nal,bk,t)::bl,c))
- | _ -> anomaly (Pp.str "ill-formed fixpoint body.")
- )
-
- let rec split_fix n typ def =
- if Int.equal n 0 then ([],typ,def)
- else
- let (na,_,def) = split_lambda def in
- let (na,t,typ) = split_product na typ in
- let (bl,typ,def) = split_fix (n-1) typ def in
- (CLocalAssum ([na],default_binder_kind,t)::bl,typ,def)
-
let pr_recursive_decl pr pr_dangling dangling_with_for id bl annot t c =
let pr_body =
if dangling_with_for then pr_dangling else pr in
@@ -467,7 +411,7 @@ let tag_var = tag Tag.variable
let pr_guard_annot pr_aux bl (n,ro) =
match n with
| None -> mt ()
- | Some (loc, id) ->
+ | Some {loc; v = id} ->
match (ro : Constrexpr.recursion_order_expr) with
| CStructRec ->
let names_of_binder = function
@@ -484,11 +428,11 @@ let tag_var = tag Tag.variable
spc() ++ str "{" ++ keyword "measure" ++ spc () ++ pr_aux m ++ spc() ++ pr_id id++
(match r with None -> mt() | Some r -> str" on " ++ pr_aux r) ++ str"}"
- let pr_fixdecl pr prd dangling_with_for ((_,id),ro,bl,t,c) =
+ let pr_fixdecl pr prd dangling_with_for ({v=id},ro,bl,t,c) =
let annot = pr_guard_annot (pr lsimpleconstr) bl ro in
pr_recursive_decl pr prd dangling_with_for id bl annot t c
- let pr_cofixdecl pr prd dangling_with_for ((_,id),bl,t,c) =
+ let pr_cofixdecl pr prd dangling_with_for ({v=id},bl,t,c) =
pr_recursive_decl pr prd dangling_with_for id bl (mt()) t c
let pr_recursive pr_decl id = function
@@ -518,7 +462,7 @@ let tag_var = tag Tag.variable
let pr_simple_return_type pr na po =
(match na with
- | Some (_,Name id) ->
+ | Some {v=Name id} ->
spc () ++ keyword "as" ++ spc () ++ pr_id id
| _ -> mt ()) ++
pr_case_type pr po
@@ -549,7 +493,7 @@ let tag_var = tag Tag.variable
let pr_fun_sep = spc () ++ str "=>"
let pr_dangling_with_for sep pr inherited a =
- match a.CAst.v with
+ match a.v with
| (CFix (_,[_])|CCoFix(_,[_])) ->
pr sep (latom,E) a
| _ ->
@@ -564,18 +508,17 @@ let tag_var = tag Tag.variable
return (
hov 0 (keyword "fix" ++ spc () ++
pr_recursive
- (pr_fixdecl (pr mt) (pr_dangling_with_for mt pr)) (snd id) fix),
+ (pr_fixdecl (pr mt) (pr_dangling_with_for mt pr)) id.v fix),
lfix
)
| CCoFix (id,cofix) ->
return (
hov 0 (keyword "cofix" ++ spc () ++
pr_recursive
- (pr_cofixdecl (pr mt) (pr_dangling_with_for mt pr)) (snd id) cofix),
+ (pr_cofixdecl (pr mt) (pr_dangling_with_for mt pr)) id.v cofix),
lfix
)
- | CProdN _ ->
- let (bl,a) = extract_prod_binders a in
+ | CProdN (bl,a) ->
return (
hov 0 (
hov 2 (pr_delimited_binders pr_forall spc
@@ -583,8 +526,7 @@ let tag_var = tag Tag.variable
str "," ++ pr spc ltop a),
lprod
)
- | CLambdaN _ ->
- let (bl,a) = extract_lam_binders a in
+ | CLambdaN (bl,a) ->
return (
hov 0 (
hov 2 (pr_delimited_binders pr_fun spc
@@ -592,8 +534,8 @@ let tag_var = tag Tag.variable
pr_fun_sep ++ pr spc ltop a),
llambda
)
- | CLetIn ((_,Name x), ({ CAst.v = CFix((_,x'),[_])}
- | { CAst.v = CCoFix((_,x'),[_]) } as fx), t, b)
+ | CLetIn ({v=Name x}, ({ v = CFix({v=x'},[_])}
+ | { v = CCoFix({v=x'},[_]) } as fx), t, b)
when Id.equal x x' ->
return (
hv 0 (
@@ -649,7 +591,7 @@ let tag_var = tag Tag.variable
hv 0 (str"{|" ++ pr_record_body_gen (pr spc) l ++ str" |}"),
latom
)
- | CCases (LetPatternStyle,rtntypopt,[c,as_clause,in_clause],[(_,([[p]],b))]) ->
+ | CCases (LetPatternStyle,rtntypopt,[c,as_clause,in_clause],[{v=([[p]],b)}]) ->
return (
hv 0 (
keyword "let" ++ spc () ++ str"'" ++
@@ -722,10 +664,10 @@ let tag_var = tag Tag.variable
| CastCoerce -> str ":>"),
lcast
)
- | CNotation ("( _ )",([t],[],[])) ->
+ | CNotation ("( _ )",([t],[],[],[])) ->
return (pr (fun()->str"(") (max_int,L) t ++ str")", latom)
| CNotation (s,env) ->
- pr_notation (pr mt) (pr_binders_gen (pr mt ltop)) s env
+ pr_notation (pr mt) pr_patt (pr_binders_gen (pr mt ltop)) s env
| CGeneralization (bk,ak,c) ->
return (pr_generalization bk ak (pr mt ltop c), latom)
| CPrim p ->
diff --git a/printing/ppconstr.mli b/printing/ppconstr.mli
index 1320cce9b..cedeed5f3 100644
--- a/printing/ppconstr.mli
+++ b/printing/ppconstr.mli
@@ -10,29 +10,20 @@
objects and their subcomponents. *)
(** The default pretty-printers produce pretty-printing commands ({!Pp.t}). *)
-open Loc
open Libnames
open Constrexpr
open Names
open Misctypes
open Notation_term
-val extract_lam_binders :
- constr_expr -> local_binder_expr list * constr_expr
-val extract_prod_binders :
- constr_expr -> local_binder_expr list * constr_expr
-val split_fix :
- int -> constr_expr -> constr_expr ->
- local_binder_expr list * constr_expr * constr_expr
-
val prec_less : precedence -> tolerability -> bool
val pr_tight_coma : unit -> Pp.t
val pr_or_var : ('a -> Pp.t) -> 'a or_var -> Pp.t
-val pr_lident : Id.t located -> Pp.t
-val pr_lname : Name.t located -> Pp.t
+val pr_lident : lident -> Pp.t
+val pr_lname : lname -> Pp.t
val pr_with_comments : ?loc:Loc.t -> Pp.t -> Pp.t
val pr_com_at : int -> Pp.t
@@ -52,7 +43,7 @@ val pr_glob_level : glob_level -> Pp.t
val pr_glob_sort : glob_sort -> Pp.t
val pr_guard_annot : (constr_expr -> Pp.t) ->
local_binder_expr list ->
- ('a * Names.Id.t) option * recursion_order_expr ->
+ lident option * recursion_order_expr ->
Pp.t
val pr_record_body : (reference * constr_expr) list -> Pp.t
diff --git a/printing/pputils.ml b/printing/pputils.ml
index a544b4762..e779fc5fc 100644
--- a/printing/pputils.ml
+++ b/printing/pputils.ml
@@ -24,9 +24,11 @@ let pr_located pr (loc, x) =
before ++ x ++ after
| _ -> pr x
+let pr_ast pr { CAst.loc; v } = pr_located pr (loc, v)
+
let pr_or_var pr = function
| ArgArg x -> pr x
- | ArgVar (_,s) -> Names.Id.print s
+ | ArgVar {CAst.v=s} -> Names.Id.print s
let pr_with_occurrences pr keyword (occs,c) =
match occs with
diff --git a/printing/pputils.mli b/printing/pputils.mli
index f7f586b77..ec5c32fc4 100644
--- a/printing/pputils.mli
+++ b/printing/pputils.mli
@@ -12,6 +12,7 @@ open Locus
open Genredexpr
val pr_located : ('a -> Pp.t) -> 'a Loc.located -> Pp.t
+val pr_ast : ('a -> Pp.t) -> 'a CAst.t -> Pp.t
(** Prints an object surrounded by its commented location *)
val pr_or_var : ('a -> Pp.t) -> 'a or_var -> Pp.t
diff --git a/printing/ppvernac.ml b/printing/ppvernac.ml
index 950246c53..83cac7ddd 100644
--- a/printing/ppvernac.ml
+++ b/printing/ppvernac.ml
@@ -11,6 +11,8 @@ open Names
open CErrors
open Util
+open CAst
+
open Extend
open Vernacexpr
open Pputils
@@ -59,7 +61,7 @@ open Decl_kinds
let pr_ident_decl (lid, l) =
pr_lident lid ++ pr_universe_decl l
-
+
let string_of_fqid fqid =
String.concat "." (List.map Id.to_string fqid)
@@ -93,16 +95,35 @@ open Decl_kinds
let sep = fun _ -> spc()
let sep_v2 = fun _ -> str"," ++ spc()
- let pr_set_entry_type = function
+ let pr_at_level = function
+ | NumLevel n -> keyword "at" ++ spc () ++ keyword "level" ++ spc () ++ int n
+ | NextLevel -> keyword "at" ++ spc () ++ keyword "next" ++ spc () ++ keyword "level"
+
+ let pr_constr_as_binder_kind = function
+ | AsIdent -> keyword "as ident"
+ | AsIdentOrPattern -> keyword "as pattern"
+ | AsStrictPattern -> keyword "as strict pattern"
+
+ let pr_strict b = if b then str "strict " else mt ()
+
+ let pr_set_entry_type pr = function
| ETName -> str"ident"
| ETReference -> str"global"
- | ETPattern -> str"pattern"
- | ETConstr _ -> str"constr"
+ | ETPattern (b,None) -> pr_strict b ++ str"pattern"
+ | ETPattern (b,Some n) -> pr_strict b ++ str"pattern" ++ spc () ++ pr_at_level (NumLevel n)
+ | ETConstr lev -> str"constr" ++ pr lev
| ETOther (_,e) -> str e
+ | ETConstrAsBinder (bk,lev) -> pr lev ++ spc () ++ pr_constr_as_binder_kind bk
| ETBigint -> str "bigint"
| ETBinder true -> str "binder"
| ETBinder false -> str "closed binder"
- | ETBinderList _ | ETConstrList _ -> failwith "Internal entry type"
+
+ let pr_at_level_opt = function
+ | None -> mt ()
+ | Some n -> spc () ++ pr_at_level n
+
+ let pr_set_simple_entry_type =
+ pr_set_entry_type pr_at_level_opt
let pr_comment pr_c = function
| CommentConstr c -> pr_c c
@@ -217,7 +238,7 @@ open Decl_kinds
keyword "Module" ++ spc() ++ pr_lfqid id ++ str" := " ++
pr_located pr_qualid qid
- let rec pr_module_ast leading_space pr_c = let open CAst in function
+ let rec pr_module_ast leading_space pr_c = function
| { loc ; v = CMident qid } ->
if leading_space then
spc () ++ pr_located pr_qualid (loc, qid)
@@ -268,10 +289,10 @@ open Decl_kinds
prlist_strict (pr_module_vardecls pr_c) l
let pr_type_option pr_c = function
- | { CAst.v = CHole (k, Misctypes.IntroAnonymous, _) } -> mt()
+ | { v = CHole (k, Misctypes.IntroAnonymous, _) } -> mt()
| _ as c -> brk(0,2) ++ str" :" ++ pr_c c
- let pr_decl_notation prc ((loc,ntn),c,scopt) =
+ let pr_decl_notation prc ({loc; v=ntn},c,scopt) =
fnl () ++ keyword "where " ++ qs ntn ++ str " := "
++ Flags.without_option Flags.beautify prc c ++
pr_opt (fun sc -> str ": " ++ str sc) scopt
@@ -310,7 +331,7 @@ open Decl_kinds
let begin_of_inductive = function
| [] -> 0
- | (_,((loc,_),_))::_ -> Option.cata (fun loc -> fst (Loc.unloc loc)) 0 loc
+ | (_,({loc},_))::_ -> Option.cata (fun loc -> fst (Loc.unloc loc)) 0 loc
let pr_class_rawexpr = function
| FunClass -> keyword "Funclass"
@@ -360,22 +381,21 @@ open Decl_kinds
let pr_thm_token k = keyword (Kindops.string_of_theorem_kind k)
let pr_syntax_modifier = function
- | SetItemLevel (l,NextLevel) ->
- prlist_with_sep sep_v2 str l ++
- spc() ++ keyword "at next level"
- | SetItemLevel (l,NumLevel n) ->
+ | SetItemLevel (l,n) ->
+ prlist_with_sep sep_v2 str l ++ spc () ++ pr_at_level n
+ | SetItemLevelAsBinder (l,bk,n) ->
prlist_with_sep sep_v2 str l ++
- spc() ++ keyword "at level" ++ spc() ++ int n
- | SetLevel n -> keyword "at level" ++ spc() ++ int n
+ spc() ++ pr_at_level_opt n ++ spc() ++ pr_constr_as_binder_kind bk
+ | SetLevel n -> pr_at_level (NumLevel n)
| SetAssoc LeftA -> keyword "left associativity"
| SetAssoc RightA -> keyword "right associativity"
| SetAssoc NonA -> keyword "no associativity"
- | SetEntryType (x,typ) -> str x ++ spc() ++ pr_set_entry_type typ
+ | SetEntryType (x,typ) -> str x ++ spc() ++ pr_set_simple_entry_type typ
| SetOnlyPrinting -> keyword "only printing"
| SetOnlyParsing -> keyword "only parsing"
| SetCompatVersion v -> keyword("compat \"" ^ Flags.pr_version v ^ "\"")
- | SetFormat("text",s) -> keyword "format " ++ pr_located qs s
- | SetFormat(k,s) -> keyword "format " ++ qs k ++ spc() ++ pr_located qs s
+ | SetFormat("text",s) -> keyword "format " ++ pr_ast qs s
+ | SetFormat(k,s) -> keyword "format " ++ qs k ++ spc() ++ pr_ast qs s
let pr_syntax_modifiers = function
| [] -> mt()
@@ -519,7 +539,7 @@ open Decl_kinds
let rec aux = function
| SsEmpty -> "()"
| SsType -> "(Type)"
- | SsSingl (_,id) -> "("^Id.to_string id^")"
+ | 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^")"
@@ -643,7 +663,7 @@ open Decl_kinds
++ spc() ++ pr_smart_global q
++ spc() ++ str"[" ++ prlist_with_sep sep pr_opt_scope scl ++ str"]"
)
- | VernacInfix (((_,s),mv),q,sn) -> (* A Verifier *)
+ | VernacInfix (({v=s},mv),q,sn) -> (* A Verifier *)
return (
hov 0 (hov 0 (keyword "Infix "
++ qs s ++ str " :=" ++ pr_constrarg q) ++
@@ -652,7 +672,7 @@ open Decl_kinds
| None -> mt()
| Some sc -> spc() ++ str":" ++ spc() ++ str sc))
)
- | VernacNotation (c,((_,s),l),opt) ->
+ | VernacNotation (c,({v=s},l),opt) ->
return (
hov 2 (keyword "Notation" ++ spc() ++ qs s ++
str " :=" ++ Flags.without_option Flags.beautify pr_constrarg c ++ pr_syntax_modifiers l ++
@@ -662,7 +682,7 @@ open Decl_kinds
)
| VernacSyntaxExtension (_, (s, l)) ->
return (
- keyword "Reserved Notation" ++ spc() ++ pr_located qs s ++
+ keyword "Reserved Notation" ++ spc() ++ pr_ast qs s ++
pr_syntax_modifiers l
)
| VernacNotationAddFormat(s,k,v) ->
@@ -674,7 +694,7 @@ open Decl_kinds
| VernacDefinition ((discharge,kind),id,b) -> (* A verifier... *)
let pr_def_token dk =
keyword (
- if Name.is_anonymous (snd (fst id))
+ if Name.is_anonymous (fst id).v
then "Goal"
else Kindops.string_of_definition_object_kind dk)
in
@@ -693,7 +713,7 @@ open Decl_kinds
in
(pr_binders_arg bl,ty,Some (pr_reduce red ++ pr_lconstr body))
| ProveBody (bl,t) ->
- let typ u = if snd (fst id) = Anonymous then (assert (bl = []); u) else (str" :" ++ u) in
+ let typ u = if (fst id).v = Anonymous then (assert (bl = []); u) else (str" :" ++ u) in
(pr_binders_arg bl, typ (pr_spc_lconstr t), None) in
let (binds,typ,c) = pr_def_body b in
return (
@@ -871,16 +891,16 @@ open Decl_kinds
return (
hov 1 (
(if abst then keyword "Declare" ++ spc () else mt ()) ++
- keyword "Instance" ++
- (match instid with
- | (loc, Name id), l -> spc () ++ pr_ident_decl ((loc, id),l) ++ spc ()
- | (_, Anonymous), _ -> mt ()) ++
- pr_and_type_binders_arg sup ++
+ 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 () ++
(match bk with Implicit -> str "! " | Explicit -> mt ()) ++
pr_constr cl ++ pr_hint_info pr_constr_pattern_expr info ++
(match props with
- | Some (true, { CAst.v = CRecord l}) -> spc () ++ str":=" ++ spc () ++ str"{" ++ pr_record_body l ++ str "}"
+ | Some (true, { v = CRecord l}) -> spc () ++ str":=" ++ spc () ++ str"{" ++ pr_record_body l ++ str "}"
| Some (true,_) -> assert false
| Some (false,p) -> spc () ++ str":=" ++ spc () ++ pr_constr p
| None -> mt()))
@@ -1013,7 +1033,7 @@ open Decl_kinds
hov 2 (
keyword "Arguments" ++ spc() ++
pr_smart_global q ++
- let pr_s = function None -> str"" | Some (_,s) -> str "%" ++ str s in
+ let pr_s = function None -> str"" | Some {v=s} -> str "%" ++ str s in
let pr_if b x = if b then x else str "" in
let pr_br imp x = match imp with
| Vernacexpr.Implicit -> str "[" ++ x ++ str "]"
@@ -1219,9 +1239,9 @@ let pr_vernac_flag =
(fun f a -> pr_vernac_flag f ++ spc() ++ a)
f
(pr_vernac_expr v' ++ sep_end v')
- | VernacTime (_,(_,v)) ->
+ | VernacTime (_,{v}) ->
return (keyword "Time" ++ spc() ++ pr_vernac_control v)
- | VernacRedirect (s, (_,v)) ->
+ | VernacRedirect (s, {v}) ->
return (keyword "Redirect" ++ spc() ++ qs s ++ spc() ++ pr_vernac_control v)
| VernacTimeout(n,v) ->
return (keyword "Timeout " ++ int n ++ spc() ++ pr_vernac_control v)
diff --git a/printing/ppvernac.mli b/printing/ppvernac.mli
index 34b4fb97f..603be6308 100644
--- a/printing/ppvernac.mli
+++ b/printing/ppvernac.mli
@@ -9,6 +9,8 @@
(** This module implements pretty-printers for vernac_expr syntactic
objects and their subcomponents. *)
+val pr_set_entry_type : ('a -> Pp.t) -> 'a Extend.constr_entry_key_gen -> Pp.t
+
(** Prints a fixpoint body *)
val pr_rec_definition : (Vernacexpr.fixpoint_expr * Vernacexpr.decl_notation list) -> Pp.t
diff --git a/printing/prettyp.mli b/printing/prettyp.mli
index fd7f1f92b..c1d8f1d37 100644
--- a/printing/prettyp.mli
+++ b/printing/prettyp.mli
@@ -33,10 +33,10 @@ val print_eval :
Constrexpr.constr_expr -> EConstr.unsafe_judgment -> Pp.t
val print_name : env -> Evd.evar_map -> reference or_by_notation ->
- Vernacexpr.univ_name_list option -> Pp.t
+ Universes.univ_name_list option -> Pp.t
val print_opaque_name : env -> Evd.evar_map -> reference -> Pp.t
val print_about : env -> Evd.evar_map -> reference or_by_notation ->
- Vernacexpr.univ_name_list option -> Pp.t
+ Universes.univ_name_list option -> Pp.t
val print_impargs : reference or_by_notation -> Pp.t
(** Pretty-printing functions for classes and coercions *)
diff --git a/printing/printmod.mli b/printing/printmod.mli
index 97ed063fe..4f15dd393 100644
--- a/printing/printmod.mli
+++ b/printing/printmod.mli
@@ -13,6 +13,6 @@ val printable_body : DirPath.t -> bool
val pr_mutual_inductive_body : Environ.env ->
MutInd.t -> Declarations.mutual_inductive_body ->
- Vernacexpr.univ_name_list option -> Pp.t
+ Universes.univ_name_list option -> Pp.t
val print_module : bool -> ModPath.t -> Pp.t
val print_modtype : ModPath.t -> Pp.t
diff --git a/proofs/proof_global.ml b/proofs/proof_global.ml
index 833e34c33..0a50bcf8c 100644
--- a/proofs/proof_global.ml
+++ b/proofs/proof_global.ml
@@ -79,7 +79,7 @@ type proof_object = {
type proof_ending =
| Admitted of Names.Id.t * Decl_kinds.goal_kind * Entries.parameter_entry * UState.t
| Proved of Vernacexpr.opacity_flag *
- Vernacexpr.lident option *
+ Misctypes.lident option *
proof_object
type proof_terminator = proof_ending -> unit
type closed_proof = proof_object * proof_terminator
diff --git a/proofs/proof_global.mli b/proofs/proof_global.mli
index 29445a746..06647bf3e 100644
--- a/proofs/proof_global.mli
+++ b/proofs/proof_global.mli
@@ -50,7 +50,7 @@ type proof_ending =
| Admitted of Names.Id.t * Decl_kinds.goal_kind * Entries.parameter_entry *
UState.t
| Proved of Vernacexpr.opacity_flag *
- Vernacexpr.lident option *
+ Misctypes.lident option *
proof_object
type proof_terminator
type closed_proof = proof_object * proof_terminator
diff --git a/stm/stm.ml b/stm/stm.ml
index 92587b8ea..e7c371798 100644
--- a/stm/stm.ml
+++ b/stm/stm.ml
@@ -565,8 +565,8 @@ end = struct (* {{{ *)
let reachable id = reachable !vcs id
let mk_branch_name { expr = x } = Branch.make
(match Vernacprop.under_control x with
- | VernacDefinition (_,((_, Name i),_),_) -> Id.to_string i
- | VernacStartTheoremProof (_,[((_,i),_),_]) -> Id.to_string i
+ | VernacDefinition (_,({CAst.v=Name i},_),_) -> Id.to_string i
+ | VernacStartTheoremProof (_,[({CAst.v=i},_),_]) -> Id.to_string i
| _ -> "branch")
let edit_branch = Branch.make "edit"
let branch ?root ?pos name kind = vcs := branch !vcs ?root ?pos name kind
@@ -1174,7 +1174,7 @@ end = struct (* {{{ *)
match Vernacprop.under_control v with
| VernacResetInitial ->
Stateid.initial, VtNow
- | VernacResetName (_,name) ->
+ | VernacResetName {CAst.v=name} ->
let id = VCS.get_branch_pos (VCS.current_branch ()) in
(try
let oid =
@@ -1236,7 +1236,7 @@ let set_compilation_hints file =
let get_hint_ctx loc =
let s = Aux_file.get ?loc !hints "context_used" in
let ids = List.map Names.Id.of_string (Str.split (Str.regexp " ") s) in
- let ids = List.map (fun id -> Loc.tag id) ids in
+ let ids = List.map (fun id -> CAst.make id) ids in
match ids with
| [] -> SsEmpty
| x :: xs ->
@@ -1956,8 +1956,8 @@ end = struct (* {{{ *)
=
let e, time, batch, fail =
let rec find ~time ~batch ~fail = function
- | VernacTime (batch,(_,e)) -> find ~time:true ~batch ~fail e
- | VernacRedirect (_,(_,e)) -> find ~time ~batch ~fail e
+ | VernacTime (batch,{CAst.v=e}) -> find ~time:true ~batch ~fail e
+ | VernacRedirect (_,{CAst.v=e}) -> find ~time ~batch ~fail e
| VernacFail e -> find ~time ~batch ~fail:true e
| e -> e, time, batch, fail in
find ~time:false ~batch:false ~fail:false e in
diff --git a/stm/vernac_classifier.ml b/stm/vernac_classifier.ml
index cbbb54e45..93d58b2a9 100644
--- a/stm/vernac_classifier.ml
+++ b/stm/vernac_classifier.ml
@@ -6,10 +6,11 @@
(* * GNU Lesser General Public License Version 2.1 *)
(************************************************************************)
-open Vernacexpr
open CErrors
open Util
open Pp
+open CAst
+open Vernacexpr
let default_proof_mode () = Proof_global.get_default_proof_mode_name () [@ocaml.warning "-3"]
@@ -87,13 +88,14 @@ let classify_vernac e =
| VernacUnsetOption (["Default";"Proof";"Using"])
| VernacSetOption (["Default";"Proof";"Using"],_) -> VtSideff [], VtNow
(* StartProof *)
- | VernacDefinition ((Decl_kinds.DoDischarge,_),((_,i),_),ProveBody _) ->
- VtStartProof(default_proof_mode (),Doesn'tGuaranteeOpacity, idents_of_name i), VtLater
- | VernacDefinition (_,((_,i),_),ProveBody _) ->
+ | VernacDefinition ((Decl_kinds.DoDischarge,_),({v=i},_),ProveBody _) ->
+ VtStartProof(default_proof_mode (),Doesn'tGuaranteeOpacity, idents_of_name i), VtLater
+
+ | VernacDefinition (_,({v=i},_),ProveBody _) ->
let guarantee = if poly then Doesn'tGuaranteeOpacity else GuaranteesOpacity in
VtStartProof(default_proof_mode (),guarantee, idents_of_name i), VtLater
| VernacStartTheoremProof (_,l) ->
- let ids = List.map (fun (((_, i), _), _) -> i) l in
+ let ids = List.map (fun (({v=i}, _), _) -> i) l in
let guarantee = if poly then Doesn'tGuaranteeOpacity else GuaranteesOpacity in
VtStartProof (default_proof_mode (),guarantee,ids), VtLater
| VernacFixpoint (discharge,l) ->
@@ -102,7 +104,7 @@ let classify_vernac e =
else GuaranteesOpacity
in
let ids, open_proof =
- List.fold_left (fun (l,b) ((((_,id),_),_,_,_,p),_) ->
+ List.fold_left (fun (l,b) ((({v=id},_),_,_,_,p),_) ->
id::l, b || p = None) ([],false) l in
if open_proof
then VtStartProof (default_proof_mode (),guarantee,ids), VtLater
@@ -113,29 +115,29 @@ let classify_vernac e =
else GuaranteesOpacity
in
let ids, open_proof =
- List.fold_left (fun (l,b) ((((_,id),_),_,_,p),_) ->
+ List.fold_left (fun (l,b) ((({v=id},_),_,_,p),_) ->
id::l, b || p = None) ([],false) l in
if open_proof
then VtStartProof (default_proof_mode (),guarantee,ids), VtLater
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, _) -> snd id) l) l) in
- VtSideff ids, VtLater
- | VernacDefinition (_,((_,id),_),DefineBody _) -> VtSideff (idents_of_name id), VtLater
+ let ids = List.flatten (List.map (fun (_,(l,_)) -> List.map (fun (id, _) -> id.v) l) l) in
+ VtSideff ids, VtLater
+ | VernacDefinition (_,({v=id},_),DefineBody _) -> VtSideff (idents_of_name id), VtLater
| VernacInductive (_, _,_,l) ->
- let ids = List.map (fun (((_,((_,id),_)),_,_,_,cl),_) -> id :: match cl with
- | Constructors l -> List.map (fun (_,((_,id),_)) -> id) l
- | RecordDecl (oid,l) -> (match oid with Some (_,x) -> [x] | _ -> []) @
+ let ids = List.map (fun (((_,({v=id},_)),_,_,_,cl),_) -> id :: match cl with
+ | Constructors l -> List.map (fun (_,({v=id},_)) -> id) l
+ | RecordDecl (oid,l) -> (match oid with Some {v=x} -> [x] | _ -> []) @
CList.map_filter (function
- | ((_,AssumExpr((_,Names.Name n),_)),_),_ -> Some n
+ | ((_,AssumExpr({v=Names.Name n},_)),_),_ -> Some n
| _ -> None) l) l in
VtSideff (List.flatten ids), VtLater
| VernacScheme l ->
- let ids = List.map snd (CList.map_filter (fun (x,_) -> x) l) in
+ let ids = List.map (fun {v}->v) (CList.map_filter (fun (x,_) -> x) l) in
VtSideff ids, VtLater
- | VernacCombinedScheme ((_,id),_) -> VtSideff [id], VtLater
- | VernacBeginSection (_,id) -> VtSideff [id], VtLater
+ | VernacCombinedScheme ({v=id},_) -> VtSideff [id], VtLater
+ | VernacBeginSection {v=id} -> VtSideff [id], VtLater
| VernacUniverse _ | VernacConstraint _
| VernacCanonical _ | VernacCoercion _ | VernacIdentityCoercion _
| VernacAddLoadPath _ | VernacRemoveLoadPath _ | VernacAddMLPath _
@@ -159,10 +161,10 @@ let classify_vernac e =
(* (Local) Notations have to disappear *)
| VernacEndSegment _ -> VtSideff [], VtNow
(* Modules with parameters have to be executed: can import notations *)
- | VernacDeclareModule (exp,(_,id),bl,_)
- | VernacDefineModule (exp,(_,id),bl,_,_) ->
+ | VernacDeclareModule (exp,{v=id},bl,_)
+ | VernacDefineModule (exp,{v=id},bl,_,_) ->
VtSideff [id], if bl = [] && exp = None then VtLater else VtNow
- | VernacDeclareModuleType ((_,id),bl,_,_) ->
+ | VernacDeclareModuleType ({v=id},bl,_,_) ->
VtSideff [id], if bl = [] then VtLater else VtNow
(* These commands alter the parser *)
| VernacOpenCloseScope _ | VernacDelimiters _ | VernacBindScope _
@@ -198,7 +200,7 @@ let classify_vernac e =
) poly f in
static_classifier ~poly e
| VernacTimeout (_,e) -> static_control_classifier ~poly e
- | VernacTime (_,(_,e)) | VernacRedirect (_, (_,e)) ->
+ | VernacTime (_,{v=e}) | VernacRedirect (_, {v=e}) ->
static_control_classifier ~poly e
| VernacFail e -> (* Fail Qed or Fail Lemma must not join/fork the DAG *)
(match static_control_classifier ~poly e with
diff --git a/tactics/equality.ml b/tactics/equality.ml
index 674d01777..9a1ac768c 100644
--- a/tactics/equality.ml
+++ b/tactics/equality.ml
@@ -1484,7 +1484,7 @@ let simpleInjClause flags with_evars = function
| Some c -> onInductionArg (fun clear_flag -> onEquality with_evars (injEq flags ~old:true with_evars clear_flag None)) c
let injConcl flags = injClause flags None false None
-let injHyp flags clear_flag id = injClause flags None false (Some (clear_flag,ElimOnIdent (Loc.tag id)))
+let injHyp flags clear_flag id = injClause flags None false (Some (clear_flag,ElimOnIdent CAst.(make id)))
let decompEqThen keep_proofs ntac (lbeq,_,(t,t1,t2) as u) clause =
Proofview.Goal.enter begin fun gl ->
diff --git a/tactics/tactics.ml b/tactics/tactics.ml
index 29a30b4a2..7e281e2fe 100644
--- a/tactics/tactics.ml
+++ b/tactics/tactics.ml
@@ -1190,7 +1190,7 @@ let onOpenInductionArg env sigma tac = function
let sigma = Tacmach.New.project gl in
tac clear_flag (sigma,(c,NoBindings))
end))
- | clear_flag,ElimOnIdent (_,id) ->
+ | clear_flag,ElimOnIdent {CAst.v=id} ->
(* A quantified hypothesis *)
Tacticals.New.tclTHEN
(try_intros_until_id_check id)
@@ -1206,7 +1206,7 @@ let onInductionArg tac = function
Tacticals.New.tclTHEN
(intros_until_n n)
(Tacticals.New.onLastHyp (fun c -> tac clear_flag (c,NoBindings)))
- | clear_flag,ElimOnIdent (_,id) ->
+ | clear_flag,ElimOnIdent {CAst.v=id} ->
(* A quantified hypothesis *)
Tacticals.New.tclTHEN
(try_intros_until_id_check id)
diff --git a/test-suite/bugs/closed/5532.v b/test-suite/bugs/closed/5532.v
new file mode 100644
index 000000000..ee5446e54
--- /dev/null
+++ b/test-suite/bugs/closed/5532.v
@@ -0,0 +1,15 @@
+(* A wish granted by the new support for patterns in notations *)
+
+Local Notation mkmatch0 e p
+ := match e with
+ | p => true
+ | _ => false
+ end.
+Local Notation "'mkmatch' [[ e ]] [[ p ]]"
+ := match e with
+ | p => true
+ | _ => false
+ end
+ (at level 0, p pattern).
+Check mkmatch0 _ ((0, 0)%core).
+Check mkmatch [[ _ ]] [[ ((0, 0)%core) ]].
diff --git a/test-suite/bugs/closed/6529.v b/test-suite/bugs/closed/6529.v
new file mode 100644
index 000000000..8d9081999
--- /dev/null
+++ b/test-suite/bugs/closed/6529.v
@@ -0,0 +1,16 @@
+Require Import Vector Program.
+
+Program Definition append_nil_def :=
+ forall A n (ls: t A n), append ls (nil A) = ls. (* Works *)
+
+Lemma append_nil : append_nil_def. (* Works *)
+Proof.
+Admitted.
+
+Program Lemma append_nil' :
+ forall A n (ls: t A n), append ls (nil A) = ls.
+Abort.
+
+Fail Program Lemma append_nil'' :
+ forall A B n (ls: t A n), append ls (nil A) = ls.
+(* Error: Anomaly "Evar ?X25 was not declared." Please report at http://coq.inria.fr/bugs/. *)
diff --git a/test-suite/bugs/opened/6602.v b/test-suite/bugs/opened/6602.v
new file mode 100644
index 000000000..3690adf90
--- /dev/null
+++ b/test-suite/bugs/opened/6602.v
@@ -0,0 +1,17 @@
+Require Import Omega.
+
+Lemma test_nat:
+ forall n, (5 + pred n <= 5 + n).
+Proof.
+ intros.
+ zify.
+ omega.
+Qed.
+
+Lemma test_N:
+ forall n, (5 + N.pred n <= 5 + n)%N.
+Proof.
+ intros.
+ zify.
+ omega.
+Qed.
diff --git a/test-suite/modules/cumpoly.v b/test-suite/modules/cumpoly.v
new file mode 100644
index 000000000..654b86cb4
--- /dev/null
+++ b/test-suite/modules/cumpoly.v
@@ -0,0 +1,19 @@
+Set 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.
diff --git a/test-suite/output/Notations.out b/test-suite/output/Notations.out
index 2f0ee765d..891296b0a 100644
--- a/test-suite/output/Notations.out
+++ b/test-suite/output/Notations.out
@@ -41,7 +41,7 @@ fun x : nat => ifn x is succ n then n else 0
-4
: Z
The command has indeed failed with message:
-x should not be bound in a recursive pattern of the right-hand side.
+Cannot find where the recursive pattern starts.
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.
diff --git a/test-suite/output/Notations2.out b/test-suite/output/Notations2.out
index 121a369a9..6ffe56e11 100644
--- a/test-suite/output/Notations2.out
+++ b/test-suite/output/Notations2.out
@@ -17,10 +17,9 @@ fun (P : nat -> nat -> Prop) (x : nat) => exists y, P x y
∃ n p : nat, n + p = 0
: Prop
let a := 0 in
-∃ x y : nat,
-let b := 1 in
-let c := b in
-let d := 2 in ∃ z : nat, let e := 3 in let f := 4 in x + y = z + d
+∃ (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
diff --git a/test-suite/output/Notations2.v b/test-suite/output/Notations2.v
index 531398bb0..923caedac 100644
--- a/test-suite/output/Notations2.v
+++ b/test-suite/output/Notations2.v
@@ -36,8 +36,9 @@ 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).
+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).
diff --git a/test-suite/output/Notations3.out b/test-suite/output/Notations3.out
index 1b5725275..e6a6e0288 100644
--- a/test-suite/output/Notations3.out
+++ b/test-suite/output/Notations3.out
@@ -138,3 +138,100 @@ amatch = mmatch 0 (with 0 => 1| 1 => 2 end)
: unit
alist = [0; 1; 2]
: list nat
+! '{{x, y}}, x + y = 0
+ : Prop
+exists x : nat,
+ nat ->
+ exists y : nat,
+ nat ->
+ exists '{{u, t}}, forall z1 : nat, z1 = 0 /\ x + y = 0 /\ u + t = 0
+ : Prop
+exists x : nat,
+ nat ->
+ exists y : nat,
+ nat ->
+ exists '{{z, t}}, forall z2 : nat, z2 = 0 /\ 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
+{{{{True, nat -> True}}, nat -> True}}
+ : Prop * Prop * Prop
+{{D 1, 2}}
+ : nat * nat * (nat * nat * (nat * nat))
+! a b : nat # True #
+ : Prop * (Prop * Prop)
+!!!! 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 (S (S O)) (pair (S O) O)) (pair (pair O (S (S O))) (S O)))
+ (pair (S O) (pair (S (S O)) O))) (pair (pair O (S O)) (S (S O)))
+ : 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
diff --git a/test-suite/output/Notations3.v b/test-suite/output/Notations3.v
index a8d6c97fb..c98bfff41 100644
--- a/test-suite/output/Notations3.v
+++ b/test-suite/output/Notations3.v
@@ -253,3 +253,170 @@ Definition alist := [0;1;2].
Print alist.
End B.
+
+(* 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 inbetween 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 200, 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 }}.
+
+Notation "! x .. y # A #" :=
+ ((forall x, x=x), .. ((forall y, y=y), A) ..)
+ (at level 200, x binder).
+Check ! a b : nat # True #.
+
+Notation "!!!! x .. y # A #" :=
+ (((forall x, x=x),(forall x, x=0)), .. (((forall y, y=y),(forall y, y=0)), A) ..)
+ (at level 200, x binder).
+Check !!!! a b : nat # True #.
+
+Notation "@@ x .. y # A # B #" :=
+ ((forall x, .. (forall y, A) ..), (forall x, .. (forall y, B) ..))
+ (at level 200, 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 *)
+
+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.
+
+(* 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 ident, 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 *)
+
+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.
+
+(* 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).
diff --git a/test-suite/output/PatternsInBinders.out b/test-suite/output/PatternsInBinders.out
index 95be04c32..8a6d94c73 100644
--- a/test-suite/output/PatternsInBinders.out
+++ b/test-suite/output/PatternsInBinders.out
@@ -31,7 +31,7 @@ exists '(x, y) '(z, w), swap (x, y) = (z, w)
: Prop
both_z =
fun pat : nat * nat =>
-let '(n, p) as pat0 := pat return (F pat0) in (Z n, Z p) : F (n, p)
+let '(n, p) as x := pat return (F x) in (Z n, Z p) : F (n, p)
: forall pat : nat * nat, F pat
fun '(x, y) '(z, t) => swap (x, y) = (z, t)
: A * B -> B * A -> Prop
@@ -39,3 +39,9 @@ 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
+
+Argument scope is [nat_scope]
+fun x : nat => x + x
+ : nat -> nat
diff --git a/test-suite/output/PatternsInBinders.v b/test-suite/output/PatternsInBinders.v
index 0bad472f4..d671053c0 100644
--- a/test-suite/output/PatternsInBinders.v
+++ b/test-suite/output/PatternsInBinders.v
@@ -67,3 +67,8 @@ 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.
diff --git a/test-suite/success/Notations2.v b/test-suite/success/Notations2.v
index 2655b651a..7c2cf3ee5 100644
--- a/test-suite/success/Notations2.v
+++ b/test-suite/success/Notations2.v
@@ -92,16 +92,37 @@ Check ##### 0 _ 0%bool 0%bool : prod' bool bool.
Check fun A (x :prod' bool A) => match x with ##### 0 _ y 0%bool => 2 | _ => 1 end.
(* 10. Check computation of binding variable through other notations *)
-(* i should be detected as binding variable and the scopes not being checked *)
-
+(* 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/coq/coq/issues/6078#issuecomment-342287412 *)
-Module A.
+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 A.
+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.
diff --git a/theories/Arith/Lt.v b/theories/Arith/Lt.v
index 035c4e466..2c2bea4a6 100644
--- a/theories/Arith/Lt.v
+++ b/theories/Arith/Lt.v
@@ -107,6 +107,11 @@ Proof.
intros. symmetry. now apply Nat.lt_succ_pred with m.
Qed.
+Lemma S_pred_pos n: O < n -> n = S (pred n).
+Proof.
+ apply S_pred.
+Qed.
+
Lemma lt_pred n m : S n < m -> n < pred m.
Proof.
apply Nat.lt_succ_lt_pred.
diff --git a/theories/Init/Logic.v b/theories/Init/Logic.v
index 037d37daf..053ed601f 100644
--- a/theories/Init/Logic.v
+++ b/theories/Init/Logic.v
@@ -267,6 +267,13 @@ Notation "'exists2' x : A , p & q" := (ex2 (A:=A) (fun x => p) (fun x => q))
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.
diff --git a/theories/Init/Notations.v b/theories/Init/Notations.v
index 5e8d2faa5..a9051e761 100644
--- a/theories/Init/Notations.v
+++ b/theories/Init/Notations.v
@@ -78,6 +78,33 @@ Reserved Notation "{ x : A | 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 : 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.
+
+(** Scopes *)
+
Delimit Scope type_scope with type.
Delimit Scope function_scope with function.
Delimit Scope core_scope with core.
diff --git a/theories/Init/Specif.v b/theories/Init/Specif.v
index 3b4f833a3..47e8a7558 100644
--- a/theories/Init/Specif.v
+++ b/theories/Init/Specif.v
@@ -53,6 +53,15 @@ Notation "{ x : A & P }" := (sigT (A:=A) (fun x => P)) : type_scope.
Notation "{ x : A & P & Q }" := (sigT2 (A:=A) (fun x => P) (fun x => Q)) :
type_scope.
+Notation "{ ' pat | P }" := (sig (fun pat => P)) : type_scope.
+Notation "{ ' pat | P & Q }" := (sig2 (fun pat => P) (fun pat => Q)) : type_scope.
+Notation "{ ' pat : A | P }" := (sig (A:=A) (fun pat => P)) : type_scope.
+Notation "{ ' pat : A | P & Q }" := (sig2 (A:=A) (fun pat => P) (fun pat => Q)) :
+ type_scope.
+Notation "{ ' pat : A & P }" := (sigT (A:=A) (fun pat => P)) : type_scope.
+Notation "{ ' pat : A & P & Q }" := (sigT2 (A:=A) (fun pat => P) (fun pat => Q)) :
+ type_scope.
+
Add Printing Let sig.
Add Printing Let sig2.
Add Printing Let sigT.
diff --git a/theories/Unicode/Utf8_core.v b/theories/Unicode/Utf8_core.v
index a0545c0a4..95c8336d2 100644
--- a/theories/Unicode/Utf8_core.v
+++ b/theories/Unicode/Utf8_core.v
@@ -10,10 +10,12 @@
(* Logic *)
-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.
+Notation "∀ x .. y , P" := (forall x, .. (forall y, P) ..)
+ (at level 200, x binder, y binder, right associativity,
+ format "'[ ' ∀ x .. y ']' , P") : type_scope.
+Notation "∃ x .. y , P" := (exists x, .. (exists y, P) ..)
+ (at level 200, x binder, y binder, right associativity,
+ format "'[ ' ∃ x .. y ']' , P") : type_scope.
Notation "x ∨ y" := (x \/ y) (at level 85, right associativity) : type_scope.
Notation "x ∧ y" := (x /\ y) (at level 80, right associativity) : type_scope.
@@ -25,5 +27,6 @@ Notation "¬ x" := (~x) (at level 75, right associativity) : type_scope.
Notation "x ≠ y" := (x <> y) (at level 70) : type_scope.
(* Abstraction *)
-Notation "'λ' x .. y , t" := (fun x => .. (fun y => t) ..)
- (at level 200, x binder, y binder, right associativity).
+Notation "'λ' x .. y , t" := (fun x => .. (fun y => t) ..)
+ (at level 200, x binder, y binder, right associativity,
+ format "'[ ' 'λ' x .. y ']' , t").
diff --git a/toplevel/vernac.ml b/toplevel/vernac.ml
index 1f681d9cf..92dee84f3 100644
--- a/toplevel/vernac.ml
+++ b/toplevel/vernac.ml
@@ -170,7 +170,7 @@ let rec interp_vernac ~time ~check ~interactive ~state (loc,com) =
(* The -time option is only supported from console-based
clients due to the way it prints. *)
if time then print_cmd_header ?loc com;
- let com = if time then VernacTime(time,(loc,com)) else com in
+ let com = if time then VernacTime(time, CAst.make ?loc com) else com in
interp com
with reraise ->
(* XXX: In non-interactive mode edit_at seems to do very weird
diff --git a/vernac/classes.ml b/vernac/classes.ml
index 4a2dba859..695be74bb 100644
--- a/vernac/classes.ml
+++ b/vernac/classes.ml
@@ -132,7 +132,7 @@ let new_instance ?(abstract=false) ?(global=false) ?(refine= !refine_instance)
~program_mode poly ctx (instid, bk, cl) props ?(generalize=true)
?(tac:unit Proofview.tactic option) ?hook pri =
let env = Global.env() in
- let ((loc, instid), pl) = instid in
+ let ({CAst.loc;v=instid}, pl) = instid in
let sigma, decl = Univdecls.interp_univ_decl_opt env pl in
let tclass, ids =
match bk with
@@ -410,7 +410,7 @@ let context poly l =
let nstatus = match b with
| None ->
pi3 (ComAssumption.declare_assumption false decl (t, univs) Universes.empty_binders [] impl
- Vernacexpr.NoInline (Loc.tag id))
+ Vernacexpr.NoInline (CAst.make id))
| Some b ->
let decl = (Discharge, poly, Definition) in
let entry = Declare.definition_entry ~univs ~types:t b in
diff --git a/vernac/comAssumption.ml b/vernac/comAssumption.ml
index 5d7adb24a..7e5b941ad 100644
--- a/vernac/comAssumption.ml
+++ b/vernac/comAssumption.ml
@@ -42,7 +42,7 @@ let should_axiom_into_instance = function
true
| Global | Local -> !axiom_into_instance
-let declare_assumption is_coe (local,p,kind) (c,ctx) pl imps impl nl (_,ident) =
+let declare_assumption is_coe (local,p,kind) (c,ctx) pl imps impl nl {CAst.v=ident} =
match local with
| Discharge when Lib.sections_are_opened () ->
let ctx = match ctx with
@@ -109,7 +109,7 @@ let declare_assumptions idl is_coe k (c,uctx) pl imps nl =
let maybe_error_many_udecls = function
- | ((loc,id), Some _) ->
+ | ({CAst.loc;v=id}, Some _) ->
user_err ?loc ~hdr:"many_universe_declarations"
Pp.(str "When declaring multiple axioms in one command, " ++
str "only the first is allowed a universe binder " ++
@@ -126,7 +126,7 @@ let process_assumptions_udecls kind l =
in
let () = match kind, udecl with
| (Discharge, _, _), Some _ when Lib.sections_are_opened () ->
- let loc = fst first_id in
+ let loc = first_id.CAst.loc in
let msg = Pp.str "Section variables cannot be polymorphic." in
user_err ?loc msg
| _ -> ()
@@ -151,8 +151,8 @@ let do_assumptions kind nl l =
let (sigma,_,_),l = List.fold_left_map (fun (sigma,env,ienv) (is_coe,(idl,c)) ->
let sigma,(t,imps) = interp_assumption sigma env ienv [] c in
let env =
- push_named_context (List.map (fun (_,id) -> LocalAssum (id,t)) idl) env in
- let ienv = List.fold_right (fun (_,id) ienv ->
+ push_named_context (List.map (fun {CAst.v=id} -> LocalAssum (id,t)) idl) env in
+ let ienv = List.fold_right (fun {CAst.v=id} ienv ->
let impls = compute_internalization_data env Variable t imps in
Id.Map.add id impls ienv) idl ienv in
((sigma,env,ienv),((is_coe,idl),t,imps)))
@@ -175,7 +175,7 @@ let do_assumptions kind nl l =
let t = replace_vars subst t in
let refs, status' = declare_assumptions idl is_coe kind (t,uctx) ubinders imps nl in
let subst' = List.map2
- (fun (_,id) (c,u) -> (id, Universes.constr_of_global_univ (c,u)))
+ (fun {CAst.v=id} (c,u) -> (id, Universes.constr_of_global_univ (c,u)))
idl refs
in
subst'@subst, status' && status, next_uctx uctx)
diff --git a/vernac/comAssumption.mli b/vernac/comAssumption.mli
index 2fa156abd..0491638c9 100644
--- a/vernac/comAssumption.mli
+++ b/vernac/comAssumption.mli
@@ -30,5 +30,5 @@ val do_assumptions : locality * polymorphic * assumption_object_kind ->
val declare_assumption : coercion_flag -> assumption_kind ->
types in_constant_universes_entry ->
Universes.universe_binders -> Impargs.manual_implicits ->
- bool (** implicit *) -> Vernacexpr.inline -> variable Loc.located ->
+ bool (** implicit *) -> Vernacexpr.inline -> variable CAst.t ->
global_reference * Univ.Instance.t * bool
diff --git a/vernac/comFixpoint.ml b/vernac/comFixpoint.ml
index d648e293a..489f299a2 100644
--- a/vernac/comFixpoint.ml
+++ b/vernac/comFixpoint.ml
@@ -102,7 +102,7 @@ let check_mutuality env evd isfix fixl =
type structured_fixpoint_expr = {
fix_name : Id.t;
fix_univs : universe_decl_expr option;
- fix_annot : Id.t Loc.located option;
+ fix_annot : lident option;
fix_binders : local_binder_expr list;
fix_body : constr_expr option;
fix_type : constr_expr
@@ -175,7 +175,7 @@ let interp_recursive ~program_mode ~cofix fixl notations =
| x , None -> x
| Some ls , Some us ->
let lsu = ls.univdecl_instance and usu = us.univdecl_instance in
- if not (CList.for_all2eq (fun x y -> Id.equal (snd x) (snd y)) lsu usu) then
+ if not (CList.for_all2eq (fun x y -> Id.equal x.CAst.v y.CAst.v) lsu usu) then
user_err Pp.(str "(co)-recursive definitions should all have the same universe binders");
Some us) fixl None in
let sigma, decl = Univdecls.interp_univ_decl_opt env all_universes in
@@ -323,7 +323,7 @@ let extract_decreasing_argument limit = function
let extract_fixpoint_components limit l =
let fixl, ntnl = List.split l in
- let fixl = List.map (fun (((_,id),pl),ann,bl,typ,def) ->
+ let fixl = List.map (fun (({CAst.v=id},pl),ann,bl,typ,def) ->
let ann = extract_decreasing_argument limit ann in
{fix_name = id; fix_annot = ann; fix_univs = pl;
fix_binders = bl; fix_body = def; fix_type = typ}) fixl in
@@ -331,7 +331,7 @@ let extract_fixpoint_components limit l =
let extract_cofixpoint_components l =
let fixl, ntnl = List.split l in
- List.map (fun (((_,id),pl),bl,typ,def) ->
+ List.map (fun (({CAst.v=id},pl),bl,typ,def) ->
{fix_name = id; fix_annot = None; fix_univs = pl;
fix_binders = bl; fix_body = def; fix_type = typ}) fixl,
List.flatten ntnl
diff --git a/vernac/comFixpoint.mli b/vernac/comFixpoint.mli
index 2c84bd84d..2926e30e5 100644
--- a/vernac/comFixpoint.mli
+++ b/vernac/comFixpoint.mli
@@ -31,7 +31,7 @@ val do_cofixpoint :
type structured_fixpoint_expr = {
fix_name : Id.t;
fix_univs : Vernacexpr.universe_decl_expr option;
- fix_annot : Id.t Loc.located option;
+ fix_annot : Misctypes.lident option;
fix_binders : local_binder_expr list;
fix_body : constr_expr option;
fix_type : constr_expr
diff --git a/vernac/comInductive.ml b/vernac/comInductive.ml
index 41474fc63..c650e9e40 100644
--- a/vernac/comInductive.ml
+++ b/vernac/comInductive.ml
@@ -249,7 +249,7 @@ let inductive_levels env evd poly arities inds =
(evd,[]) (Array.to_list levels') destarities sizes
in evd, List.rev arities
-let check_named (loc, na) = match na with
+let check_named {CAst.loc;v=na} = match na with
| Name _ -> ()
| Anonymous ->
let msg = str "Parameters must be named." in
@@ -260,7 +260,7 @@ let check_param = function
| CLocalDef (na, _, _) -> check_named na
| CLocalAssum (nas, Default _, _) -> List.iter check_named nas
| CLocalAssum (nas, Generalized _, _) -> ()
-| CLocalPattern (loc,_) ->
+| CLocalPattern {CAst.loc} ->
Loc.raise ?loc (Stream.Error "pattern with quote not allowed here.")
let interp_mutual_inductive (paramsl,indl) notations cum poly prv finite =
@@ -364,7 +364,7 @@ let eq_local_binders bl1 bl2 =
List.equal local_binder_eq bl1 bl2
let extract_coercions indl =
- let mkqid (_,((_,id),_)) = qualid_of_ident id in
+ let mkqid (_,({CAst.v=id},_)) = qualid_of_ident id in
let extract lc = List.filter (fun (iscoe,_) -> iscoe) lc in
List.map mkqid (List.flatten(List.map (fun (_,_,_,lc) -> extract lc) indl))
@@ -378,10 +378,10 @@ let extract_params indl =
params
let extract_inductive indl =
- List.map (fun (((_,indname),pl),_,ar,lc) -> {
+ List.map (fun (({CAst.v=indname},pl),_,ar,lc) -> {
ind_name = indname; ind_univs = pl;
ind_arity = Option.cata (fun x -> x) (CAst.make @@ CSort (GType [])) ar;
- ind_lc = List.map (fun (_,((_,id),t)) -> (id,t)) lc
+ ind_lc = List.map (fun (_,({CAst.v=id},t)) -> (id,t)) lc
}) indl
let extract_mutual_inductive_declaration_components indl =
diff --git a/vernac/comProgramFixpoint.ml b/vernac/comProgramFixpoint.ml
index a9a91e304..af34f8b29 100644
--- a/vernac/comProgramFixpoint.ml
+++ b/vernac/comProgramFixpoint.ml
@@ -298,16 +298,16 @@ let do_program_recursive local poly fixkind fixl ntns =
let do_program_fixpoint local poly l =
let g = List.map (fun ((_,wf,_,_,_),_) -> wf) l in
match g, l with
- | [(n, CWfRec r)], [((((_,id),pl),_,bl,typ,def),ntn)] ->
+ | [(n, CWfRec r)], [((({CAst.v=id},pl),_,bl,typ,def),ntn)] ->
let recarg =
match n with
- | Some n -> mkIdentC (snd n)
+ | Some n -> mkIdentC n.CAst.v
| None ->
user_err ~hdr:"do_program_fixpoint"
(str "Recursive argument required for well-founded fixpoints")
in build_wellfounded (id, pl, n, bl, typ, out_def def) poly r recarg ntn
- | [(n, CMeasureRec (m, r))], [((((_,id),pl),_,bl,typ,def),ntn)] ->
+ | [(n, CMeasureRec (m, r))], [((({CAst.v=id},pl),_,bl,typ,def),ntn)] ->
build_wellfounded (id, pl, n, bl, typ, out_def def) poly
(Option.default (CAst.make @@ CRef (lt_ref,None)) r) m ntn
@@ -322,7 +322,7 @@ let do_program_fixpoint local poly l =
let extract_cofixpoint_components l =
let fixl, ntnl = List.split l in
- List.map (fun (((_,id),pl),bl,typ,def) ->
+ List.map (fun (({CAst.v=id},pl),bl,typ,def) ->
{fix_name = id; fix_annot = None; fix_univs = pl;
fix_binders = bl; fix_body = def; fix_type = typ}) fixl,
List.flatten ntnl
diff --git a/vernac/indschemes.ml b/vernac/indschemes.ml
index 2f4c95aff..447c5085b 100644
--- a/vernac/indschemes.ml
+++ b/vernac/indschemes.ml
@@ -367,17 +367,16 @@ requested
| InType -> recs ^ "t_nodep")
) in
let newid = add_suffix (basename_of_global (IndRef ind)) suffix in
- let newref = Loc.tag newid in
+ let newref = CAst.make newid in
((newref,isdep,ind,z)::l1),l2
in
match t with
| CaseScheme (x,y,z) -> names "_case" "_case" x y z
| InductionScheme (x,y,z) -> names "_ind" "_rec" x y z
| EqualityScheme x -> l1,((None,smart_global_inductive x)::l2)
-
let do_mutual_induction_scheme lnamedepindsort =
- let lrecnames = List.map (fun ((_,f),_,_,_) -> f) lnamedepindsort
+ let lrecnames = List.map (fun ({CAst.v},_,_,_) -> v) lnamedepindsort
and env0 = Global.env() in
let sigma, lrecspec, _ =
List.fold_right
@@ -416,7 +415,7 @@ let get_common_underlying_mutual_inductive = function
then user_err Pp.(str "A type occurs twice");
mind,
List.map_filter
- (function (Some id,(_,i)) -> Some (i,snd id) | (None,_) -> None) all
+ (function (Some id,(_,i)) -> Some (i,id.CAst.v) | (None,_) -> None) all
let do_scheme l =
let ischeme,escheme = split_scheme l in
@@ -450,7 +449,7 @@ let fold_left' f = function
let mk_coq_and sigma = Evarutil.new_global sigma (Coqlib.build_coq_and ())
let mk_coq_conj sigma = Evarutil.new_global sigma (Coqlib.build_coq_conj ())
-
+
let build_combined_scheme env schemes =
let evdref = ref (Evd.from_env env) in
let defs = List.map (fun cst ->
@@ -492,18 +491,19 @@ let build_combined_scheme env schemes =
(!evdref, body, typ)
let do_combined_scheme name schemes =
+ let open CAst in
let csts =
- List.map (fun x ->
- let refe = Ident x in
- let qualid = qualid_of_reference refe in
- try Nametab.locate_constant (snd qualid)
- with Not_found -> user_err Pp.(pr_qualid (snd qualid) ++ str " is not declared."))
+ List.map (fun {CAst.loc;v} ->
+ let refe = Ident (Loc.tag ?loc v) in
+ let qualid = qualid_of_reference refe in
+ try Nametab.locate_constant (snd qualid)
+ with Not_found -> user_err Pp.(pr_qualid (snd qualid) ++ str " is not declared."))
schemes
in
let sigma,body,typ = build_combined_scheme (Global.env ()) csts in
let proof_output = Future.from_val ((body,Univ.ContextSet.empty),Safe_typing.empty_private_constants) in
- ignore (define (snd name) UserIndividualRequest sigma proof_output (Some typ));
- fixpoint_message None [snd name]
+ ignore (define name.v UserIndividualRequest sigma proof_output (Some typ));
+ fixpoint_message None [name.v]
(**********************************************************************)
diff --git a/vernac/indschemes.mli b/vernac/indschemes.mli
index 4b31389ab..8658d85f6 100644
--- a/vernac/indschemes.mli
+++ b/vernac/indschemes.mli
@@ -6,7 +6,6 @@
(* * GNU Lesser General Public License Version 2.1 *)
(************************************************************************)
-open Loc
open Names
open Constr
open Environ
@@ -31,17 +30,17 @@ val declare_rewriting_schemes : inductive -> unit
(** Mutual Minimality/Induction scheme *)
val do_mutual_induction_scheme :
- (Id.t located * bool * inductive * Sorts.family) list -> unit
+ (Misctypes.lident * bool * inductive * Sorts.family) list -> unit
(** Main calls to interpret the Scheme command *)
-val do_scheme : (Id.t located option * scheme) list -> unit
+val do_scheme : (Misctypes.lident option * scheme) list -> unit
(** Combine a list of schemes into a conjunction of them *)
val build_combined_scheme : env -> Constant.t list -> Evd.evar_map * constr * types
-val do_combined_scheme : Id.t located -> Id.t located list -> unit
+val do_combined_scheme : Misctypes.lident -> Misctypes.lident list -> unit
(** Hook called at each inductive type definition *)
diff --git a/vernac/lemmas.ml b/vernac/lemmas.ml
index 57436784b..7661fff6d 100644
--- a/vernac/lemmas.ml
+++ b/vernac/lemmas.ml
@@ -214,7 +214,7 @@ let fresh_name_for_anonymous_theorem () =
let avoid = Id.Set.of_list (Proof_global.get_all_proof_names ()) in
next_global_ident_away default_thm_id avoid
-let check_name_freshness locality (loc,id) : unit =
+let check_name_freshness locality {CAst.loc;v=id} : unit =
(* We check existence here: it's a bit late at Qed time *)
if Nametab.exists_cci (Lib.make_path id) || is_section_variable id ||
locality == Global && Nametab.exists_cci (Lib.make_path_except_section id)
@@ -339,7 +339,7 @@ let universe_proof_terminator compute_guard hook =
(hook (Some (proof.Proof_global.universes))) is_opaque in
begin match idopt with
| None -> save_named ~export_seff proof
- | Some (_,id) -> save_anonymous ~export_seff proof id
+ | Some { CAst.v = id } -> save_anonymous ~export_seff proof id
end
end
@@ -444,7 +444,7 @@ let start_proof_com ?inference_hook kind thms hook =
let ids = List.map RelDecl.get_name ctx in
check_name_freshness (pi1 kind) id;
(* XXX: The nf_evar is critical !! *)
- evd, (snd id,
+ evd, (id.CAst.v,
(Evarutil.nf_evar evd (EConstr.it_mkProd_or_LetIn t' ctx),
(ids, imps @ lift_implicits (Context.Rel.nhyps ctx) imps'))))
evd thms in
diff --git a/vernac/metasyntax.ml b/vernac/metasyntax.ml
index 3be357598..f63206216 100644
--- a/vernac/metasyntax.ml
+++ b/vernac/metasyntax.ml
@@ -43,13 +43,6 @@ let add_token_obj s = Lib.add_anonymous_leaf (inToken s)
let entry_buf = Buffer.create 64
-type any_entry = AnyEntry : 'a Pcoq.Gram.entry -> any_entry
-
-let grammars : any_entry list String.Map.t ref = ref String.Map.empty
-
-let register_grammar name grams =
- grammars := String.Map.add name grams !grammars
-
let pr_entry e =
let () = Buffer.clear entry_buf in
let ft = Format.formatter_of_buffer entry_buf in
@@ -57,11 +50,11 @@ let pr_entry e =
str (Buffer.contents entry_buf)
let pr_registered_grammar name =
- let gram = try Some (String.Map.find name !grammars) with Not_found -> None in
+ let gram = try Some (Pcoq.find_grammars_by_name name) with Not_found -> None in
match gram with
| None -> user_err Pp.(str "Unknown or unprintable grammar entry.")
| Some entries ->
- let pr_one (AnyEntry e) =
+ let pr_one (Pcoq.AnyEntry e) =
str "Entry " ++ str (Pcoq.Gram.Entry.name e) ++ str " is" ++ fnl () ++
pr_entry e
in
@@ -96,7 +89,7 @@ let pr_grammar = function
(* Parse a format (every terminal starting with a letter or a single
quote (except a single quote alone) must be quoted) *)
-let parse_format ((loc, str) : lstring) =
+let parse_format ({CAst.loc;v=str} : Misctypes.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
@@ -199,36 +192,6 @@ let parse_format ((loc, str) : lstring) =
(***********************)
(* Analyzing notations *)
-type symbol_token = WhiteSpace of int | String of string
-
-let split_notation_string str =
- let push_token beg i l =
- if Int.equal beg i then l else
- let s = String.sub str beg (i - beg) in
- String s :: l
- in
- let push_whitespace beg i l =
- if Int.equal beg i then l else WhiteSpace (i-beg) :: l
- in
- let rec loop beg i =
- if i < String.length str then
- if str.[i] == ' ' then
- push_token beg i (loop_on_whitespace (i+1) (i+1))
- else
- loop beg (i+1)
- else
- push_token beg i []
- and loop_on_whitespace beg i =
- if i < String.length str then
- if str.[i] != ' ' then
- push_whitespace beg i (loop i (i+1))
- else
- loop_on_whitespace beg (i+1)
- else
- push_whitespace beg i []
- in
- loop 0 0
-
(* Interpret notations with a recursive component *)
let out_nt = function NonTerminal x -> x | _ -> assert false
@@ -284,17 +247,6 @@ let quote_notation_token x =
if (n > 0 && norm) || (n > 2 && x.[0] == '\'') then "'"^x^"'"
else x
-let rec raw_analyze_notation_tokens = function
- | [] -> []
- | String ".." :: sl -> NonTerminal ldots_var :: raw_analyze_notation_tokens sl
- | String "_" :: _ -> user_err Pp.(str "_ must be quoted.")
- | String x :: sl when CLexer.is_ident x ->
- NonTerminal (Names.Id.of_string x) :: raw_analyze_notation_tokens sl
- | String s :: sl ->
- Terminal (String.drop_simple_quotes s) :: raw_analyze_notation_tokens sl
- | WhiteSpace n :: sl ->
- Break n :: raw_analyze_notation_tokens sl
-
let is_numeral symbs =
match List.filter (function Break _ -> false | _ -> true) symbs with
| ([Terminal "-"; Terminal x] | [Terminal x]) ->
@@ -315,8 +267,8 @@ let rec get_notation_vars onlyprint = function
| (Terminal _ | Break _) :: sl -> get_notation_vars onlyprint sl
| SProdList _ :: _ -> assert false
-let analyze_notation_tokens ~onlyprint l =
- let l = raw_analyze_notation_tokens l in
+let analyze_notation_tokens ~onlyprint ntn =
+ let l = decompose_raw_notation ntn in
let vars = get_notation_vars onlyprint l in
let recvars,l = interp_list_parser [] l in
recvars, List.subtract Id.equal vars (List.map snd recvars), l
@@ -333,13 +285,17 @@ let prec_assoc = function
| LeftA -> (E,L)
| NonA -> (L,L)
-let precedence_of_entry_type from = function
- | ETConstr (NumLevel n,BorderProd (_,None)) -> n, Prec n
- | ETConstr (NumLevel n,BorderProd (b,Some a)) ->
+let precedence_of_position_and_level from = function
+ | NumLevel n, BorderProd (_,None) -> n, Prec n
+ | NumLevel n, BorderProd (b,Some a) ->
n, let (lp,rp) = prec_assoc a in if b == Left then lp else rp
- | ETConstr (NumLevel n,InternalProd) -> n, Prec n
- | ETConstr (NextLevel,_) -> from, L
- | _ -> 0, E (* ?? *)
+ | NumLevel n, InternalProd -> n, Prec n
+ | NextLevel, _ -> from, L
+
+let precedence_of_entry_type from = function
+ | ETConstr x | ETConstrAsBinder (_,x) -> precedence_of_position_and_level from x
+ | ETPattern (_,n) -> let n = match n with None -> 0 | Some n -> n in n, Prec n
+ | _ -> 0, E (* should not matter *)
(* Some breaking examples *)
(* "x = y" : "x /1 = y" (breaks before any symbol) *)
@@ -377,8 +333,8 @@ let is_non_terminal = function
| NonTerminal _ | SProdList _ -> true
| _ -> false
-let is_next_non_terminal = function
-| [] -> false
+let is_next_non_terminal b = function
+| [] -> b
| pr :: _ -> is_non_terminal pr
let is_next_terminal = function Terminal _ :: _ -> true | _ -> false
@@ -387,8 +343,9 @@ 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 = function
- | (((_,UnpCut (PpBrk _)) :: _) | []) as l -> 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 =
@@ -403,45 +360,59 @@ let check_open_binder isopen sl m =
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 prec = snd (precedence_of_entry_type from x) in
+ match x with
+ | ETConstr _ | ETConstrAsBinder _ | ETReference | ETBigint ->
+ UnpMetaVar (i,prec)
+ | ETPattern _ ->
+ UnpBinderMetaVar (i,prec)
+ | ETName ->
+ UnpBinderMetaVar (i,Prec 0)
+ | ETBinder isopen ->
+ assert false
+ | ETOther _ -> failwith "TODO"
+
(* Heuristics for building default printing rules *)
let index_id id l = List.index Id.equal id l
let make_hunks etyps symbols from =
let vars,typs = List.split etyps in
- let rec make = function
+ let rec make b = function
| NonTerminal m :: prods ->
let i = index_id m vars in
- let _,prec = precedence_of_entry_type from (List.nth typs (i-1)) in
- let u = UnpMetaVar (i,prec) in
- if is_next_non_terminal prods then
- (None,u) :: add_break_if_none 1 (make prods)
+ let u = unparsing_metavar i from 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 prods
- | Terminal s :: prods when List.exists is_non_terminal prods ->
+ (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 (make prods)
+ (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 (make prods)
- else if is_left_bracket s && is_next_non_terminal prods then
- (None,UnpTerminal s) :: make prods
+ (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 prods
+ (None, UnpTerminal (s^" ")) :: make b prods
else
(* Rely on user spaces *)
- (None,UnpTerminal s) :: make prods
+ (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 prods
- | _ -> (None,UnpTerminal s) :: make prods)
+ | Terminal _ :: _ -> (None,UnpTerminal (s^" ")) :: make b prods
+ | _ -> (None,UnpTerminal s) :: make b prods)
| Break n :: prods ->
- add_break n (make prods)
+ add_break n (make b prods)
| SProdList (m,sl) :: prods ->
let i = index_id m vars in
@@ -451,47 +422,52 @@ let make_hunks etyps symbols from =
(* 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 snd (List.sep_last (make (sl@[NonTerminal m]))) in
+ else make true sl in
let hunk = match typ with
| ETConstr _ -> UnpListMetaVar (i,prec,List.map snd sl')
| ETBinder isopen ->
check_open_binder isopen sl m;
UnpBinderListMetaVar (i,isopen,List.map snd sl')
| _ -> assert false in
- (None,hunk) :: make_with_space prods
+ (None, hunk) :: make_with_space b prods
| [] -> []
- and make_with_space 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 (make prods')
+ (None,UnpTerminal (" "^s')) :: add_break_if_none 1 b (make b prods')
else if is_comma s' then
(* No space whatsoever before comma *)
- make prods
+ make b prods
else if is_right_bracket s' then
- make prods
+ make b prods
else
(* A breakable space between any other two terminals *)
- add_break_if_none 1 (make prods)
+ add_break_if_none 1 b (make b prods)
| (NonTerminal _ | SProdList _) :: _ ->
(* A breakable space before a non-terminal *)
- add_break_if_none 1 (make prods)
+ add_break_if_none 1 b (make b prods)
| Break _ :: _ ->
(* Rely on user wish *)
- make prods
+ make b prods
| [] -> []
- in make symbols
+ 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:"parsing"
+ (fun () ->
+ strbrk "Discarding format implicitly indicated by multiple spaces in notation because an explicit format modifier is given.")
+
let rec split_format_at_ldots hd = function
- | (loc,UnpTerminal s) :: fmt when String.equal s (Id.to_string ldots_var) -> loc, List.rev hd, fmt
+ | (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
@@ -538,8 +514,7 @@ let hunks_of_format (from,(vars,typs)) symfmt =
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 _,prec = precedence_of_entry_type from (List.nth typs (i-1)) in
- let symbs, l = aux (symbs,fmt) in symbs, UnpMetaVar (i,prec) :: l
+ let symbs, l = aux (symbs,fmt) in symbs, unparsing_metavar i from typs :: l
| symbs, (_,UnpBox (a,b)) :: fmt ->
let symbs', b' = aux (symbs,b) in
let symbs', l = aux (symbs',fmt) in
@@ -562,6 +537,7 @@ let hunks_of_format (from,(vars,typs)) symfmt =
| _ -> assert false in
symbs, hunk :: 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
@@ -574,8 +550,8 @@ let hunks_of_format (from,(vars,typs)) symfmt =
let assoc_of_type n (_,typ) = precedence_of_entry_type n typ
let is_not_small_constr = function
- ETConstr _ -> true
- | ETOther("constr","binder_constr") -> true
+ ETProdConstr _ -> true
+ | ETProdOther("constr","binder_constr") -> true
| _ -> false
let rec define_keywords_aux = function
@@ -607,14 +583,14 @@ let distribute a ll = List.map (fun l -> a @ l) ll
let expand_list_rule typ tkl x n p ll =
let camlp5_message_name = Some (add_suffix x ("_"^string_of_int n)) in
- let main = GramConstrNonTerminal (ETConstr typ, camlp5_message_name) in
+ let main = GramConstrNonTerminal (ETProdConstr typ, camlp5_message_name) in
let tks = List.map (fun x -> GramConstrTerminal x) tkl in
let rec aux i hds ll =
if i < p then aux (i+1) (main :: tks @ hds) ll
else if Int.equal i (p+n) then
let hds =
GramConstrListMark (p+n,true,p) :: hds
- @ [GramConstrNonTerminal (ETConstrList (typ,tkl), Some x)] in
+ @ [GramConstrNonTerminal (ETProdConstrList (typ,tkl), Some x)] in
distribute hds ll
else
distribute (GramConstrListMark (i+1,false,p) :: hds @ [main]) ll @
@@ -623,7 +599,7 @@ let expand_list_rule typ tkl x n p ll =
let is_constr_typ typ x etyps =
match List.assoc x etyps with
- | ETConstr typ' -> typ = typ'
+ | ETConstr typ' | ETConstrAsBinder (_,typ') -> typ = typ'
| _ -> false
let include_possible_similar_trailing_pattern typ etyps sl l =
@@ -636,12 +612,21 @@ let include_possible_similar_trailing_pattern typ etyps sl l =
with Exit -> n,l in
try_aux 0 l
+let prod_entry_type = function
+ | ETName -> ETProdName
+ | ETReference -> ETProdReference
+ | ETBigint -> ETProdBigint
+ | ETBinder _ -> assert false (* See check_binder_type *)
+ | ETConstr p | ETConstrAsBinder (_,p) -> ETProdConstr p
+ | ETPattern (_,n) -> ETProdPattern (match n with None -> 0 | Some n -> n)
+ | ETOther (s,t) -> ETProdOther (s,t)
+
let make_production etyps symbols =
let rec aux = function
| [] -> [[]]
| NonTerminal m :: l ->
let typ = List.assoc m etyps in
- distribute [GramConstrNonTerminal (typ, Some m)] (aux l)
+ distribute [GramConstrNonTerminal (prod_entry_type typ, Some m)] (aux l)
| Terminal s :: l ->
distribute [GramConstrTerminal (CLexer.terminal s)] (aux l)
| Break _ :: l ->
@@ -656,8 +641,10 @@ let make_production etyps symbols =
let p,l' = include_possible_similar_trailing_pattern typ etyps sl l in
expand_list_rule typ tkl x 1 p (aux l')
| ETBinder o ->
- distribute
- [GramConstrNonTerminal (ETBinderList (o,tkl), Some x)] (aux l)
+ check_open_binder o sl x;
+ let typ = if o then (assert (tkl = []); ETBinderOpen) else ETBinderClosed tkl in
+ distribute
+ [GramConstrNonTerminal (ETProdBinderList typ, Some x)] (aux l)
| _ ->
user_err Pp.(str "Components of recursive patterns in notation must be terms or binders.") in
let prods = aux symbols in
@@ -675,6 +662,7 @@ let rec find_symbols c_current c_next c_last = function
let border = function
| (_,ETConstr(_,BorderProd (_,a))) :: _ -> a
+ | (_,(ETConstrAsBinder(_,(_,BorderProd (_,a))))) :: _ -> a
| _ -> None
let recompute_assoc typs =
@@ -688,17 +676,16 @@ let recompute_assoc typs =
(* Registration of syntax extensions (parsing/printing, no interpretation)*)
let pr_arg_level from (lev,typ) =
- let pplev = match lev with
+ let pplev = function
| (n,L) when Int.equal n from -> str "at next level"
| (n,E) -> str "at level " ++ int n
| (n,L) -> str "at level below " ++ int n
| (n,Prec m) when Int.equal m n -> str "at level " ++ int n
| (n,_) -> str "Unknown level" in
- let pptyp = match typ with
- | NtnInternTypeConstr -> mt ()
- | NtnInternTypeBinder -> str " " ++ surround (str "binder")
- | NtnInternTypeIdent -> str " " ++ surround (str "ident") in
- pplev ++ pptyp
+ Ppvernac.pr_set_entry_type (fun _ -> (*TO CHECK*) mt()) typ ++
+ (match typ with
+ | ETConstr _ | ETConstrAsBinder _ | ETPattern _ -> spc () ++ pplev lev
+ | _ -> mt ())
let pr_level ntn (from,args,typs) =
str "at level " ++ int from ++ spc () ++ str "with arguments" ++ spc() ++
@@ -802,7 +789,7 @@ type notation_modifier = {
only_parsing : bool;
only_printing : bool;
compat : Flags.compat_version option;
- format : string Loc.located option;
+ format : Misctypes.lstring option;
extra : (string * string) list;
}
@@ -830,15 +817,23 @@ let interp_modifiers modl = let open NotationMods in
interp { acc with etyps = (id,typ) :: acc.etyps; } l
| SetItemLevel ([],n) :: l ->
interp acc l
+ | SetItemLevelAsBinder ([],_,_) :: l ->
+ interp acc l
| SetItemLevel (s::idl,n) :: l ->
let id = Id.of_string s in
if Id.List.mem_assoc id acc.etyps then
user_err ~hdr:"Metasyntax.interp_modifiers"
(str s ++ str " is already assigned to an entry or constr level.");
- let typ = ETConstr (n,()) in
+ let typ = ETConstr (Some n) in
interp { acc with etyps = (id,typ)::acc.etyps; } (SetItemLevel (idl,n)::l)
+ | SetItemLevelAsBinder (s::idl,bk,n) :: l ->
+ let id = Id.of_string s in
+ if Id.List.mem_assoc id acc.etyps then
+ user_err ~hdr:"Metasyntax.interp_modifiers"
+ (str s ++ str " is already assigned to an entry or constr level.");
+ let typ = ETConstrAsBinder (bk,n) in
+ interp { acc with etyps = (id,typ)::acc.etyps; } (SetItemLevelAsBinder (idl,bk,n)::l)
| SetLevel n :: l ->
-
interp { acc with level = Some n; } l
| SetAssoc a :: l ->
if not (Option.is_empty acc.assoc) then user_err Pp.(str "An associativity is given more than once.");
@@ -852,7 +847,7 @@ let interp_modifiers modl = let open NotationMods in
| SetFormat ("text",s) :: l ->
if not (Option.is_empty acc.format) then user_err Pp.(str "A format is given more than once.");
interp { acc with format = Some s; } l
- | SetFormat (k,(_,s)) :: l ->
+ | SetFormat (k,{CAst.v=s}) :: l ->
interp { acc with extra = (k,s)::acc.extra; } l
in interp default modl
@@ -902,12 +897,17 @@ let get_compat_version mods =
let set_entry_type etyps (x,typ) =
let typ = try
match List.assoc x etyps, typ with
- | ETConstr (n,()), (_,BorderProd (left,_)) ->
+ | ETConstr (Some n), (_,BorderProd (left,_)) ->
ETConstr (n,BorderProd (left,None))
- | ETConstr (n,()), (_,InternalProd) -> ETConstr (n,InternalProd)
- | (ETPattern | ETName | ETBigint | ETOther _ |
- ETReference | ETBinder _ as t), _ -> t
- | (ETBinderList _ |ETConstrList _), _ -> assert false
+ | ETConstr (Some n), (_,InternalProd) -> ETConstr (n,InternalProd)
+ | ETConstrAsBinder (bk, Some n), (_,BorderProd (left,_)) ->
+ ETConstrAsBinder (bk, (n,BorderProd (left,None)))
+ | ETConstrAsBinder (bk, Some n), (_,InternalProd) ->
+ ETConstrAsBinder (bk, (n,InternalProd))
+ | ETPattern (b,n), _ -> ETPattern (b,n)
+ | (ETName | ETBigint | ETReference | ETBinder _ | ETOther _ as x), _ -> x
+ | ETConstr None, _ -> ETConstr typ
+ | ETConstrAsBinder (bk,None), _ -> ETConstrAsBinder (bk,typ)
with Not_found -> ETConstr typ
in (x,typ)
@@ -927,12 +927,9 @@ let join_auxiliary_recursive_types recvars etyps =
recvars etyps
let internalization_type_of_entry_type = function
- | ETConstr _ -> NtnInternTypeConstr
- | ETBigint | ETReference -> NtnInternTypeConstr
- | ETBinder _ -> NtnInternTypeBinder
- | ETName -> NtnInternTypeIdent
- | ETPattern | ETOther _ -> user_err Pp.(str "Not supported.")
- | ETBinderList _ | ETConstrList _ -> assert false
+ | ETBinder _ -> NtnInternTypeOnlyBinder
+ | ETConstr _ | ETConstrAsBinder _ | ETBigint | ETReference
+ | ETName | ETPattern _ | ETOther _ -> NtnInternTypeAny
let set_internalization_type typs =
List.map (fun (_, e) -> internalization_type_of_entry_type e) typs
@@ -943,28 +940,36 @@ let make_internalization_vars recvars mainvars typs =
maintyps @ extratyps
let make_interpretation_type isrec isonlybinding = function
- | NtnInternTypeConstr when isrec -> NtnTypeConstrList
- | NtnInternTypeConstr | NtnInternTypeIdent ->
- if isonlybinding then NtnTypeOnlyBinder else NtnTypeConstr
- | NtnInternTypeBinder when isrec -> NtnTypeBinderList
- | NtnInternTypeBinder -> user_err Pp.(str "Type binder is only for use in recursive notations for binders.")
-
-let make_interpretation_vars recvars allvars =
+ | ETConstr _ ->
+ if isrec then NtnTypeConstrList else
+ if isonlybinding then
+ (* Parsed as constr, but interpreted as a binder: default is to parse it as an ident only *)
+ NtnTypeBinder (NtnBinderParsedAsConstr AsIdent)
+ else NtnTypeConstr
+ | ETConstrAsBinder (bk,_) -> NtnTypeBinder (NtnBinderParsedAsConstr bk)
+ | ETName -> NtnTypeBinder NtnParsedAsIdent
+ | ETPattern (ppstrict,_) -> NtnTypeBinder (NtnParsedAsPattern ppstrict) (* Parsed as ident/pattern, primarily interpreted as binder; maybe strict at printing *)
+ | ETBigint | ETReference | ETOther _ -> NtnTypeConstr
+ | ETBinder _ ->
+ if isrec then NtnTypeBinderList
+ else anomaly Pp.(str "Type binder is only for use in recursive notations for binders.")
+
+let make_interpretation_vars recvars allvars typs =
let eq_subscope (sc1, l1) (sc2, l2) =
Option.equal String.equal sc1 sc2 &&
List.equal String.equal l1 l2
in
let check (x, y) =
- let (_,scope1, _) = Id.Map.find x allvars in
- let (_,scope2, _) = Id.Map.find y allvars in
+ let (_,scope1) = Id.Map.find x allvars in
+ let (_,scope2) = Id.Map.find y allvars in
if not (eq_subscope scope1 scope2) then error_not_same_scope x y
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, typ) ->
- (sc, make_interpretation_type (Id.List.mem_assoc x recvars) isonlybinding typ)) mainvars
+ Id.Map.mapi (fun x (isonlybinding, sc) ->
+ (sc, make_interpretation_type (Id.List.mem_assoc x recvars) isonlybinding (Id.List.assoc x typs))) mainvars
let check_rule_productivity l =
if List.for_all (function NonTerminal _ | Break _ -> true | _ -> false) l then
@@ -979,18 +984,27 @@ let warn_notation_bound_to_variable =
let warn_non_reversible_notation =
CWarnings.create ~name:"non-reversible-notation" ~category:"parsing"
- (fun () ->
- strbrk "This notation will not be used for printing as it is not reversible.")
-
-let is_not_printable onlyparse nonreversible = function
+ (function
+ | APrioriReversible -> assert false
+ | HasLtac ->
+ strbrk "This notation contains Ltac expressions: 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_not_printable onlyparse reversibility = function
| NVar _ ->
if not onlyparse then warn_notation_bound_to_variable ();
true
| _ ->
- if not onlyparse && nonreversible then
- (warn_non_reversible_notation (); true)
+ if not onlyparse && reversibility <> APrioriReversible then
+ (warn_non_reversible_notation reversibility; true)
else onlyparse
+
let find_precedence lev etyps symbols onlyprint =
let first_symbol =
let rec aux = function
@@ -1008,29 +1022,30 @@ let find_precedence lev etyps symbols onlyprint =
match first_symbol with
| None -> [],0
| Some (NonTerminal x) ->
+ 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 [],Option.get lev
+ else
+ user_err Pp.(str "The level of the leftmost non-terminal cannot be changed.") in
(try match List.assoc x etyps with
- | ETConstr _ ->
- 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 [],Option.get lev
- else
- user_err Pp.(str "The level of the leftmost non-terminal cannot be changed.")
- | ETName | ETBigint | ETReference ->
+ | ETConstr _ -> test ()
+ | ETConstrAsBinder (_,Some _) -> test ()
+ | (ETName | ETBigint | ETReference) ->
begin match lev with
| None ->
([Feedback.msg_info ?loc:None ,strbrk "Setting notation at level 0."],0)
| Some 0 ->
([],0)
| _ ->
- user_err Pp.(str "A notation starting with an atomic expression must be at level 0.")
+ user_err Pp.(str "A notation starting with an atomic expression must be at level 0.")
end
- | ETPattern | ETBinder _ | ETOther _ -> (* Give a default ? *)
- if Option.is_empty lev then
- user_err Pp.(str "Need an explicit level.")
- else [],Option.get lev
- | ETConstrList _ | ETBinderList _ ->
- assert false (* internally used in grammar only *)
+ | (ETPattern _ | ETBinder _ | ETOther _ | ETConstrAsBinder _) ->
+ (* Give a default ? *)
+ if Option.is_empty lev then
+ user_err Pp.(str "Need an explicit level.")
+ else [],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.")
@@ -1074,7 +1089,7 @@ let remove_curly_brackets l =
module SynData = struct
- type subentry_types = (Id.t * (production_level, production_position) constr_entry_key_gen) list
+ type subentry_types = (Id.t * (production_level * production_position) constr_entry_key_gen) list
(* XXX: Document *)
type syn_data = {
@@ -1086,7 +1101,7 @@ module SynData = struct
only_parsing : bool;
only_printing : bool;
compat : Flags.compat_version option;
- format : string Loc.located option;
+ format : Misctypes.lstring option;
extra : (string * string) list;
(* XXX: Callback to printing, must remove *)
@@ -1128,8 +1143,7 @@ let compute_syntax_data df modifiers =
let onlyparse = mods.only_parsing in
if onlyprint && onlyparse then user_err (str "A notation cannot be both 'only printing' and 'only parsing'.");
let assoc = Option.append mods.assoc (Some NonA) in
- let toks = split_notation_string df in
- let (recvars,mainvars,symbols) = analyze_notation_tokens ~onlyprint toks in
+ let (recvars,mainvars,symbols) = analyze_notation_tokens ~onlyprint df in
let _ = check_useless_entry_types recvars mainvars mods.etyps in
let _ = check_binder_type recvars mods.etyps in
@@ -1152,7 +1166,7 @@ let compute_syntax_data df modifiers =
let i_typs = set_internalization_type sy_typs in
let pa_sy_data = (sy_typs_for_grammar,symbols_for_grammar) in
let pp_sy_data = (sy_typs,symbols) in
- let sy_fulldata = (ntn_for_grammar,(n,prec_for_grammar,i_typs),need_squash) in
+ let sy_fulldata = (ntn_for_grammar,(n,prec_for_grammar,List.map snd sy_typs_for_grammar),need_squash) in
let df' = ((Lib.library_dp(),Lib.current_dirpath true),df) in
let i_data = ntn_for_interp, df' in
@@ -1171,7 +1185,7 @@ let compute_syntax_data df modifiers =
mainvars;
intern_typs = i_typs;
- level = (n,prec,i_typs);
+ level = (n,prec,List.map snd sy_typs);
pa_syntax_data = pa_sy_data;
pp_syntax_data = pp_sy_data;
not_data = sy_fulldata;
@@ -1329,10 +1343,10 @@ let add_notation_in_scope local df env c mods scope =
ninterp_var_type = to_map i_vars;
ninterp_rec_vars = to_map sd.recvars;
} in
- let (acvars, ac, reversible) = interp_notation_constr env nenv c in
- let interp = make_interpretation_vars sd.recvars acvars in
+ let (acvars, ac, reversibility) = interp_notation_constr env nenv c in
+ let interp = make_interpretation_vars sd.recvars acvars (fst sd.pa_syntax_data) in
let map (x, _) = try Some (x, Id.Map.find x interp) with Not_found -> None in
- let onlyparse = is_not_printable sd.only_parsing (not reversible) ac in
+ let onlyparse = is_not_printable sd.only_parsing reversibility ac in
let notation = {
notobj_local = local;
notobj_scope = scope;
@@ -1350,8 +1364,7 @@ let add_notation_in_scope local df env c mods scope =
sd.info
let add_notation_interpretation_core local df env ?(impls=empty_internalization_env) c scope onlyparse onlyprint compat =
- let dfs = split_notation_string df in
- let (recvars,mainvars,symbs) = analyze_notation_tokens ~onlyprint dfs in
+ let (recvars,mainvars,symbs) = analyze_notation_tokens ~onlyprint df in
(* Recover types of variables and pa/pp rules; redeclare them if needed *)
let i_typs, onlyprint = if not (is_numeral symbs) then begin
let sy = recover_notation_syntax (make_notation_key symbs) in
@@ -1363,15 +1376,15 @@ let add_notation_interpretation_core local df env ?(impls=empty_internalization_
(* Declare interpretation *)
let path = (Lib.library_dp(), Lib.current_dirpath true) in
let df' = (make_notation_key symbs, (path,df)) in
- let i_vars = make_internalization_vars recvars mainvars i_typs in
+ let i_vars = make_internalization_vars recvars mainvars (List.map internalization_type_of_entry_type i_typs) in
let nenv = {
ninterp_var_type = to_map i_vars;
ninterp_rec_vars = to_map recvars;
} in
- let (acvars, ac, reversible) = interp_notation_constr env ~impls nenv c in
- let interp = make_interpretation_vars recvars acvars in
+ let (acvars, ac, reversibility) = interp_notation_constr env ~impls nenv c in
+ let interp = make_interpretation_vars recvars acvars (List.combine mainvars i_typs) in
let map (x, _) = try Some (x, Id.Map.find x interp) with Not_found -> None in
- let onlyparse = is_not_printable onlyparse (not reversible) ac in
+ let onlyparse = is_not_printable onlyparse reversibility ac in
let notation = {
notobj_local = local;
notobj_scope = scope;
@@ -1387,7 +1400,7 @@ let add_notation_interpretation_core local df env ?(impls=empty_internalization_
(* Notations without interpretation (Reserved Notation) *)
-let add_syntax_extension local ((loc,df),mods) = let open SynData in
+let add_syntax_extension local ({CAst.loc;v=df},mods) = let open SynData in
let psd = compute_pure_syntax_data df mods in
let sy_rules = make_syntax_rules {psd with compat = None} in
Flags.if_verbose (List.iter (fun (f,x) -> f x)) psd.msgs;
@@ -1395,11 +1408,11 @@ let add_syntax_extension local ((loc,df),mods) = let open SynData in
(* Notations with only interpretation *)
-let add_notation_interpretation env ((loc,df),c,sc) =
+let add_notation_interpretation env ({CAst.loc;v=df},c,sc) =
let df' = add_notation_interpretation_core false df env c sc false false None in
Dumpglob.dump_notation (loc,df') sc true
-let set_notation_for_interpretation env impls ((_,df),c,sc) =
+let set_notation_for_interpretation env impls ({CAst.v=df},c,sc) =
(try ignore
(Flags.silently (fun () -> add_notation_interpretation_core false df env ~impls c sc false false None) ());
with NoSyntaxRule ->
@@ -1408,7 +1421,7 @@ let set_notation_for_interpretation env impls ((_,df),c,sc) =
(* Main entry point *)
-let add_notation local env c ((loc,df),modifiers) sc =
+let add_notation local env c ({CAst.loc;v=df},modifiers) sc =
let df' =
if no_syntax_modifiers modifiers then
(* No syntax data: try to rely on a previously declared rule *)
@@ -1427,8 +1440,7 @@ let add_notation local env c ((loc,df),modifiers) sc =
let add_notation_extra_printing_rule df k v =
let notk =
- let dfs = split_notation_string df in
- let _,_, symbs = analyze_notation_tokens ~onlyprint:true dfs in
+ let _,_, symbs = analyze_notation_tokens ~onlyprint:true df in
make_notation_key symbs in
Notation.add_notation_extra_printing_rule notk k v
@@ -1436,13 +1448,13 @@ let add_notation_extra_printing_rule df k v =
let inject_var x = CAst.make @@ CRef (Ident (Loc.tag @@ Id.of_string x),None)
-let add_infix local env ((loc,inf),modifiers) pr sc =
+let add_infix local env ({CAst.loc;v=inf},modifiers) pr sc =
check_infix_modifiers modifiers;
(* check the precedence *)
let metas = [inject_var "x"; inject_var "y"] in
let c = mkAppC (pr,metas) in
- let df = "x "^(quote_notation_token inf)^" y" in
- add_notation local env c ((loc,df),modifiers) sc
+ let df = CAst.make ?loc @@ "x "^(quote_notation_token inf)^" y" in
+ add_notation local env c (df,modifiers) sc
(**********************************************************************)
(* Delimiters and classes bound to scopes *)
@@ -1499,23 +1511,21 @@ let try_interp_name_alias = function
| _ -> raise Not_found
let add_syntactic_definition env ident (vars,c) local onlyparse =
- let nonprintable = ref false in
- let vars,pat =
- try [], NRef (try_interp_name_alias (vars,c))
+ let vars,reversibility,pat =
+ try [], APrioriReversible, NRef (try_interp_name_alias (vars,c))
with Not_found ->
- let fold accu id = Id.Map.add id NtnInternTypeConstr accu in
+ let fold accu id = Id.Map.add id NtnInternTypeAny 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
- let nvars, pat, reversible = interp_notation_constr env nenv c in
- let () = nonprintable := not reversible in
- let map id = let (_,sc,_) = Id.Map.find id nvars in (id, sc) in
- List.map map vars, pat
+ let nvars, pat, reversibility = interp_notation_constr env nenv c in
+ let map id = let (_,sc) = Id.Map.find id nvars in (id, sc) in
+ List.map map vars, reversibility, pat
in
let onlyparse = match onlyparse with
- | None when (is_not_printable false !nonprintable pat) -> Some Flags.Current
+ | None when (is_not_printable false reversibility pat) -> Some Flags.Current
| p -> p
in
Syntax_def.declare_syntactic_definition local ident onlyparse (vars,pat)
diff --git a/vernac/metasyntax.mli b/vernac/metasyntax.mli
index e064b570e..7740604c3 100644
--- a/vernac/metasyntax.mli
+++ b/vernac/metasyntax.mli
@@ -12,6 +12,7 @@ open Notation
open Constrexpr
open Notation_term
open Environ
+open Misctypes
val add_token_obj : string -> unit
@@ -55,10 +56,6 @@ val add_syntactic_definition : env -> Id.t -> Id.t list * constr_expr ->
val pr_grammar : string -> Pp.t
-type any_entry = AnyEntry : 'a Pcoq.Gram.entry -> any_entry
-
-val register_grammar : string -> any_entry list -> unit
-
val check_infix_modifiers : syntax_modifier list -> unit
val with_syntax_protection : ('a -> 'b) -> 'a -> 'b
diff --git a/vernac/obligations.ml b/vernac/obligations.ml
index 58e4b00fc..e4bcbc4bb 100644
--- a/vernac/obligations.ml
+++ b/vernac/obligations.ml
@@ -295,10 +295,10 @@ type obligation =
type obligations = (obligation array * int)
type fixpoint_kind =
- | IsFixpoint of (Id.t Loc.located option * Constrexpr.recursion_order_expr) list
+ | IsFixpoint of (Misctypes.lident option * Constrexpr.recursion_order_expr) list
| IsCoFixpoint
-type notations = (Vernacexpr.lstring * Constrexpr.constr_expr * Notation_term.scope_name option) list
+type notations = (Misctypes.lstring * Constrexpr.constr_expr * Notation_term.scope_name option) list
type program_info_aux = {
prg_name: Id.t;
@@ -500,7 +500,7 @@ let rec lam_index n t acc =
let compute_possible_guardness_evidences (n,_) fixbody fixtype =
match n with
- | Some (loc, n) -> [lam_index n fixbody 0]
+ | Some { CAst.loc; v = n } -> [lam_index n fixbody 0]
| None ->
(* If recursive argument was not given by user, we try all args.
An earlier approach was to look only for inductive arguments,
diff --git a/vernac/obligations.mli b/vernac/obligations.mli
index bdc97d48c..0ec127152 100644
--- a/vernac/obligations.mli
+++ b/vernac/obligations.mli
@@ -61,10 +61,10 @@ val add_definition : Names.Id.t -> ?term:constr -> types ->
?hook:(UState.t -> unit) Lemmas.declaration_hook -> ?opaque:bool -> obligation_info -> progress
type notations =
- (Vernacexpr.lstring * Constrexpr.constr_expr * Notation_term.scope_name option) list
+ (Misctypes.lstring * Constrexpr.constr_expr * Notation_term.scope_name option) list
type fixpoint_kind =
- | IsFixpoint of (Id.t Loc.located option * Constrexpr.recursion_order_expr) list
+ | IsFixpoint of (Misctypes.lident option * Constrexpr.recursion_order_expr) list
| IsCoFixpoint
val add_mutual_definitions :
diff --git a/vernac/proof_using.ml b/vernac/proof_using.ml
index ffe99cfd8..8422baf57 100644
--- a/vernac/proof_using.ml
+++ b/vernac/proof_using.ml
@@ -51,7 +51,7 @@ let rec process_expr env e ty =
let rec aux = function
| SsEmpty -> Id.Set.empty
| SsType -> set_of_type env ty
- | SsSingl (_,id) -> set_of_id env id
+ | SsSingl { CAst.v = id } -> set_of_id env 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 env) (aux e)
diff --git a/vernac/record.ml b/vernac/record.ml
index 16b95a5ef..1140e3d37 100644
--- a/vernac/record.ml
+++ b/vernac/record.ml
@@ -62,7 +62,7 @@ let _ =
let interp_fields_evars env sigma impls_env nots l =
List.fold_left2
- (fun (env, sigma, uimpls, params, impls) no ((loc, i), b, t) ->
+ (fun (env, sigma, uimpls, params, impls) no ({CAst.loc;v=i}, b, t) ->
let sigma, (t', impl) = interp_type_evars_impls env sigma ~impls t in
let sigma, b' =
Option.cata (fun x -> on_snd (fun x -> Some (fst x)) @@
@@ -92,8 +92,9 @@ let compute_constructor_level evars env l =
let binder_of_decl = function
| Vernacexpr.AssumExpr(n,t) -> (n,None,t)
- | Vernacexpr.DefExpr(n,c,t) -> (n,Some c, match t with Some c -> c
- | None -> CAst.make ?loc:(fst n) @@ CHole (None, Misctypes.IntroAnonymous, None))
+ | Vernacexpr.DefExpr(n,c,t) ->
+ (n,Some c, match t with Some c -> c
+ | None -> CAst.make ?loc:n.CAst.loc @@ CHole (None, Misctypes.IntroAnonymous, None))
let binders_of_decls = List.map binder_of_decl
@@ -101,7 +102,7 @@ let typecheck_params_and_fields finite def id poly pl t ps nots fs =
let env0 = Global.env () in
let sigma, decl = Univdecls.interp_univ_decl_opt env0 pl in
let _ =
- let error bk (loc, name) =
+ let error bk {CAst.loc; v=name} =
match bk, name with
| Default _, Anonymous ->
user_err ?loc ~hdr:"record" (str "Record parameters must be named")
@@ -110,7 +111,7 @@ let typecheck_params_and_fields finite def id poly pl t ps nots fs =
List.iter
(function CLocalDef (b, _, _) -> error default_binder_kind b
| CLocalAssum (ls, bk, ce) -> List.iter (error bk) ls
- | CLocalPattern (loc,(_,_)) ->
+ | CLocalPattern {CAst.loc} ->
Loc.raise ?loc (Stream.Error "pattern with quote not allowed in record parameters.")) ps
in
let sigma, (impls_env, ((env1,newps), imps)) = interp_context_evars env0 sigma ps in
@@ -571,13 +572,13 @@ open Vernacexpr
(* [fs] corresponds to fields and [ps] to parameters; [coers] is a
list telling if the corresponding fields must me declared as coercions
or subinstances. *)
-let definition_structure (kind,cum,poly,finite,(is_coe,((loc,idstruc),pl)),ps,cfs,idbuild,s) =
+let definition_structure (kind,cum,poly,finite,(is_coe,({CAst.loc;v=idstruc},pl)),ps,cfs,idbuild,s) =
let cfs,notations = List.split cfs in
let cfs,priorities = List.split cfs in
let coers,fs = List.split cfs in
let extract_name acc = function
- Vernacexpr.AssumExpr((_,Name id),_) -> id::acc
- | Vernacexpr.DefExpr ((_,Name id),_,_) -> id::acc
+ Vernacexpr.AssumExpr({CAst.v=Name id},_) -> id::acc
+ | Vernacexpr.DefExpr ({CAst.v=Name id},_,_) -> id::acc
| _ -> acc in
let allnames = idstruc::(List.fold_left extract_name [] fs) in
let () = match List.duplicates Id.equal allnames with
diff --git a/vernac/record.mli b/vernac/record.mli
index e632e7bbf..e0a4b8fdd 100644
--- a/vernac/record.mli
+++ b/vernac/record.mli
@@ -13,6 +13,17 @@ open Globnames
val primitive_flag : bool ref
+val declare_projections :
+ inductive ->
+ Entries.constant_universes_entry ->
+ ?kind:Decl_kinds.definition_object_kind ->
+ Id.t ->
+ bool list ->
+ Universes.universe_binders ->
+ Impargs.manual_implicits list ->
+ Context.Rel.t ->
+ (Name.t * bool) list * Constant.t option list
+
val definition_structure :
inductive_kind * Decl_kinds.cumulative_inductive_flag * Decl_kinds.polymorphic *
Declarations.recursivity_kind * ident_decl with_coercion * local_binder_expr list *
diff --git a/vernac/vernacentries.ml b/vernac/vernacentries.ml
index 35ef4bfa4..689d7a423 100644
--- a/vernac/vernacentries.ml
+++ b/vernac/vernacentries.ml
@@ -10,6 +10,7 @@
open Pp
open CErrors
+open CAst
open Util
open Names
open Nameops
@@ -443,11 +444,13 @@ let start_proof_and_print k l hook =
let hook env sigma ev =
let tac = !Obligations.default_tactic in
let evi = Evd.find sigma ev in
+ let evi = Evarutil.nf_evar_info sigma evi in
let env = Evd.evar_filtered_env evi in
try
- let concl = Evarutil.nf_evars_universes sigma evi.Evd.evar_concl in
- let concl = EConstr.of_constr concl in
- if Evarutil.has_undefined_evars sigma concl then raise Exit;
+ let concl = EConstr.of_constr evi.Evd.evar_concl in
+ if not (Evarutil.is_ground_env sigma env &&
+ Evarutil.is_ground_term sigma concl)
+ then raise Exit;
let c, _, ctx =
Pfedit.build_by_tactic env (Evd.evar_universe_context sigma)
concl (Tacticals.New.tclCOMPLETE tac)
@@ -469,13 +472,13 @@ let vernac_definition_hook p = function
| SubClass -> Class.add_subclass_hook p
| _ -> no_hook
-let vernac_definition ~atts discharge kind ((loc, id), pl) def =
+let vernac_definition ~atts discharge kind ({loc;v=id}, pl) def =
let local = enforce_locality_exp atts.locality discharge in
let hook = vernac_definition_hook atts.polymorphic kind in
let () =
match id with
| Anonymous -> ()
- | Name n -> let lid = (loc, n) in
+ | Name n -> let lid = CAst.make ?loc n in
match local with
| Discharge -> Dumpglob.dump_definition lid true "var"
| Local | Global -> Dumpglob.dump_definition lid false "def"
@@ -489,7 +492,7 @@ let vernac_definition ~atts discharge kind ((loc, id), pl) def =
(match def with
| ProveBody (bl,t) -> (* local binders, typ *)
start_proof_and_print (local, atts.polymorphic, DefinitionBody kind)
- [((loc, name), pl), (bl, t)] hook
+ [(CAst.make ?loc name, pl), (bl, t)] hook
| DefineBody (bl,red_option,c,typ_opt) ->
let red_option = match red_option with
| None -> None
@@ -544,14 +547,14 @@ let should_treat_as_cumulative cum poly =
let vernac_record cum k poly finite struc binders sort nameopt cfs =
let is_cumulative = should_treat_as_cumulative cum poly in
let const = match nameopt with
- | None -> add_prefix "Build_" (snd (fst (snd struc)))
- | Some (_,id as lid) ->
+ | None -> add_prefix "Build_" (fst (snd struc)).v
+ | Some ({v=id} as lid) ->
Dumpglob.dump_definition lid false "constr"; id in
if Dumpglob.dump () then (
Dumpglob.dump_definition (fst (snd struc)) false "rec";
List.iter (fun (((_, x), _), _) ->
match x with
- | Vernacexpr.AssumExpr ((loc, Name id), _) -> Dumpglob.dump_definition (loc,id) false "proj"
+ | Vernacexpr.AssumExpr ({loc;v=Name id}, _) -> Dumpglob.dump_definition (make ?loc id) false "proj"
| _ -> ()) cfs);
ignore(Record.definition_structure (k,is_cumulative,poly,finite,struc,binders,cfs,const,sort))
@@ -580,9 +583,9 @@ let vernac_inductive ~atts cum lo finite indl =
atts.polymorphic finite id bl c oc fs
| [ ( id , bl , c , Class _, Constructors [l]), [] ] ->
let f =
- let (coe, ((loc, id), ce)) = l in
+ let (coe, ({loc;v=id}, ce)) = l in
let coe' = if coe then Some true else None in
- (((coe', AssumExpr ((loc, Name id), ce)), None), [])
+ (((coe', AssumExpr ((make ?loc @@ Name id), ce)), None), [])
in vernac_record cum (Class true) atts.polymorphic finite id bl c None [f]
| [ ( _ , _, _, Class _, Constructors _), [] ] ->
user_err Pp.(str "Inductive classes not supported")
@@ -635,7 +638,7 @@ let vernac_scheme l =
let vernac_combined_scheme lid l =
if Dumpglob.dump () then
(Dumpglob.dump_definition lid false "def";
- List.iter (fun lid -> dump_global (Misctypes.AN (Ident lid))) l);
+ List.iter (fun {loc;v=id} -> dump_global (Misctypes.AN (Ident (Loc.tag ?loc id)))) l);
Indschemes.do_combined_scheme lid l
let vernac_universe ~atts l =
@@ -658,7 +661,7 @@ let vernac_constraint ~atts l =
let vernac_import export refl =
Library.import_module export (List.map qualid_of_reference refl)
-let vernac_declare_module export (loc, id) binders_ast mty_ast =
+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
@@ -676,7 +679,7 @@ let vernac_declare_module export (loc, id) binders_ast mty_ast =
Flags.if_verbose Feedback.msg_info (str "Module " ++ Id.print id ++ str " is declared");
Option.iter (fun export -> vernac_import export [Ident (Loc.tag id)]) export
-let vernac_define_module export (loc, id) binders_ast mty_ast_o mexpr_ast_l =
+let vernac_define_module export {loc;v=id} (binders_ast : module_binder list) 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
@@ -687,7 +690,7 @@ let vernac_define_module export (loc, id) binders_ast mty_ast_o mexpr_ast_l =
let binders_ast,argsexport =
List.fold_right
(fun (export,idl,ty) (args,argsexport) ->
- (idl,ty)::args, (List.map (fun (_,i) -> export,i)idl)@argsexport) binders_ast
+ (idl,ty)::args, (List.map (fun {v=i} -> export,i)idl)@argsexport) binders_ast
([],[]) in
let mp =
Declaremods.start_module Modintern.interp_module_ast
@@ -717,13 +720,13 @@ let vernac_define_module export (loc, id) binders_ast mty_ast_o mexpr_ast_l =
Option.iter (fun export -> vernac_import export [Ident (Loc.tag id)])
export
-let vernac_end_module export (loc,id as lid) =
+let vernac_end_module export {loc;v=id} =
let mp = Declaremods.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 -> vernac_import export [Ident lid]) export
+ Option.iter (fun export -> vernac_import export [Ident (Loc.tag ?loc id)]) export
-let vernac_declare_module_type (loc,id) binders_ast mty_sign mty_ast_l =
+let vernac_declare_module_type {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.");
@@ -733,7 +736,7 @@ let vernac_declare_module_type (loc,id) binders_ast mty_sign mty_ast_l =
let binders_ast,argsexport =
List.fold_right
(fun (export,idl,ty) (args,argsexport) ->
- (idl,ty)::args, (List.map (fun (_,i) -> export,i)idl)@argsexport) binders_ast
+ (idl,ty)::args, (List.map (fun {v=i} -> export,i)idl)@argsexport) binders_ast
([],[]) in
let mp =
@@ -763,7 +766,7 @@ let vernac_declare_module_type (loc,id) binders_ast mty_sign mty_ast_l =
Flags.if_verbose Feedback.msg_info
(str "Module Type " ++ Id.print id ++ str " is defined")
-let vernac_end_modtype (loc,id) =
+let vernac_end_modtype {loc;v=id} =
let mp = Declaremods.end_modtype () in
Dumpglob.dump_modref ?loc mp "modtype";
Flags.if_verbose Feedback.msg_info (str "Module Type " ++ Id.print id ++ str " is defined")
@@ -776,21 +779,21 @@ let vernac_include l =
(* Sections *)
-let vernac_begin_section (_, id as lid) =
+let vernac_begin_section ({v=id} as lid) =
Proof_global.check_no_pending_proof ();
Dumpglob.dump_definition lid true "sec";
Lib.open_section id
-let vernac_end_section (loc,_) =
+let vernac_end_section {CAst.loc} =
Dumpglob.dump_reference ?loc
(DirPath.to_string (Lib.current_dirpath true)) "<>" "sec";
Lib.close_section ()
-let vernac_name_sec_hyp (_,id) set = Proof_using.name_set id set
+let vernac_name_sec_hyp {v=id} set = Proof_using.name_set id set
(* Dispatcher of the "End" command *)
-let vernac_end_segment (_,id as lid) =
+let vernac_end_segment ({v=id} as lid) =
Proof_global.check_no_pending_proof ();
match Lib.find_opening_node id with
| Lib.OpenedModule (false,export,_,_) -> vernac_end_module export lid
@@ -973,7 +976,7 @@ let vernac_hints ~atts lb h =
let vernac_syntactic_definition ~atts lid x y =
Dumpglob.dump_definition lid false "syndef";
let local = enforce_module_locality atts.locality in
- Metasyntax.add_syntactic_definition (Global.env()) (snd lid) x local y
+ Metasyntax.add_syntactic_definition (Global.env()) lid.v x local y
let vernac_declare_implicits ~atts r l =
let local = make_section_locality atts.locality in
@@ -1209,7 +1212,7 @@ let vernac_arguments ~atts reference args more_implicits nargs_for_red flags =
end;
if scopes_specified || clear_scopes_flag then begin
- let scopes = List.map (Option.map (fun (loc,k) ->
+ let scopes = List.map (Option.map (fun {loc;v=k} ->
try ignore (Notation.find_scope k); k
with UserError _ ->
Notation.find_delimiters_scope ?loc k)) scopes
@@ -1822,7 +1825,7 @@ let vernac_locate = function
let vernac_register id r =
if Proof_global.there_are_pending_proofs () then
user_err Pp.(str "Cannot register a primitive while in proof editing mode.");
- let kn = Constrintern.global_reference (snd id) in
+ let kn = Constrintern.global_reference id.v in
if not (isConstRef kn) then
user_err Pp.(str "Register inline: a constant is expected");
match r with
@@ -2013,7 +2016,7 @@ let interp ?proof ~atts ~st c =
| VernacImport (export,qidl) -> vernac_import export qidl
| VernacCanonical qid -> vernac_canonical qid
| VernacCoercion (r,s,t) -> vernac_coercion ~atts r s t
- | VernacIdentityCoercion ((_,id),s,t) ->
+ | VernacIdentityCoercion ({v=id},s,t) ->
vernac_identity_coercion ~atts id s t
(* Type classes *)
@@ -2231,12 +2234,12 @@ let interp ?(verbosely=true) ?proof ~st (loc,c) =
aux ~polymorphism ~atts v
| VernacFail v -> with_fail st true (fun () -> control v)
| VernacTimeout (n,v) ->
- current_timeout := Some n;
- control v
- | VernacRedirect (s, (_,v)) ->
- Topfmt.with_output_to_file s control v
- | VernacTime (batch, (_loc,v)) ->
- System.with_time ~batch control v;
+ current_timeout := Some n;
+ control v
+ | VernacRedirect (s, {v}) ->
+ Topfmt.with_output_to_file s control v
+ | VernacTime (batch, {v}) ->
+ System.with_time ~batch control v;
and aux ~polymorphism ~atts : _ -> unit =
function
diff --git a/vernac/vernacprop.ml b/vernac/vernacprop.ml
index 3932d1c7b..172a20b7a 100644
--- a/vernac/vernacprop.ml
+++ b/vernac/vernacprop.ml
@@ -13,15 +13,15 @@ open Vernacexpr
let rec under_control = function
| VernacExpr (_, c) -> c
- | VernacRedirect (_,(_,c))
- | VernacTime (_,(_,c))
+ | VernacRedirect (_,{CAst.v=c})
+ | VernacTime (_,{CAst.v=c})
| VernacFail c
| VernacTimeout (_,c) -> under_control c
let rec has_Fail = function
| VernacExpr _ -> false
- | VernacRedirect (_,(_,c))
- | VernacTime (_,(_,c))
+ | VernacRedirect (_,{CAst.v=c})
+ | VernacTime (_,{CAst.v=c})
| VernacTimeout (_,c) -> has_Fail c
| VernacFail _ -> true
@@ -38,8 +38,8 @@ let is_navigation_vernac c =
is_navigation_vernac_expr (under_control c)
let rec is_deep_navigation_vernac = function
- | VernacTime (_,(_,c)) -> is_deep_navigation_vernac c
- | VernacRedirect (_, (_,c))
+ | VernacTime (_,{CAst.v=c}) -> is_deep_navigation_vernac c
+ | VernacRedirect (_, {CAst.v=c})
| VernacTimeout (_,c) | VernacFail c -> is_navigation_vernac c
| VernacExpr _ -> false