aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHugo Herbelin2020-10-23 22:58:30 +0200
committerHugo Herbelin2020-11-20 19:41:17 +0100
commit52b93b587b9cb53b0ed11c7d6cf5f328d7ee1479 (patch)
tree46642477744ae889c1871c6301ff5eb88bc2646f
parenta61f4371adf8e5f81866ce4e8684cafdd1dc050a (diff)
Add preliminary support for notations with large class (non-recursive) binders.
We introduce a class of open binders which includes "x", "x:t", "'pat" and a class of closed binders which includes "x", "(x:t)", "'pat".
-rw-r--r--interp/constrexpr.ml4
-rw-r--r--interp/constrexpr_ops.ml7
-rw-r--r--interp/constrextern.ml3
-rw-r--r--interp/constrintern.ml32
-rw-r--r--interp/notation.ml3
-rw-r--r--interp/notation_ops.ml24
-rw-r--r--interp/notation_ops.mli2
-rw-r--r--interp/notation_term.ml2
-rw-r--r--parsing/extend.ml1
-rw-r--r--parsing/extend.mli1
-rw-r--r--parsing/g_constr.mlg20
-rw-r--r--parsing/pcoq.ml2
-rw-r--r--parsing/pcoq.mli2
-rw-r--r--parsing/ppextend.ml6
-rw-r--r--parsing/ppextend.mli4
-rw-r--r--plugins/ssrsearch/g_search.mlg2
-rw-r--r--printing/ppconstr.ml19
-rw-r--r--vernac/egramcoq.ml11
-rw-r--r--vernac/metasyntax.ml24
19 files changed, 109 insertions, 60 deletions
diff --git a/interp/constrexpr.ml b/interp/constrexpr.ml
index 977cbbccf2..a5ff5df7cf 100644
--- a/interp/constrexpr.ml
+++ b/interp/constrexpr.ml
@@ -83,6 +83,8 @@ type cases_pattern_expr_r =
| CPatCast of cases_pattern_expr * constr_expr
and cases_pattern_expr = cases_pattern_expr_r CAst.t
+and kinded_cases_pattern_expr = cases_pattern_expr * Glob_term.binding_kind
+
and cases_pattern_notation_substitution =
cases_pattern_expr list * (* for constr subterms *)
cases_pattern_expr list list (* for recursive notations *)
@@ -150,7 +152,7 @@ and local_binder_expr =
and constr_notation_substitution =
constr_expr list * (* for constr subterms *)
constr_expr list list * (* for recursive notations *)
- cases_pattern_expr list * (* for binders *)
+ kinded_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/interp/constrexpr_ops.ml b/interp/constrexpr_ops.ml
index efc2a35b65..fe107c3580 100644
--- a/interp/constrexpr_ops.ml
+++ b/interp/constrexpr_ops.ml
@@ -94,6 +94,9 @@ and cases_pattern_notation_substitution_eq (s1, n1) (s2, n2) =
List.equal cases_pattern_expr_eq s1 s2 &&
List.equal (List.equal cases_pattern_expr_eq) n1 n2
+let kinded_cases_pattern_expr_eq (p1,bk1) (p2,bk2) =
+ cases_pattern_expr_eq p1 p2 && Glob_ops.binding_kind_eq bk1 bk2
+
let eq_universes u1 u2 =
match u1, u2 with
| None, None -> true
@@ -231,7 +234,7 @@ and local_binder_eq l1 l2 = match l1, l2 with
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 kinded_cases_pattern_expr_eq b1 b2 &&
List.equal (List.equal local_binder_eq) bl1 bl2
and instance_eq (x1,c1) (x2,c2) =
@@ -472,7 +475,7 @@ let locs_of_notation ?loc locs ntn =
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 (fun (x,_) -> cases_pattern_expr_loc x) binders@
List.map local_binders_loc binderslist)
let patntn_loc ?loc (args,argslist) =
diff --git a/interp/constrextern.ml b/interp/constrextern.ml
index 8d3cf7274a..aa3a458989 100644
--- a/interp/constrextern.ml
+++ b/interp/constrextern.ml
@@ -1303,7 +1303,8 @@ and extern_notation inctx (custom,scopes as allscopes) vars t rules =
termlists in
let bl =
List.map (fun ((vars,bl),(subentry,(scopt,scl))) ->
- mkCPatOr (List.map (extern_cases_pattern_in_scope (subentry,(scopt,scl@scopes')) vars) bl))
+ (mkCPatOr (List.map (extern_cases_pattern_in_scope (subentry,(scopt,scl@scopes')) vars) bl)),
+ Explicit)
binders in
let bll =
List.map (fun ((vars,bl),(subentry,(scopt,scl))) ->
diff --git a/interp/constrintern.ml b/interp/constrintern.ml
index b13225d91f..cb2c5b5f4c 100644
--- a/interp/constrintern.ml
+++ b/interp/constrintern.ml
@@ -715,7 +715,7 @@ let out_patvar = CAst.map_with_loc (fun ?loc -> function
| _ -> assert false)
let traverse_binder intern_pat ntnvars (terms,_,binders,_ as subst) avoid (renaming,env) = function
- | Anonymous -> (renaming,env), None, Anonymous
+ | Anonymous -> (renaming,env), None, Anonymous, Explicit
| Name id ->
let store,get = set_temporary_memory () in
let test_kind = test_kind_tolerant in
@@ -726,17 +726,17 @@ let traverse_binder intern_pat ntnvars (terms,_,binders,_ as subst) avoid (renam
let pat, na = match disjpat with
| [pat] when is_patvar_store store pat -> let na = get () in None, na
| _ -> Some ((List.map (fun x -> x.v) ids,disjpat),id), na.v in
- (renaming,env), pat, na
+ (renaming,env), pat, na, Explicit
with Not_found ->
try
(* Trying to associate a pattern *)
- let pat,(onlyident,scopes) = Id.Map.find id binders in
+ let (pat,bk),(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_patvar pat in
let env = push_name_env ntnvars [] env na in
- (renaming,env), None, na.v
+ (renaming,env), None, na.v, bk
else
(* Interpret as a pattern *)
let env,((disjpat,ids),id),na = intern_pat test_kind ntnvars env pat in
@@ -744,7 +744,7 @@ let traverse_binder intern_pat ntnvars (terms,_,binders,_ as subst) avoid (renam
match disjpat with
| [pat] when is_patvar_store store pat -> let na = get () in None, na
| _ -> Some ((List.map (fun x -> x.v) ids,disjpat),id), na.v in
- (renaming,env), pat, na
+ (renaming,env), pat, na, bk
with Not_found ->
(* Binders not bound in the notation do not capture variables *)
(* outside the notation (i.e. in the substitution) *)
@@ -752,7 +752,7 @@ let traverse_binder intern_pat ntnvars (terms,_,binders,_ as subst) avoid (renam
let renaming' =
if Id.equal id id' then renaming else Id.Map.add id id' renaming
in
- (renaming',env), None, Name id'
+ (renaming',env), None, Name id', Explicit
type binder_action =
| AddLetIn of lname * constr_expr * constr_expr option
@@ -877,7 +877,7 @@ let instantiate_notation_constr loc intern intern_pat ntnvars subst infos c =
Id.Map.add id (gc, None) map
with Nametab.GlobalizationError _ -> map
in
- let mk_env' (c, (onlyident,scopes)) =
+ let mk_env' ((c,_bk), (onlyident,scopes)) =
let nenv = set_env_scopes env scopes in
let test_kind =
if onlyident then test_kind_ident_in_notation
@@ -916,17 +916,17 @@ let instantiate_notation_constr loc intern intern_pat ntnvars subst infos 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,disjpat,na = traverse_binder intern_pat ntnvars subst avoid subinfos na in
+ let subinfos,disjpat,na,bk = 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,Option.fold_right apply_cases_pattern disjpat (aux subst' subinfos c'))
+ DAst.make ?loc @@ GProd (na,bk,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,disjpat,na = traverse_binder intern_pat ntnvars subst avoid subinfos na in
+ let subinfos,disjpat,na,bk = 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,Option.fold_right apply_cases_pattern disjpat (aux subst' subinfos c'))
+ DAst.make ?loc @@ GLambda (na,bk,ty,Option.fold_right apply_cases_pattern disjpat (aux subst' subinfos c'))
| t ->
glob_constr_of_notation_constr_with_binders ?loc
- (traverse_binder intern_pat ntnvars subst avoid) (aux subst') ~h:binder_status_fun subinfos t
+ (traverse_binder intern_pat ntnvars subst avoid) (aux subst') ~h:binder_status_fun subinfos t
and subst_var (terms, binderopt, _terminopt) (renaming, env) id =
(* subst remembers the delimiters stack in the interpretation *)
(* of the notations *)
@@ -935,7 +935,7 @@ let instantiate_notation_constr loc intern intern_pat ntnvars subst infos c =
intern (set_env_scopes env scopes) a
with Not_found ->
try
- let pat,(onlyident,scopes) = Id.Map.find id binders in
+ let (pat,_bk),(onlyident,scopes) = Id.Map.find id binders in
let nenv = set_env_scopes env scopes in
let test_kind =
if onlyident then test_kind_ident_in_notation
@@ -982,13 +982,13 @@ let split_by_type ids subst =
(terms,termlists,binders,binderlists),(terms',termlists',binders',binderlists')
| NtnTypeBinder NtnBinderParsedAsConstr (AsIdentOrPattern | 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
+ let binders' = Id.Map.add id ((coerce_to_cases_pattern_expr a,Explicit),(false,scl)) binders' in
(terms,termlists,binders,binderlists),(terms',termlists',binders',binderlists')
| NtnTypeBinder NtnBinderParsedAsConstr 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
+ let binders' = Id.Map.add id ((cases_pattern_of_name (coerce_to_name a),Explicit),(true,scl)) binders' in
(terms,termlists,binders,binderlists),(terms',termlists',binders',binderlists')
- | NtnTypeBinder (NtnParsedAsIdent | NtnParsedAsPattern _ as x) ->
+ | NtnTypeBinder (NtnParsedAsIdent | NtnParsedAsPattern _ | NtnParsedAsBinder 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')
diff --git a/interp/notation.ml b/interp/notation.ml
index 286ece6cb6..b5951a9c59 100644
--- a/interp/notation.ml
+++ b/interp/notation.ml
@@ -64,7 +64,8 @@ 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
+| NtnParsedAsBinder, NtnParsedAsBinder -> true
+| (NtnParsedAsIdent | NtnParsedAsPattern _ | NtnBinderParsedAsConstr _ | NtnParsedAsBinder), _ -> false
let ntpe_eq t1 t2 = match t1, t2 with
| NtnTypeConstr, NtnTypeConstr -> true
diff --git a/interp/notation_ops.ml b/interp/notation_ops.ml
index c4d2a2a496..61f93aa969 100644
--- a/interp/notation_ops.ml
+++ b/interp/notation_ops.ml
@@ -272,9 +272,14 @@ let default_binder_status_fun = {
slide = (fun x -> x);
}
+let test_implicit_argument_mark bk =
+ if not (Glob_ops.binding_kind_eq bk Explicit) then
+ user_err (Pp.str "Unexpected implicit argument mark.")
+
let protect g e na =
- let e',disjpat,na = g e na in
+ let e',disjpat,na,bk = g e na in
if disjpat <> None then user_err (Pp.str "Unsupported substitution of an arbitrary pattern.");
+ test_implicit_argument_mark bk;
e',na
let apply_cases_pattern_term ?loc (ids,disjpat) tm c =
@@ -302,12 +307,13 @@ let glob_constr_of_notation_constr_with_binders ?loc g f ?(h=default_binder_stat
DAst.get (subst_glob_vars outerl it)
| NLambda (na,ty,c) ->
let e = h.switch_lambda e in
- let e',disjpat,na = g e na in GLambda (na,Explicit,f (h.restart_prod e) ty,Option.fold_right (apply_cases_pattern ?loc) disjpat (f e' c))
+ let e',disjpat,na,bk = g e na in GLambda (na,bk,f (h.restart_prod e) ty,Option.fold_right (apply_cases_pattern ?loc) disjpat (f e' c))
| NProd (na,ty,c) ->
let e = h.switch_prod e in
- let e',disjpat,na = g e na in GProd (na,Explicit,f (h.restart_prod e) ty,Option.fold_right (apply_cases_pattern ?loc) disjpat (f e' c))
+ let e',disjpat,na,bk = g e na in GProd (na,bk,f (h.restart_prod e) ty,Option.fold_right (apply_cases_pattern ?loc) disjpat (f e' c))
| NLetIn (na,b,t,c) ->
- let e',disjpat,na = g e na in
+ let e',disjpat,na,bk = g e na in
+ test_implicit_argument_mark bk;
(match disjpat with
| None -> GLetIn (na,f (h.restart_lambda e) b,Option.map (f (h.restart_prod e)) t,f e' c)
| Some (disjpat,_id) -> DAst.get (apply_cases_pattern_term ?loc disjpat (f e b) (f e' c)))
@@ -323,7 +329,10 @@ let glob_constr_of_notation_constr_with_binders ?loc g f ?(h=default_binder_stat
e',Some (CAst.make ?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 fold (idl,e) na =
+ let (e,disjpat,na,bk) = g e na in
+ test_implicit_argument_mark bk;
+ ((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
@@ -356,7 +365,7 @@ let glob_constr_of_notation_constr_with_binders ?loc g f ?(h=default_binder_stat
let glob_constr_of_notation_constr ?loc x =
let rec aux () x =
- glob_constr_of_notation_constr_with_binders ?loc (fun () id -> ((),None,id)) aux () x
+ glob_constr_of_notation_constr_with_binders ?loc (fun () id -> ((),None,id,Explicit)) aux () x
in aux () x
(******************************************************************************)
@@ -852,6 +861,7 @@ let is_onlybinding_pattern_like_meta isvar id metas =
| _,NtnTypeBinder (NtnBinderParsedAsConstr
(AsIdentOrPattern | AsStrictPattern)) -> true
| _,NtnTypeBinder (NtnParsedAsPattern strict) -> not (strict && isvar)
+ | _,NtnTypeBinder NtnParsedAsBinder -> not isvar
| _ -> false
with Not_found -> false
@@ -1497,7 +1507,7 @@ let match_notation_constr ~print_univ c ~vars (metas,pat) =
let v = glob_constr_of_cases_pattern (Global.env()) pat in
(((vars,v),scl)::terms',termlists',binders',binderlists')
| _ -> raise No_match)
- | NtnTypeBinder (NtnParsedAsIdent | NtnParsedAsPattern _) ->
+ | NtnTypeBinder (NtnParsedAsIdent | NtnParsedAsPattern _ | NtnParsedAsBinder) ->
(terms',termlists',(Id.List.assoc x binders,scl)::binders',binderlists')
| NtnTypeConstrList ->
(terms',(Id.List.assoc x termlists,scl)::termlists',binders',binderlists')
diff --git a/interp/notation_ops.mli b/interp/notation_ops.mli
index 9d451a5bb9..3e8fdd8254 100644
--- a/interp/notation_ops.mli
+++ b/interp/notation_ops.mli
@@ -53,7 +53,7 @@ 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 * ((Id.t list * cases_pattern_disjunction) * Id.t) option * Name.t) ->
+ ('a -> Name.t -> 'a * ((Id.t list * cases_pattern_disjunction) * Id.t) option * Name.t * Glob_term.binding_kind) ->
('a -> notation_constr -> glob_constr) -> ?h:'a binder_status_fun ->
'a -> notation_constr -> glob_constr
diff --git a/interp/notation_term.ml b/interp/notation_term.ml
index 82238b71b7..47b9deccce 100644
--- a/interp/notation_term.ml
+++ b/interp/notation_term.ml
@@ -78,6 +78,8 @@ type notation_binder_source =
| NtnParsedAsIdent
(* This accepts ident, or pattern, or both *)
| NtnBinderParsedAsConstr of constr_as_binder_kind
+ (* This accepts ident, _, and quoted pattern *)
+ | NtnParsedAsBinder
type notation_var_instance_type =
| NtnTypeConstr | NtnTypeBinder of notation_binder_source | NtnTypeConstrList | NtnTypeBinderList
diff --git a/parsing/extend.ml b/parsing/extend.ml
index a6fa6edad5..94c3768116 100644
--- a/parsing/extend.ml
+++ b/parsing/extend.ml
@@ -58,6 +58,7 @@ type constr_prod_entry_key =
| ETProdName (* Parsed as a name (ident or _) *)
| ETProdReference (* Parsed as a global reference *)
| ETProdBigint (* Parsed as an (unbounded) integer *)
+ | ETProdOneBinder of bool (* Parsed as name, or name:type or 'pattern, possibly in closed form *)
| ETProdConstr of Constrexpr.notation_entry * (production_level * production_position) (* Parsed as constr or pattern, or a subentry of those *)
| ETProdPattern of int (* Parsed as pattern as a binder (as subpart of a constr) *)
| ETProdConstrList of Constrexpr.notation_entry * (production_level * production_position) * string Tok.p list (* Parsed as non-empty list of constr, or subentries of those *)
diff --git a/parsing/extend.mli b/parsing/extend.mli
index 057fdb3841..b698415fd6 100644
--- a/parsing/extend.mli
+++ b/parsing/extend.mli
@@ -53,6 +53,7 @@ type constr_prod_entry_key =
| ETProdName (* Parsed as a name (ident or _) *)
| ETProdReference (* Parsed as a global reference *)
| ETProdBigint (* Parsed as an (unbounded) integer *)
+ | ETProdOneBinder of bool (* Parsed as name, or name:type or 'pattern, possibly in closed form *)
| ETProdConstr of Constrexpr.notation_entry * (production_level * production_position) (* Parsed as constr or pattern, or a subentry of those *)
| ETProdPattern of int (* Parsed as pattern as a binder (as subpart of a constr) *)
| ETProdConstrList of Constrexpr.notation_entry * (production_level * production_position) * string Tok.p list (* Parsed as non-empty list of constr, or subentries of those *)
diff --git a/parsing/g_constr.mlg b/parsing/g_constr.mlg
index 67a061175a..9b4b41acd2 100644
--- a/parsing/g_constr.mlg
+++ b/parsing/g_constr.mlg
@@ -39,6 +39,10 @@ let binder_of_name expl { CAst.loc = loc; v = na } =
let binders_of_names l =
List.map (binder_of_name Explicit) l
+let pat_of_name CAst.{loc;v} = match v with
+| Anonymous -> CAst.make ?loc @@ CPatAtom None
+| Name id -> CAst.make ?loc @@ CPatAtom (Some (qualid_of_ident id))
+
let err () = raise Stream.Failure
(* Hack to parse "(x:=t)" as an explicit argument without conflicts with the *)
@@ -84,7 +88,8 @@ GRAMMAR EXTEND Gram
universe_level universe_name sort sort_family
global constr_pattern cpattern Constr.ident
closed_binder open_binders binder binders binders_fixannot
- record_declaration typeclass_constraint pattern arg type_cstr;
+ record_declaration typeclass_constraint pattern arg type_cstr
+ one_closed_binder one_open_binder;
Constr.ident:
[ [ id = Prim.ident -> { id } ] ]
;
@@ -446,6 +451,19 @@ GRAMMAR EXTEND Gram
in
[CLocalPattern (CAst.make ~loc (p, ty))] } ] ]
;
+ one_open_binder:
+ [ [ na = name -> { (pat_of_name na, Explicit) }
+ | na = name; ":"; t = lconstr -> { (CAst.make ~loc @@ CPatCast (pat_of_name na, t), Explicit) }
+ | b = one_closed_binder -> { b } ] ]
+ ;
+ one_closed_binder:
+ [ [ "("; na = name; ":"; t = lconstr; ")" -> { (CAst.make ~loc @@ CPatCast (pat_of_name na, t), Explicit) }
+ | "{"; na = name; "}" -> { (pat_of_name na, MaxImplicit) }
+ | "{"; na = name; ":"; t = lconstr; "}" -> { (CAst.make ~loc @@ CPatCast (pat_of_name na, t), MaxImplicit) }
+ | "["; na = name; "]" -> { (pat_of_name na, NonMaxImplicit) }
+ | "["; na = name; ":"; t = lconstr; "]" -> { (CAst.make ~loc @@ CPatCast (pat_of_name na, t), NonMaxImplicit) }
+ | "'"; p = pattern LEVEL "0" -> { (p, Explicit) } ] ]
+ ;
typeclass_constraint:
[ [ "!" ; c = term LEVEL "200" -> { (CAst.make ~loc Anonymous), true, c }
| "{"; id = name; "}"; ":" ; expl = [ "!" -> { true } | -> { false } ] ; c = term LEVEL "200" ->
diff --git a/parsing/pcoq.ml b/parsing/pcoq.ml
index 22b5e70311..d49a49d242 100644
--- a/parsing/pcoq.ml
+++ b/parsing/pcoq.ml
@@ -327,6 +327,8 @@ module Constr =
let binder = Entry.create "binder"
let binders = Entry.create "binders"
let open_binders = Entry.create "open_binders"
+ let one_open_binder = Entry.create "one_open_binder"
+ let one_closed_binder = Entry.create "one_closed_binder"
let binders_fixannot = Entry.create "binders_fixannot"
let typeclass_constraint = Entry.create "typeclass_constraint"
let record_declaration = Entry.create "record_declaration"
diff --git a/parsing/pcoq.mli b/parsing/pcoq.mli
index ce4c91d51f..d0ae594db1 100644
--- a/parsing/pcoq.mli
+++ b/parsing/pcoq.mli
@@ -203,6 +203,8 @@ module Constr :
val binder : local_binder_expr list Entry.t (* closed_binder or variable *)
val binders : local_binder_expr list Entry.t (* list of binder *)
val open_binders : local_binder_expr list Entry.t
+ val one_open_binder : kinded_cases_pattern_expr Entry.t
+ val one_closed_binder : kinded_cases_pattern_expr Entry.t
val binders_fixannot : (local_binder_expr list * recursion_order_expr option) Entry.t
val typeclass_constraint : (lname * bool * constr_expr) Entry.t
val record_declaration : constr_expr Entry.t
diff --git a/parsing/ppextend.ml b/parsing/ppextend.ml
index aab385a707..b64c2b956a 100644
--- a/parsing/ppextend.ml
+++ b/parsing/ppextend.ml
@@ -36,9 +36,11 @@ let ppcmd_of_cut = function
| PpFnl -> fnl ()
| PpBrk(n1,n2) -> brk(n1,n2)
+type pattern_quote_style = QuotedPattern | NotQuotedPattern
+
type unparsing =
| UnpMetaVar of entry_relative_level * Extend.side option
- | UnpBinderMetaVar of entry_relative_level
+ | UnpBinderMetaVar of entry_relative_level * pattern_quote_style
| UnpListMetaVar of entry_relative_level * unparsing list * Extend.side option
| UnpBinderListMetaVar of bool * unparsing list
| UnpTerminal of string
@@ -50,7 +52,7 @@ type extra_unparsing_rules = (string * string) list
let rec unparsing_eq unp1 unp2 = match (unp1,unp2) with
| UnpMetaVar (p1,s1), UnpMetaVar (p2,s2) -> entry_relative_level_eq p1 p2 && s1 = s2
- | UnpBinderMetaVar p1, UnpBinderMetaVar p2 -> entry_relative_level_eq p1 p2
+ | UnpBinderMetaVar (p1,s1), UnpBinderMetaVar (p2,s2) -> entry_relative_level_eq p1 p2 && s1 = s2
| UnpListMetaVar (p1,l1,s1), UnpListMetaVar (p2,l2,s2) -> entry_relative_level_eq p1 p2 && List.for_all2eq unparsing_eq l1 l2 && s1 = s2
| UnpBinderListMetaVar (b1,l1), UnpBinderListMetaVar (b2,l2) -> b1 = b2 && List.for_all2eq unparsing_eq l1 l2
| UnpTerminal s1, UnpTerminal s2 -> String.equal s1 s2
diff --git a/parsing/ppextend.mli b/parsing/ppextend.mli
index 56a3fc8e3c..ca22aacacf 100644
--- a/parsing/ppextend.mli
+++ b/parsing/ppextend.mli
@@ -28,10 +28,12 @@ val ppcmd_of_cut : ppcut -> Pp.t
(** {6 Printing rules for notations} *)
+type pattern_quote_style = QuotedPattern | NotQuotedPattern
+
(** Declare and look for the printing rule for symbolic notations *)
type unparsing =
| UnpMetaVar of entry_relative_level * Extend.side option
- | UnpBinderMetaVar of entry_relative_level
+ | UnpBinderMetaVar of entry_relative_level * pattern_quote_style
| UnpListMetaVar of entry_relative_level * unparsing list * Extend.side option
| UnpBinderListMetaVar of bool * unparsing list
| UnpTerminal of string
diff --git a/plugins/ssrsearch/g_search.mlg b/plugins/ssrsearch/g_search.mlg
index 54fdea0860..2daecd4af8 100644
--- a/plugins/ssrsearch/g_search.mlg
+++ b/plugins/ssrsearch/g_search.mlg
@@ -141,7 +141,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 -> (), None, x) sub () c in
+ glob_constr_of_notation_constr_with_binders ?loc (fun _ x -> (), None, x, Explicit) sub () c in
let _, npat = Patternops.pattern_of_glob_constr (sub () body) in
Search.GlobSearchSubPattern (Vernacexpr.Anywhere,false,npat)
diff --git a/printing/ppconstr.ml b/printing/ppconstr.ml
index e312c68b7d..f726626ac4 100644
--- a/printing/ppconstr.ml
+++ b/printing/ppconstr.ml
@@ -98,10 +98,10 @@ let tag_var = tag Tag.variable
let pp2 = aux l in
let pp1 = pr (if parens && side <> None then LevelLe 0 else prec) c in
return unp pp1 pp2
- | UnpBinderMetaVar prec as unp :: l ->
- let c = pop bl in
+ | UnpBinderMetaVar (prec,style) as unp :: l ->
+ let c,bk = pop bl in
let pp2 = aux l in
- let pp1 = pr_patt prec c in
+ let pp1 = pr_patt prec style bk c in
return unp pp1 pp2
| UnpListMetaVar (prec, sl, side) as unp :: l ->
let cl = pop envlist in
@@ -310,7 +310,7 @@ let tag_var = tag Tag.variable
pr_patt (fun()->str"(") lpattop p ++ str")", latom
| CPatNotation (which,s,(l,ll),args) ->
- let strm_not, l_not = pr_notation (pr_patt mt) (fun _ _ -> mt ()) (fun _ _ _ -> mt()) which s (l,ll,[],[]) in
+ let strm_not, l_not = pr_notation (pr_patt mt) (fun _ _ _ _ -> mt ()) (fun _ _ _ -> mt()) which s (l,ll,[],[]) in
(if List.is_empty args||prec_less l_not (LevelLt lapp) then strm_not else surround strm_not)
++ prlist (pr_patt spc (LevelLt lapp)) args, if not (List.is_empty args) then lapp else l_not
@@ -329,6 +329,15 @@ let tag_var = tag Tag.variable
let pr_patt = pr_patt mt
+ let pr_patt_binder prec style bk c =
+ match bk with
+ | MaxImplicit -> str "{" ++ pr_patt lpattop c ++ str "}"
+ | NonMaxImplicit -> str "[" ++ pr_patt lpattop c ++ str "]"
+ | Explicit ->
+ match style, c with
+ | NotQuotedPattern, _ | _, {v=CPatAtom _} -> pr_patt prec c
+ | QuotedPattern, _ -> str "'" ++ pr_patt prec c
+
let pr_eqn pr {loc;v=(pl,rhs)} =
spc() ++ hov 4
(pr_with_comments ?loc
@@ -673,7 +682,7 @@ let tag_var = tag Tag.variable
| CNotation (_,(_,"( _ )"),([t],[],[],[])) ->
return (pr (fun()->str"(") ltop t ++ str")", latom)
| CNotation (which,s,env) ->
- pr_notation (pr mt) pr_patt (pr_binders_gen (pr mt ltop)) which s env
+ pr_notation (pr mt) pr_patt_binder (pr_binders_gen (pr mt ltop)) which s env
| CGeneralization (bk,ak,c) ->
return (pr_generalization bk ak (pr mt ltop c), latom)
| CPrim p ->
diff --git a/vernac/egramcoq.ml b/vernac/egramcoq.ml
index efe4e17d0b..ad6ac8d3f3 100644
--- a/vernac/egramcoq.ml
+++ b/vernac/egramcoq.ml
@@ -249,6 +249,7 @@ type (_, _) entry =
| TTName : ('self, lname) entry
| TTReference : ('self, qualid) entry
| TTBigint : ('self, string) entry
+| TTBinder : bool -> ('self, kinded_cases_pattern_expr) entry
| TTConstr : notation_entry * prod_info * 'r target -> ('r, 'r) entry
| TTConstrList : notation_entry * prod_info * string Tok.p list * 'r target -> ('r, 'r list) entry
| TTPattern : int -> ('self, cases_pattern_expr) entry
@@ -364,6 +365,8 @@ let symbol_of_entry : type s r. _ -> _ -> (s, r) entry -> (s, r) mayrec_symbol =
| TTClosedBinderList [] -> MayRecNo (Pcoq.Symbol.list1 (Pcoq.Symbol.nterm Constr.binder))
| TTClosedBinderList tkl -> MayRecNo (Pcoq.Symbol.list1sep (Pcoq.Symbol.nterm Constr.binder) (make_sep_rules tkl) false)
| TTName -> MayRecNo (Pcoq.Symbol.nterm Prim.name)
+| TTBinder true -> MayRecNo (Pcoq.Symbol.nterm Constr.one_open_binder)
+| TTBinder false -> MayRecNo (Pcoq.Symbol.nterm Constr.one_closed_binder)
| TTOpenBinderList -> MayRecNo (Pcoq.Symbol.nterm Constr.open_binders)
| TTBigint -> MayRecNo (Pcoq.Symbol.nterm Prim.bignat)
| TTReference -> MayRecNo (Pcoq.Symbol.nterm Constr.global)
@@ -372,6 +375,7 @@ let interp_entry forpat e = match e with
| ETProdName -> TTAny TTName
| ETProdReference -> TTAny TTReference
| ETProdBigint -> TTAny TTBigint
+| ETProdOneBinder o -> TTAny (TTBinder o)
| ETProdConstr (s,p) -> TTAny (TTConstr (s, p, forpat))
| ETProdPattern p -> TTAny (TTPattern p)
| ETProdConstrList (s, p, tkl) -> TTAny (TTConstrList (s, p, tkl, forpat))
@@ -385,7 +389,7 @@ let cases_pattern_expr_of_name { CAst.loc; v = na } = CAst.make ?loc @@ match na
type 'r env = {
constrs : 'r list;
constrlists : 'r list list;
- binders : cases_pattern_expr list;
+ binders : kinded_cases_pattern_expr list;
binderlists : local_binder_expr list list;
}
@@ -396,14 +400,15 @@ match e with
| TTConstr _ -> push_constr subst v
| TTName ->
begin match forpat with
- | ForConstr -> { subst with binders = cases_pattern_expr_of_name v :: subst.binders }
+ | ForConstr -> { subst with binders = (cases_pattern_expr_of_name v, Glob_term.Explicit) :: subst.binders }
| ForPattern -> push_constr subst (cases_pattern_expr_of_name v)
end
| TTPattern _ ->
begin match forpat with
- | ForConstr -> { subst with binders = v :: subst.binders }
+ | ForConstr -> { subst with binders = (v, Glob_term.Explicit) :: subst.binders }
| ForPattern -> push_constr subst v
end
+| TTBinder o -> { subst with binders = v :: subst.binders }
| TTOpenBinderList -> { subst with binderlists = v :: subst.binderlists }
| TTClosedBinderList _ -> { subst with binderlists = List.flatten v :: subst.binderlists }
| TTBigint ->
diff --git a/vernac/metasyntax.ml b/vernac/metasyntax.ml
index dc2b2e889e..8759798331 100644
--- a/vernac/metasyntax.ml
+++ b/vernac/metasyntax.ml
@@ -342,12 +342,10 @@ let unparsing_metavar i from typs =
match x with
| ETConstr _ | ETGlobal | ETBigint ->
UnpMetaVar (prec,side)
- | ETPattern _ ->
- UnpBinderMetaVar prec
- | ETIdent ->
- UnpBinderMetaVar prec
- | ETBinder isopen ->
- assert false
+ | ETPattern _ | ETIdent ->
+ UnpBinderMetaVar (prec,NotQuotedPattern)
+ | ETBinder _ ->
+ UnpBinderMetaVar (prec,QuotedPattern)
(* Heuristics for building default printing rules *)
@@ -636,7 +634,7 @@ let prod_entry_type = function
| ETIdent -> ETProdName
| ETGlobal -> ETProdReference
| ETBigint -> ETProdBigint
- | ETBinder _ -> assert false (* See check_binder_type *)
+ | ETBinder o -> ETProdOneBinder o
| ETConstr (s,_,p) -> ETProdConstr (s,p)
| ETPattern (_,n) -> ETProdPattern (match n with None -> 0 | Some n -> n)
@@ -970,15 +968,6 @@ let check_useless_entry_types recvars mainvars etyps =
(Id.print x ++ str " is unbound in the notation.")
| _ -> ()
-let check_binder_type recvars etyps =
- let l1,l2 = List.split recvars in
- let l = l1@l2 in
- List.iter (function
- | (x,ETBinder b) when not (List.mem x l) ->
- CErrors.user_err (str (if b then "binder" else "closed binder") ++
- strbrk " is only for use in recursive notations for binders.")
- | _ -> ()) etyps
-
let interp_non_syntax_modifiers mods =
let set modif (only_parsing,only_printing,entry) = match modif with
| SetOnlyParsing -> Some (true,only_printing,entry)
@@ -1058,7 +1047,7 @@ let make_interpretation_type isrec isonlybinding default_if_binding = function
| ETBigint | ETGlobal -> NtnTypeConstr
| ETBinder _ ->
if isrec then NtnTypeBinderList
- else anomaly Pp.(str "Type binder is only for use in recursive notations for binders.")
+ else NtnTypeBinder NtnParsedAsBinder
let subentry_of_constr_prod_entry from_level = function
(* Specific 8.2 approximation *)
@@ -1297,7 +1286,6 @@ let compute_syntax_data ~local deprecation df modifiers =
let assoc = Option.append mods.assoc (Some Gramlib.Gramext.NonA) 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
(* Notations for interp and grammar *)
let msgs,n = find_precedence mods.custom mods.level mods.etyps symbols onlyprint in