aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--interp/constrexpr_ops.ml23
-rw-r--r--interp/constrexpr_ops.mli4
-rw-r--r--interp/constrextern.ml37
-rw-r--r--interp/constrintern.ml579
-rw-r--r--interp/notation.ml4
-rw-r--r--interp/notation.mli4
-rw-r--r--interp/topconstr.ml13
-rw-r--r--intf/constrexpr.mli16
-rw-r--r--parsing/egramcoq.ml2
-rw-r--r--parsing/g_constr.ml410
-rw-r--r--plugins/decl_mode/decl_interp.ml9
-rw-r--r--printing/ppconstr.ml17
12 files changed, 355 insertions, 363 deletions
diff --git a/interp/constrexpr_ops.ml b/interp/constrexpr_ops.ml
index 18f0a38d4..27cebf9e6 100644
--- a/interp/constrexpr_ops.ml
+++ b/interp/constrexpr_ops.ml
@@ -13,6 +13,7 @@ open Nameops
open Libnames
open Misctypes
open Term
+open Glob_term
open Mod_subst
open Constrexpr
open Decl_kinds
@@ -57,15 +58,20 @@ let constr_loc = function
let cases_pattern_expr_loc = function
| CPatAlias (loc,_,_) -> loc
- | CPatCstr (loc,_,_) -> loc
- | CPatCstrExpl (loc,_,_) -> loc
+ | CPatCstr (loc,_,_,_) -> loc
| CPatAtom (loc,_) -> loc
| CPatOr (loc,_) -> loc
- | CPatNotation (loc,_,_) -> loc
+ | CPatNotation (loc,_,_,_) -> loc
| CPatRecord (loc, _) -> loc
| CPatPrim (loc,_) -> loc
| CPatDelimiters (loc,_,_) -> loc
+let raw_cases_pattern_expr_loc = function
+ | RCPatAlias (loc,_,_) -> loc
+ | RCPatCstr (loc,_,_,_) -> loc
+ | RCPatAtom (loc,_) -> loc
+ | RCPatOr (loc,_) -> loc
+
let local_binder_loc = function
| LocalRawAssum ((loc,_)::_,_,t)
| LocalRawDef ((loc,_),t) -> join_loc loc (constr_loc t)
@@ -140,3 +146,14 @@ let coerce_to_name = function
| a -> Errors.user_err_loc
(constr_loc a,"coerce_to_name",
str "This expression should be a name.")
+
+let rec raw_cases_pattern_expr_of_glob_constr looked_for = function
+ | GVar (loc,id) -> RCPatAtom (loc,Some id)
+ | GHole (loc,_) -> RCPatAtom (loc,None)
+ | GRef (loc,g) ->
+ looked_for g;
+ RCPatCstr (loc, g,[],[])
+ | GApp (loc,GRef (_,g),l) ->
+ looked_for g;
+ RCPatCstr (loc, g,[],List.map (raw_cases_pattern_expr_of_glob_constr looked_for) l)
+ | _ -> raise Not_found
diff --git a/interp/constrexpr_ops.mli b/interp/constrexpr_ops.mli
index 161320626..d3e32da46 100644
--- a/interp/constrexpr_ops.mli
+++ b/interp/constrexpr_ops.mli
@@ -19,6 +19,7 @@ open Constrexpr
val constr_loc : constr_expr -> loc
val cases_pattern_expr_loc : cases_pattern_expr -> loc
+val raw_cases_pattern_expr_loc : raw_cases_pattern_expr -> loc
val local_binders_loc : local_binder list -> loc
@@ -50,3 +51,6 @@ val names_of_local_assums : local_binder list -> name located list
(** Does not take let binders into account *)
val names_of_local_binders : local_binder list -> name located list
+
+val raw_cases_pattern_expr_of_glob_constr : (Globnames.global_reference -> unit)
+ -> Glob_term.glob_constr -> raw_cases_pattern_expr
diff --git a/interp/constrextern.ml b/interp/constrextern.ml
index 7537e7d0b..9ac030136 100644
--- a/interp/constrextern.ml
+++ b/interp/constrextern.ml
@@ -169,10 +169,9 @@ let rec check_same_pattern p1 p2 =
match p1, p2 with
| CPatAlias(_,a1,i1), CPatAlias(_,a2,i2) when i1=i2 ->
check_same_pattern a1 a2
- | CPatCstr(_,c1,a1), CPatCstr(_,c2,a2) when c1=c2 ->
- List.iter2 check_same_pattern a1 a2
- | CPatCstrExpl(_,c1,a1), CPatCstrExpl(_,c2,a2) when c1=c2 ->
- List.iter2 check_same_pattern a1 a2
+ | CPatCstr(_,c1,a1,b1), CPatCstr(_,c2,a2,b2) when c1=c2 ->
+ let () = List.iter2 check_same_pattern a1 a2 in
+ List.iter2 check_same_pattern b1 b2
| CPatAtom(_,r1), CPatAtom(_,r2) when r1=r2 -> ()
| CPatPrim(_,i1), CPatPrim(_,i2) when i1=i2 -> ()
| CPatDelimiters(_,s1,e1), CPatDelimiters(_,s2,e2) when s1=s2 ->
@@ -321,21 +320,21 @@ let make_notation loc ntn (terms,termlists,binders as subst) =
destPrim terms
let make_pat_notation loc ntn (terms,termlists as subst) =
- if termlists <> [] then CPatNotation (loc,ntn,subst) else
+ if termlists <> [] then CPatNotation (loc,ntn,subst,[]) else
make_notation_gen loc ntn
- (fun (loc,ntn,l) -> CPatNotation (loc,ntn,(l,[])))
+ (fun (loc,ntn,l) -> CPatNotation (loc,ntn,(l,[]),[]))
(fun (loc,p) -> CPatPrim (loc,p))
destPatPrim terms
let mkPat loc qid l =
(* Normally irrelevant test with v8 syntax, but let's do it anyway *)
- if l = [] then CPatAtom (loc,Some qid) else CPatCstr (loc,qid,l)
+ if l = [] then CPatAtom (loc,Some qid) else CPatCstr (loc,qid,[],l)
let add_patt_for_params ind l =
Util.list_addn (fst (Inductiveops.inductive_nargs ind)) (CPatAtom (dummy_loc,None)) l
-let drop_implicits_in_patt ind args =
- let impl_st = extract_impargs_data (implicits_of_global (IndRef ind)) in
+let drop_implicits_in_patt cst args =
+ let impl_st = extract_impargs_data (implicits_of_global cst) in
let rec impls_fit l = function
|[],t -> Some (List.rev_append l t)
|_,[] -> None
@@ -367,7 +366,7 @@ let rec extern_cases_pattern_in_scope (scopes:local_scopes) vars pat =
when !in_debugger||Inductiveops.mis_constructor_has_local_defs cstrsp ->
let c = extern_reference loc Idset.empty (ConstructRef cstrsp) in
let args = List.map (extern_cases_pattern_in_scope scopes vars) args in
- CPatCstrExpl (loc, c, add_patt_for_params (fst cstrsp) args)
+ CPatCstr (loc, c, add_patt_for_params (fst cstrsp) args, [])
| _ ->
try
if !Flags.raw_print or !print_no_symbol then raise No_match;
@@ -410,13 +409,13 @@ let rec extern_cases_pattern_in_scope (scopes:local_scopes) vars pat =
let c = extern_reference loc Idset.empty (ConstructRef cstrsp) in
if !Topconstr.oldfashion_patterns then
if pattern_printable_in_both_syntax cstrsp
- then CPatCstr (loc, c, args)
- else CPatCstrExpl (loc, c, add_patt_for_params (fst cstrsp) args)
+ then CPatCstr (loc, c, [], args)
+ else CPatCstr (loc, c, add_patt_for_params (fst cstrsp) args, [])
else
let full_args = add_patt_for_params (fst cstrsp) args in
- match drop_implicits_in_patt (fst cstrsp) full_args with
- |Some true_args -> CPatCstr (loc, c, true_args)
- |None -> CPatCstrExpl (loc, c, full_args)
+ match drop_implicits_in_patt (ConstructRef cstrsp) full_args with
+ |Some true_args -> CPatCstr (loc, c, [], true_args)
+ |None -> CPatCstr (loc, c, full_args, [])
in insert_pat_alias loc p na
and apply_notation_to_pattern loc ((subst,substlist),more_args) (tmp_scope, scopes as allscopes) vars =
function
@@ -483,7 +482,7 @@ let extern_ind_pattern_in_scope (scopes:local_scopes) vars ind args =
if !in_debugger||Inductiveops.inductive_has_local_defs ind then
let c = extern_reference dummy_loc vars (IndRef ind) in
let args = List.map (extern_cases_pattern_in_scope scopes vars) args in
- CPatCstrExpl (dummy_loc, c, add_patt_for_params ind args)
+ CPatCstr (dummy_loc, c, add_patt_for_params ind args, [])
else
try
if !Flags.raw_print or !print_no_symbol then raise No_match;
@@ -500,9 +499,9 @@ let extern_ind_pattern_in_scope (scopes:local_scopes) vars ind args =
with No_match ->
let c = extern_reference dummy_loc vars (IndRef ind) in
let args = List.map (extern_cases_pattern_in_scope scopes vars) args in
- match drop_implicits_in_patt ind args with
- |Some true_args -> CPatCstr (dummy_loc, c, true_args)
- |None -> CPatCstrExpl (dummy_loc, c, args)
+ match drop_implicits_in_patt (IndRef ind) args with
+ |Some true_args -> CPatCstr (dummy_loc, c, [], true_args)
+ |None -> CPatCstr (dummy_loc, c, args, [])
let extern_cases_pattern vars p =
extern_cases_pattern_in_scope (None,[]) vars p
diff --git a/interp/constrintern.ml b/interp/constrintern.ml
index 304712675..f6513fd0d 100644
--- a/interp/constrintern.ml
+++ b/interp/constrintern.ml
@@ -176,7 +176,7 @@ let explain_internalization_error e =
let error_bad_inductive_type loc =
user_err_loc (loc,"",str
- "This should be an inductive type applied to names or \"_\".")
+ "This should be an inductive type applied to patterns.")
let error_parameter_not_implicit loc =
user_err_loc (loc,"", str
@@ -248,7 +248,7 @@ let contract_pat_notation ntn (l,ll) =
let ntn' = ref ntn in
let rec contract_squash n = function
| [] -> []
- | CPatNotation (_,"{ _ }",([a],[])) :: l ->
+ | CPatNotation (_,"{ _ }",([a],[]),[]) :: l ->
ntn' := expand_notation_string !ntn' n;
contract_squash n (a::l)
| a :: l ->
@@ -744,6 +744,10 @@ let interp_reference vars r =
(vars,[]) [] r
in r
+(**********************************************************************)
+(** {5 Cases } *)
+
+(** {6 Elemtary bricks } *)
let apply_scope_env env = function
| [] -> {env with tmp_scope = None}, []
| sc::scl -> {env with tmp_scope = sc}, scl
@@ -757,12 +761,21 @@ let rec simple_adjust_scopes n scopes =
| sc::scopes -> sc :: simple_adjust_scopes (n-1) scopes
let find_remaining_scopes pl1 pl2 ref =
- snd (list_chop (List.length pl1)
- (simple_adjust_scopes (List.length pl1 + List.length pl2)
- (find_arguments_scope ref)))
-
-(**********************************************************************)
-(* Cases *)
+ let impls_st = implicits_of_global ref in
+ let len_pl1 = List.length pl1 in
+ let len_pl2 = List.length pl2 in
+ let impl_list = if len_pl1 = 0
+ then select_impargs_size len_pl2 impls_st
+ else list_skipn_at_least len_pl1 (select_stronger_impargs impls_st) in
+ let allscs = find_arguments_scope ref in
+ let scope_list = list_skipn_at_least len_pl1 allscs in
+ let rec aux = function
+ |[],l -> l
+ |_,[] -> []
+ |h::t,_::tt when is_status_implicit h -> aux (t,tt)
+ |_::t,h::tt -> h :: aux (t,tt)
+ in ((try list_firstn len_pl1 allscs with Failure _ -> simple_adjust_scopes len_pl1 allscs),
+ simple_adjust_scopes len_pl2 (aux (impl_list,scope_list)))
let product_of_cases_patterns ids idspl =
List.fold_right (fun (ids,pl) (ids',ptaill) ->
@@ -779,7 +792,9 @@ let simple_product_of_cases_patterns pl =
List.map (fun (subst',ptail) -> (subst@subst',p::ptail)) ptaill) pl))
pl [[],[]]
-(* Check linearity of pattern-matching *)
+(* @return the first variable that occurs twice in a pattern
+
+naive n2 algo *)
let rec has_duplicate = function
| [] -> None
| x::l -> if List.mem x l then (Some x) else has_duplicate l
@@ -804,246 +819,77 @@ let check_or_pat_variables loc ids idsl =
user_err_loc (loc, "", str
"The components of this disjunctive pattern must bind the same variables.")
-(** @param with_params says if _ for params were asked to the user.
+(** Use only when params were NOT asked to the user.
@return if letin are included *)
-let check_constructor_length env loc cstr with_params pl pl0 =
+let check_constructor_length env loc cstr len_pl pl0 =
let nargs = Inductiveops.mis_constructor_nargs cstr in
- let n = List.length pl + List.length pl0 in
+ let n = len_pl + List.length pl0 in
if n = nargs then false else
(n = (fst (Inductiveops.inductive_nargs (fst cstr))) + Inductiveops.constructor_nrealhyps cstr) ||
(error_wrong_numarg_constructor_loc loc env cstr
- (if with_params then nargs else nargs - (Inductiveops.inductive_nparams (fst cstr))))
+ (nargs - (Inductiveops.inductive_nparams (fst cstr))))
-let add_implicits_check_length nargs impls_st len_pl1 pl2 fail =
+let add_implicits_check_length fail nargs nargs_with_letin impls_st len_pl1 pl2 =
let impl_list = if len_pl1 = 0
then select_impargs_size (List.length pl2) impls_st
- else snd (list_chop len_pl1 (select_stronger_impargs impls_st)) in
+ else list_skipn_at_least len_pl1 (select_stronger_impargs impls_st) in
let remaining_args = List.fold_left (fun i x -> if is_status_implicit x then i else succ i) in
let rec aux i = function
|[],l -> let args_len = List.length l + List.length impl_list + len_pl1 in
- if args_len = nargs then l
- else fail (nargs - List.length impl_list + i)
- |imp::q,l when is_status_implicit imp -> CPatAtom(dummy_loc,None):: aux i (q,l)
- |il,[] -> fail (remaining_args (len_pl1+i) il)
- |_::q,hh::tt -> hh::aux (succ i) (q,tt)
+ ((if args_len = nargs then false
+ else args_len = nargs_with_letin || (fst (fail (nargs - List.length impl_list + i))))
+ ,l)
+ |imp::q as il,[] -> if is_status_implicit imp && maximal_insertion_of imp
+ then let (b,out) = aux i (q,[]) in (b,RCPatAtom(dummy_loc,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,RCPatAtom(dummy_loc,None)::out)
+ else let (b,out) = aux (succ i) (q,tt) in (b,hh::out)
in aux 0 (impl_list,pl2)
-let add_implicits_check_constructor_length env loc c idslpl1 pl2 =
+let add_implicits_check_constructor_length env loc c len_pl1 pl2 =
let nargs = Inductiveops.mis_constructor_nargs c in
- let len_pl1 = List.length idslpl1 in
+ let nargs' = (fst (Inductiveops.inductive_nargs (fst c)))
+ + Inductiveops.constructor_nrealhyps c in
let impls_st = implicits_of_global (ConstructRef c) in
- add_implicits_check_length nargs impls_st len_pl1 pl2
- (error_wrong_numarg_constructor_loc loc env c)
+ add_implicits_check_length (error_wrong_numarg_constructor_loc loc env c)
+ nargs nargs' impls_st len_pl1 pl2
-(** @return if the letin are include *)
-let check_ind_length env loc ind pl pl0 =
- let (mib,mip) = Global.lookup_inductive ind in
- let nparams = mib.Declarations.mind_nparams in
- let nargs = mip.Declarations.mind_nrealargs + nparams in
- let n = List.length pl + List.length pl0 in
- if n = nargs then false else
- let nparams', nrealargs' = inductive_nargs_env env ind in
- let nargs' = nrealargs' + nparams' in
- n = nargs' ||
- (error_wrong_numarg_inductive_loc loc env ind nargs)
-
-let add_implicits_check_ind_length env loc c idslpl1 pl2 =
+let add_implicits_check_ind_length env loc c len_pl1 pl2 =
let (mib,mip) = Global.lookup_inductive c in
let nparams = mib.Declarations.mind_nparams in
let nargs = mip.Declarations.mind_nrealargs + nparams in
- let len_pl1 = List.length idslpl1 in
+ let nparams', nrealargs' = inductive_nargs_env env c in
let impls_st = implicits_of_global (IndRef c) in
- add_implicits_check_length nargs impls_st len_pl1 pl2
- (error_wrong_numarg_inductive_loc loc env c)
-(* Manage multiple aliases *)
+ add_implicits_check_length (error_wrong_numarg_inductive_loc loc env c)
+ nargs (nrealargs' + nparams') impls_st len_pl1 pl2
- (* [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 (ids,asubst as _aliases) id =
- ids@[id], if ids=[] then asubst else (id, List.hd ids)::asubst
-
-let alias_of = function
- | ([],_) -> Anonymous
- | (id::_,_) -> Name id
-
-let message_redundant_alias (id1,id2) =
- if_warn msg_warning
- (str "Alias variable " ++ pr_id id1 ++ str " is merged with " ++ pr_id id2)
-
-(* Expanding notations *)
-
-let rec subst_pat_iterator y t (subst,p) = match p with
- | PatVar (_,id) as x ->
- if id = Name y then t else [subst,x]
- | PatCstr (loc,id,l,alias) ->
- let l' = List.map (fun a -> (subst_pat_iterator y t ([],a))) l in
- let pl = simple_product_of_cases_patterns l' in
- List.map (fun (subst',pl) -> subst'@subst,PatCstr (loc,id,pl,alias)) pl
-
-(** @raise NotEnoughArguments only in the case of [subst_cases_pattern] thanks to
- preconditions in other cases. *)
+(** Do not raise NotEnoughArguments thanks to preconditions*)
let chop_params_pattern loc ind args with_letin =
let nparams = if with_letin
then fst (Inductiveops.inductive_nargs ind)
else Inductiveops.inductive_nparams ind in
- if nparams > List.length args then error_not_enough_arguments loc;
+ assert (nparams <= List.length args);
let params,args = list_chop nparams args in
List.iter (function PatVar(_,Anonymous) -> ()
| PatVar (loc',_) | PatCstr(loc',_,_,_) -> error_parameter_not_implicit loc') params;
args
-let subst_cases_pattern loc alias intern fullsubst env a =
- let rec aux alias (subst,substlist as fullsubst) = function
- | NVar id ->
- begin
- (* subst remembers the delimiters stack in the interpretation *)
- (* of the notations *)
- try
- let (a,(scopt,subscopes)) = List.assoc id subst in
- intern {env with scopes=subscopes@env.scopes;
- tmp_scope = scopt} ([],[]) a
- with Not_found ->
- if id = ldots_var then [], [[], PatVar (loc,Name id)] else
- anomaly ("Unbound pattern notation variable: "^(string_of_id id))
- (*
- (* Happens for local notation joint with inductive/fixpoint defs *)
- if aliases <> ([],[]) then
- anomaly "Pattern notation without constructors";
- [[id],[]], PatVar (loc,Name id)
- *)
- end
- | NRef (ConstructRef c) ->
- ([],[[], PatCstr (loc,c, [], alias)])
- | NApp (NRef (ConstructRef cstr),args) ->
- let idslpll = List.map (aux Anonymous fullsubst) args in
- let ids',pll = product_of_cases_patterns [] idslpll in
- let pl' = List.map (fun (asubst,pl) ->
- asubst,PatCstr (loc,cstr,chop_params_pattern loc (fst cstr) pl false,alias)) pll in
- ids', pl'
- | NList (x,_,iter,terminator,lassoc) ->
- (try
- (* All elements of the list are in scopes (scopt,subscopes) *)
- let (l,(scopt,subscopes)) = List.assoc x substlist in
- let termin = aux Anonymous fullsubst terminator in
- let idsl,v =
- List.fold_right (fun a (tids,t) ->
- let uids,u = aux Anonymous ((x,(a,(scopt,subscopes)))::subst,substlist) iter in
- let pll = List.map (subst_pat_iterator ldots_var t) u in
- tids@uids, List.flatten pll)
- (if lassoc then List.rev l else l) termin in
- idsl, List.map (fun ((asubst, pl) as x) ->
- match pl with PatCstr (loc, c, pl, Anonymous) -> (asubst, PatCstr (loc, c, pl, alias)) | _ -> x) v
- with Not_found ->
- anomaly "Inconsistent substitution of recursive notation")
- | NHole _ -> ([],[[], PatVar (loc,Anonymous)])
- | t -> error_invalid_pattern_notation loc
- in aux alias fullsubst a
-
-let subst_ind_pattern loc intern_ind_patt intern (subst,_ as fullsubst) env = function
- | NVar id ->
- begin
- (* subst remembers the delimiters stack in the interpretation *)
- (* of the notations *)
- try
- let (a,(scopt,subscopes)) = List.assoc id subst in
- intern_ind_patt {env with scopes=subscopes@env.scopes;
- tmp_scope = scopt} a
- with Not_found ->
- anomaly ("Unbound pattern notation variable: "^(string_of_id id))
- end
- | NRef (IndRef c) ->
- false, (c, [])
- | NApp (NRef (IndRef ind),args) ->
- let idslpll = List.map (subst_cases_pattern loc Anonymous intern fullsubst env) args in
- begin
- match product_of_cases_patterns [] idslpll with
- |_,[_,pl]->
- let pl' = chop_params_pattern loc ind pl false in
- false, (ind,pl')
- |_ -> error_invalid_pattern_notation loc
- end
- | t -> error_invalid_pattern_notation loc
-
-
-(* Differentiating between constructors and matching variables *)
-type pattern_qualid_kind =
- | ConstrPat of constructor * (identifier list *
- ((identifier * identifier) list * cases_pattern) list) list
- | VarPat of identifier
-
-let find_at_head looked_for add_params ref f pats env =
- let (loc,qid) = qualid_of_reference ref in
- let gref =
- try locate_extended qid
- with Not_found -> raise (InternalizationError (loc,NotAConstructor ref)) in
- match gref with
- | SynDef sp ->
- let (vars,a) = Syntax_def.search_syntactic_definition sp in
- (match a with
- | NRef g ->
- let cstr = looked_for g in
- assert (vars=[]);
- cstr,add_params cstr, pats
- | NApp (NRef g,args) ->
- let cstr = looked_for g in
- let nvars = List.length vars in
- if List.length pats < nvars then error_not_enough_arguments loc;
- let pats1,pats2 = list_chop nvars pats in
- let subst = List.map2 (fun (id,scl) a -> (id,(a,scl))) vars pats1 in
- let idspl1 = List.map (subst_cases_pattern loc Anonymous f (subst,[]) env) args in
- cstr, idspl1, pats2
- | _ -> raise Not_found)
-
- | TrueGlobal r ->
- let rec unf = function
- | ConstRef cst ->
- let v = Environ.constant_value (Global.env()) cst in
- unf (global_of_constr v)
- | g ->
- let cstr = looked_for g in
- Dumpglob.add_glob loc r;
- cstr, add_params cstr, pats
- in unf r
-
-let find_constructor add_params =
- find_at_head (function ConstructRef cstr -> cstr |_ -> raise Not_found)
- (function (ind,_ as c) -> match add_params with
- |Some nb_args -> let nb = if nb_args = Inductiveops.constructor_nrealhyps c
- then fst (Inductiveops.inductive_nargs ind)
- else Inductiveops.inductive_nparams ind in
- Util.list_make nb ([],[([],PatVar(dummy_loc,Anonymous))])
- |None -> [])
-
+let find_constructor loc add_params ref =
+ let cstr = (function ConstructRef cstr -> cstr
+ |IndRef _ -> user_err_loc (loc,"find_constructor",str "There is an inductive name deep in a \"in\" clause.")
+ |_ -> anomaly "unexpected global_reference in pattern") ref in
+ cstr, (function (ind,_ as c) -> match add_params with
+ |Some nb_args -> let nb = if nb_args = Inductiveops.constructor_nrealhyps c
+ then fst (Inductiveops.inductive_nargs ind)
+ else Inductiveops.inductive_nparams ind in
+ Util.list_make nb ([],[([],PatVar(dummy_loc,Anonymous))])
+ |None -> []) cstr
let find_pattern_variable = function
| Ident (loc,id) -> id
| Qualid (loc,_) as x -> raise (InternalizationError(loc,NotAConstructor x))
-let maybe_constructor add_params ref f env =
- try
- let c,idspl1,pl2 = find_constructor add_params ref f [] env in
- assert (pl2 = []);
- ConstrPat (c,idspl1)
- with
- (* patt var does not exists globally *)
- | InternalizationError _ -> VarPat (find_pattern_variable ref)
- (* patt var also exists globally but does not satisfy preconditions *)
- | (Environ.NotEvaluableConst _ | Not_found) ->
- if_warn msg_warning (str "pattern " ++ pr_reference ref ++
- str " is understood as a pattern variable");
- VarPat (find_pattern_variable ref)
-
-let mustbe_constructor loc add_params ref f patl env =
- try find_constructor add_params ref f patl env
- with (Environ.NotEvaluableConst _ | Not_found) ->
- raise (InternalizationError (loc,NotAConstructor ref))
-
-let mustbe_inductive loc ref f patl env =
- try find_at_head (function IndRef ind -> ind|_ -> raise Not_found) (function _ -> []) ref f patl env
- with (Environ.NotEvaluableConst _ | Not_found|
- InternalizationError (_,NotAConstructor _)) ->
- error_bad_inductive_type loc
-
let sort_fields mode loc l completer =
(*mode=false if pattern and true if constructor*)
match l with
@@ -1133,124 +979,225 @@ let sort_fields mode loc l completer =
Some (nparams, base_constructor,
List.rev (clean_list sorted_indexed_pattern 0 []))
-let rec intern_cases_pattern genv env (ids,asubst as aliases) pat =
- let intern_pat = intern_cases_pattern genv in
+(** {6 Manage multiple aliases} *)
+
+ (* [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 (ids,asubst as _aliases) id =
+ ids@[id], if ids=[] then asubst else (id, List.hd ids)::asubst
+
+let alias_of = function
+ | ([],_) -> Anonymous
+ | (id::_,_) -> Name id
+
+let message_redundant_alias (id1,id2) =
+ if_warn msg_warning
+ (str "Alias variable " ++ pr_id id1 ++ str " is merged with " ++ pr_id id2)
+
+(** {6 Expanding notations }
+
+ @returns a raw_case_pattern_expr :
+ - no notations and syntactic definition
+ - global reference and identifeir instead of reference
+
+*)
+
+let rec subst_pat_iterator y t p = match p with
+ | RCPatAtom (_,id) ->
+ begin match id with Some x when x = y -> t |_ -> p end
+ | RCPatCstr (loc,id,l1,l2) ->
+ RCPatCstr (loc,id,List.map (subst_pat_iterator y t) l1,
+ List.map (subst_pat_iterator y t) l2)
+ | RCPatAlias (l,p,a) -> RCPatAlias (l,subst_pat_iterator y t p,a)
+ | RCPatOr (l,pl) -> RCPatOr (l,List.map (subst_pat_iterator y t) pl)
+
+let drop_notations_pattern looked_for =
+ let rec drop_syndef env re pats =
+ let (loc,qid) = qualid_of_reference re in
+ try
+ match locate_extended qid with
+ |SynDef sp ->
+ let (vars,a) = Syntax_def.search_syntactic_definition sp in
+ (match a with
+ | NRef g ->
+ looked_for g;
+ let () = assert (vars = []) in
+ let (_,argscs) = find_remaining_scopes [] pats g in
+ Some (g, [], List.map2 (in_pat_sc env) argscs pats)
+ | NApp (NRef g,[]) -> (* special case : Syndef for @Cstr *)
+ looked_for g;
+ let () = assert (vars = []) in
+ let (argscs,_) = find_remaining_scopes pats [] g in
+ Some (g, List.map2 (in_pat_sc env) argscs pats, [])
+ | NApp (NRef g,args) ->
+ looked_for g;
+ let nvars = List.length vars in
+ if List.length pats < nvars then error_not_enough_arguments loc;
+ let pats1,pats2 = list_chop nvars pats in
+ let subst = List.map2 (fun (id,scl) a -> (id,(a,scl))) vars pats1 in
+ let idspl1 = List.map (in_not loc env (subst,[]) []) args in
+ let (_,argscs) = find_remaining_scopes pats1 pats2 g in
+ Some (g, idspl1, List.map2 (in_pat_sc env) argscs pats2)
+ | _ -> raise Not_found)
+ |TrueGlobal g ->
+ looked_for g;
+ Dumpglob.add_glob loc g;
+ let (_,argscs) = find_remaining_scopes [] pats g in
+ Some (g,[],List.map2 (fun x -> in_pat {env with tmp_scope = x}) argscs pats)
+ with Not_found -> None
+ and in_pat env = function
+ | CPatAlias (loc, p, id) -> RCPatAlias (loc, in_pat env p, id)
+ | CPatRecord (loc, l) ->
+ let sorted_fields =
+ sort_fields false loc l (fun _ l -> (CPatAtom (loc, None))::l) in
+ begin match sorted_fields with
+ | None -> RCPatAtom (loc, None)
+ | Some (_, head, pl) ->
+ match drop_syndef env head pl with
+ |Some (a,b,c) -> RCPatCstr(loc, a, b, c)
+ |None -> raise (InternalizationError (loc,NotAConstructor head))
+ end
+ | CPatCstr (loc, head, [], pl) ->
+ begin
+ match drop_syndef env head pl with
+ | Some (a,b,c) -> RCPatCstr(loc, a, b, c)
+ | None -> raise (InternalizationError (loc,NotAConstructor head))
+ end
+ | CPatCstr (loc, r, expl_pl, pl) ->
+ let g = try
+ (locate (snd (qualid_of_reference r)))
+ with Not_found ->
+ raise (InternalizationError (loc,NotAConstructor r)) in
+ let (argscs1,argscs2) = find_remaining_scopes expl_pl pl g in
+ RCPatCstr (loc, g, List.map2 (in_pat_sc env) argscs1 expl_pl, List.map2 (in_pat_sc env) argscs2 pl)
+ | CPatNotation (loc,"- _",([CPatPrim(_,Numeral p)],[]),[])
+ when Bigint.is_strictly_pos p ->
+ fst (Notation.interp_prim_token_cases_pattern_expr loc looked_for (Numeral (Bigint.neg p))
+ (env.tmp_scope,env.scopes))
+ | CPatNotation (_,"( _ )",([a],[]),[]) ->
+ in_pat env a
+ | CPatNotation (loc, ntn, fullargs,extrargs) ->
+ let ntn,(args,argsl as fullargs) = contract_pat_notation ntn fullargs in
+ let ((ids',c),df) = Notation.interp_notation loc ntn (env.tmp_scope,env.scopes) in
+ let (ids',idsl',_) = split_by_type ids' in
+ Dumpglob.dump_notation_location (patntn_loc loc fullargs ntn) ntn df;
+ let subst = List.map2 (fun (id,scl) a -> (id,(a,scl))) ids' args in
+ let substlist = List.map2 (fun (id,scl) a -> (id,(a,scl))) idsl' argsl in
+ in_not loc env (subst,substlist) extrargs c
+ | CPatDelimiters (loc, key, e) ->
+ in_pat {env with scopes=find_delimiters_scope loc key::env.scopes;
+ tmp_scope = None} e
+ | CPatPrim (loc,p) -> fst (Notation.interp_prim_token_cases_pattern_expr loc looked_for p
+ (env.tmp_scope,env.scopes))
+ | CPatAtom (loc, Some id) ->
+ begin
+ match drop_syndef env id [] with
+ |Some (a,b,c) -> RCPatCstr (loc, a, b, c)
+ |None -> RCPatAtom (loc, Some (find_pattern_variable id))
+ end
+ | CPatAtom (loc,None) -> RCPatAtom (loc,None)
+ | CPatOr (loc, pl) ->
+ RCPatOr (loc,List.map (in_pat env) pl)
+ and in_pat_sc env x = in_pat {env with tmp_scope = x}
+ and in_not loc env (subst,substlist as fullsubst) args = function
+ | NVar id ->
+ assert (args = []);
+ begin
+ (* subst remembers the delimiters stack in the interpretation *)
+ (* of the notations *)
+ try
+ let (a,(scopt,subscopes)) = List.assoc id subst in
+ in_pat {env with scopes=subscopes@env.scopes;
+ tmp_scope = scopt} a
+ with Not_found ->
+ if id = ldots_var then RCPatAtom (loc,Some id) else
+ anomaly ("Unbound pattern notation variable: "^(string_of_id id))
+ end
+ | NRef g ->
+ looked_for g;
+ let (_,argscs) = find_remaining_scopes [] args g in
+ RCPatCstr (loc, g, [], List.map2 (in_pat_sc env) argscs args)
+ | NApp (NRef g,pl) ->
+ looked_for g;
+ let (argscs1,argscs2) = find_remaining_scopes pl args g in
+ RCPatCstr (loc, g,
+ List.map2 (fun x -> in_not loc {env with tmp_scope = x} fullsubst []) argscs1 pl,
+ List.map2 (in_pat_sc env) argscs2 args)
+ | NList (x,_,iter,terminator,lassoc) ->
+ let () = assert (args = []) in
+ (try
+ (* All elements of the list are in scopes (scopt,subscopes) *)
+ let (l,(scopt,subscopes)) = List.assoc x substlist in
+ let termin = in_not loc env fullsubst [] terminator in
+ List.fold_right (fun a t ->
+ let u = in_not loc env ((x,(a,(scopt,subscopes)))::subst,substlist) [] iter in
+ subst_pat_iterator ldots_var t u)
+ (if lassoc then List.rev l else l) termin
+ with Not_found ->
+ anomaly "Inconsistent substitution of recursive notation")
+ | NHole _ -> let () = assert (args = []) in RCPatAtom (loc,None)
+ | t -> error_invalid_pattern_notation loc
+ in in_pat
+
+let rec intern_pat genv (ids,asubst as aliases) pat =
let intern_cstr_with_all_args loc c with_letin idslpl1 pl2 =
- let argscs2 = find_remaining_scopes idslpl1 pl2 (ConstructRef c) in
- let idslpl2 = List.map2 (fun x -> intern_pat {env with tmp_scope = x} ([],[])) argscs2 pl2 in
+ let idslpl2 = List.map (intern_pat genv ([],[])) pl2 in
let (ids',pll) = product_of_cases_patterns ids (idslpl1@idslpl2) in
let pl' = List.map (fun (asubst,pl) ->
(asubst, PatCstr (loc,c,chop_params_pattern loc (fst c) pl with_letin,alias_of aliases))) pll in
ids',pl' in
match pat with
- | CPatAlias (loc, p, id) ->
+ | RCPatAlias (loc, p, id) ->
let aliases' = merge_aliases aliases id in
- intern_pat env aliases' p
- | CPatRecord (loc, l) ->
- let sorted_fields = sort_fields false loc l (fun _ l -> (CPatAtom (loc, None))::l) in
- let self_patt =
- match sorted_fields with
- | None -> CPatAtom (loc, None)
- | Some (_, head, pl) -> CPatCstr(loc, head, pl)
- in
- intern_pat env aliases self_patt
- | CPatCstr (loc, head, pl) ->
+ intern_pat genv aliases' p
+ | RCPatCstr (loc, head, expl_pl, pl) ->
if !oldfashion_patterns then
- let c,idslpl1,pl2 = mustbe_constructor loc (Some (List.length pl)) head intern_pat pl env in
- let with_letin = check_constructor_length genv loc c false idslpl1 pl2 in
- intern_cstr_with_all_args loc c with_letin idslpl1 pl2
+ let c,idslpl1 = find_constructor loc (if expl_pl = [] then Some (List.length pl) else None) head in
+ let with_letin =
+ 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@pl)
else
- let c,idslpl1,pl2 = mustbe_constructor loc None head intern_pat pl env in
- let pl2' = add_implicits_check_constructor_length genv loc c idslpl1 pl2 in
- intern_cstr_with_all_args loc c false idslpl1 pl2'
- | CPatCstrExpl (loc, head, pl) ->
- let c,idslpl1,pl2 = mustbe_constructor loc None head intern_pat pl env in
- let with_letin = check_constructor_length genv loc c true idslpl1 pl2 in
- intern_cstr_with_all_args loc c with_letin idslpl1 pl2
- | CPatNotation (loc,"- _",([CPatPrim(_,Numeral p)],[]))
- when Bigint.is_strictly_pos p ->
- intern_pat env aliases (CPatPrim(loc,Numeral(Bigint.neg p)))
- | CPatNotation (_,"( _ )",([a],[])) ->
- intern_pat env aliases a
- | CPatNotation (loc, ntn, fullargs) ->
- let ntn,(args,argsl as fullargs) = contract_pat_notation ntn fullargs in
- let ((ids',c),df) = Notation.interp_notation loc ntn (env.tmp_scope,env.scopes) in
- let (ids',idsl',_) = split_by_type ids' in
- Dumpglob.dump_notation_location (patntn_loc loc fullargs ntn) ntn df;
- let subst = List.map2 (fun (id,scl) a -> (id,(a,scl))) ids' args in
- let substlist = List.map2 (fun (id,scl) a -> (id,(a,scl))) idsl' argsl in
- let ids'',pl =
- subst_cases_pattern loc (alias_of aliases) intern_pat (subst,substlist)
- env c
- in ids@ids'', pl
- | CPatPrim (loc, p) ->
- let a = alias_of aliases in
- let (c,_) = Notation.interp_prim_token_cases_pattern loc p a
- (env.tmp_scope,env.scopes) in
- (ids,[asubst,c])
- | CPatDelimiters (loc, key, e) ->
- intern_pat {env with scopes=find_delimiters_scope loc key::env.scopes;
- tmp_scope = None} aliases e
- | CPatAtom (loc, Some head) ->
- (match maybe_constructor (if !oldfashion_patterns then Some 0 else None)
- head intern_pat env with
- | ConstrPat (c,idspl) ->
- if !oldfashion_patterns then
- let with_letin = check_constructor_length genv loc c false idspl [] in
- intern_cstr_with_all_args loc c with_letin idspl []
- else
- let pl2 = add_implicits_check_constructor_length genv loc c idspl [] in
- intern_cstr_with_all_args loc c false idspl pl2
- | VarPat id ->
- let ids,asubst = merge_aliases aliases id in
- (ids,[asubst, PatVar (loc,alias_of (ids,asubst))]))
- | CPatAtom (loc, None) ->
+ let c,idslpl1 = find_constructor loc None head in
+ 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 (loc, Some id) ->
+ let ids,asubst = merge_aliases aliases id in
+ (ids,[asubst, PatVar (loc,alias_of (ids,asubst))])
+ | RCPatAtom (loc, None) ->
(ids,[asubst, PatVar (loc,alias_of aliases)])
- | CPatOr (loc, pl) ->
+ | RCPatOr (loc, pl) ->
assert (pl <> []);
- let pl' = List.map (intern_pat env aliases) pl in
+ let pl' = List.map (intern_pat genv 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 rec intern_ind_pattern genv env pat =
- let intern_ind_with_all_args loc c idslpl1 pl2 =
- let argscs2 = find_remaining_scopes idslpl1 pl2 (IndRef c) in
- let idslpl2 = List.map2 (fun x -> intern_cases_pattern genv {env with tmp_scope = x} ([],[])) argscs2 pl2 in
- match product_of_cases_patterns [] (idslpl1@idslpl2) with
- |_,[_,pl] ->
- (c,chop_params_pattern loc c pl false)
- |_ -> error_bad_inductive_type loc
- in
- match pat with
- | CPatCstr (loc, head, pl) ->
- let c,idslpl1,pl2 = mustbe_inductive loc head (intern_cases_pattern genv) pl env in
- let pl2' = add_implicits_check_ind_length genv loc c idslpl1 pl2 in
- false,intern_ind_with_all_args loc c idslpl1 pl2'
- | CPatCstrExpl (loc, head, pl) ->
- let c,idslpl1,pl2 = mustbe_inductive loc head (intern_cases_pattern genv) pl env in
- let with_letin = check_ind_length genv loc c idslpl1 pl2 in
- with_letin,intern_ind_with_all_args loc c idslpl1 pl2
- | CPatNotation (_,"( _ )",([a],[])) ->
- intern_ind_pattern genv env a
- | CPatNotation (loc, ntn, fullargs) ->
- let ntn,(args,argsl as fullargs) = contract_pat_notation ntn fullargs in
- let ((ids',c),df) = Notation.interp_notation loc ntn (env.tmp_scope,env.scopes) in
- let (ids',idsl',_) = split_by_type ids' in
- Dumpglob.dump_notation_location (patntn_loc loc fullargs ntn) ntn df;
- let subst = List.map2 (fun (id,scl) a -> (id,(a,scl))) ids' args in
- let substlist = List.map2 (fun (id,scl) a -> (id,(a,scl))) idsl' argsl in
- subst_ind_pattern loc (intern_ind_pattern genv) (intern_cases_pattern genv) (subst,substlist)
- env c
- | CPatDelimiters (loc, key, e) ->
- intern_ind_pattern genv {env with scopes=find_delimiters_scope loc key::env.scopes;
- tmp_scope = None} e
- | CPatAtom (loc, Some head) ->
- let c,idslpl1,pl2 = mustbe_inductive loc head (intern_cases_pattern genv) [] env in
- let with_letin = check_ind_length genv loc c idslpl1 pl2 in
- with_letin,intern_ind_with_all_args loc c idslpl1 pl2
- | x -> error_bad_inductive_type (cases_pattern_expr_loc x)
+let intern_cases_pattern genv env aliases pat =
+ intern_pat genv aliases
+ (drop_notations_pattern (function ConstructRef _ -> () |_ -> raise Not_found) env pat)
+
+let intern_ind_pattern genv env pat =
+ let no_not =
+ try
+ drop_notations_pattern (function (IndRef _ | ConstructRef _) -> () |_ -> raise Not_found) env pat
+ with InternalizationError(loc,NotAConstructor _) -> error_bad_inductive_type loc
+ in
+ match no_not with
+ | RCPatCstr (loc, head,expl_pl, pl) ->
+ 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 ([],[])) expl_pl in
+ let idslpl2 = List.map (intern_pat genv ([],[])) pl2 in
+ (with_letin,
+ match product_of_cases_patterns [] (List.rev_append idslpl1 idslpl2) with
+ |_,[_,pl] ->
+ (c,chop_params_pattern loc c pl with_letin)
+ |_ -> error_bad_inductive_type loc)
+ | x -> error_bad_inductive_type (raw_cases_pattern_expr_loc x)
(**********************************************************************)
(* Utilities for application *)
diff --git a/interp/notation.ml b/interp/notation.ml
index 2430b980c..a76ede48c 100644
--- a/interp/notation.ml
+++ b/interp/notation.ml
@@ -372,8 +372,8 @@ let interp_prim_token_gen g loc p local_scopes =
let interp_prim_token =
interp_prim_token_gen (fun x -> x)
-let interp_prim_token_cases_pattern loc p name =
- interp_prim_token_gen (cases_pattern_of_glob_constr name) loc p
+let interp_prim_token_cases_pattern_expr loc looked_for p =
+ interp_prim_token_gen (Constrexpr_ops.raw_cases_pattern_expr_of_glob_constr looked_for) loc p
let rec interp_notation loc ntn local_scopes =
let scopes = make_current_scopes local_scopes in
diff --git a/interp/notation.mli b/interp/notation.mli
index 7629d86e7..3f66f993a 100644
--- a/interp/notation.mli
+++ b/interp/notation.mli
@@ -84,8 +84,8 @@ val declare_string_interpreter : scope_name -> required_module ->
val interp_prim_token : loc -> prim_token -> local_scopes ->
glob_constr * (notation_location * scope_name option)
-val interp_prim_token_cases_pattern : loc -> prim_token -> name ->
- local_scopes -> cases_pattern * (notation_location * scope_name option)
+val interp_prim_token_cases_pattern_expr : loc -> (global_reference -> unit) -> prim_token ->
+ local_scopes -> raw_cases_pattern_expr * (notation_location * scope_name option)
(** Return the primitive token associated to a [term]/[cases_pattern];
raise [No_match] if no such token *)
diff --git a/interp/topconstr.ml b/interp/topconstr.ml
index 9b3c00bf2..bc9d3b851 100644
--- a/interp/topconstr.ml
+++ b/interp/topconstr.ml
@@ -47,7 +47,8 @@ let error_invalid_pattern_notation loc =
let ids_of_cases_indtype =
let rec vars_of ids = function
(* We deal only with the regular cases *)
- | (CPatCstr (_,_,l)|CPatCstrExpl (_, _, l)|CPatNotation (_,_,(l,[]))) -> List.fold_left vars_of [] l
+ | (CPatCstr (_,_,l1,l2)|CPatNotation (_,_,(l1,[]),l2)) ->
+ List.fold_left vars_of (List.fold_left vars_of [] l2) l1
(* assume the ntn is applicative and does not instantiate the head !! *)
| CPatDelimiters(_,_,c) -> vars_of ids c
| CPatAtom (_, Some (Libnames.Ident (_, x))) -> x::ids
@@ -69,10 +70,14 @@ let rec cases_pattern_fold_names f a = function
| CPatRecord (_, l) ->
List.fold_left (fun acc (r, cp) -> cases_pattern_fold_names f acc cp) a l
| CPatAlias (_,pat,id) -> f id a
- | CPatCstr (_,_,patl) | CPatCstrExpl (_,_,patl) | CPatOr (_,patl) ->
+ | CPatOr (_,patl) ->
List.fold_left (cases_pattern_fold_names f) a patl
- | CPatNotation (_,_,(patl,patll)) ->
- List.fold_left (cases_pattern_fold_names f) a (patl@List.flatten patll)
+ | CPatCstr (_,_,patl1,patl2) ->
+ List.fold_left (cases_pattern_fold_names f)
+ (List.fold_left (cases_pattern_fold_names f) a patl1) patl2
+ | CPatNotation (_,_,(patl,patll),patl') ->
+ List.fold_left (cases_pattern_fold_names f)
+ (List.fold_left (cases_pattern_fold_names f) a (patl@List.flatten patll)) patl'
| CPatDelimiters (_,_,pat) -> cases_pattern_fold_names f a pat
| CPatAtom (_,Some (Ident (_,id))) when not (is_constructor id) -> f id a
| CPatPrim _ | CPatAtom _ -> a
diff --git a/intf/constrexpr.mli b/intf/constrexpr.mli
index f6d274abb..605be512c 100644
--- a/intf/constrexpr.mli
+++ b/intf/constrexpr.mli
@@ -35,13 +35,25 @@ type proj_flag = int option (** [Some n] = proj of the n-th visible argument *)
type prim_token = Numeral of Bigint.bigint | String of string
+type raw_cases_pattern_expr =
+ | RCPatAlias of loc * raw_cases_pattern_expr * identifier
+ | RCPatCstr of loc * Globnames.global_reference
+ * raw_cases_pattern_expr list * raw_cases_pattern_expr list
+ (** [CPatCstr (_, Inl c, l1, l2)] represents (@c l1) l2 *)
+ | RCPatAtom of loc * identifier option
+ | RCPatOr of loc * raw_cases_pattern_expr list
+
type cases_pattern_expr =
| CPatAlias of loc * cases_pattern_expr * identifier
- | CPatCstr of loc * reference * cases_pattern_expr list
- | CPatCstrExpl of loc * reference * cases_pattern_expr list
+ | CPatCstr of loc * reference
+ * cases_pattern_expr list * cases_pattern_expr list
+ (** [CPatCstr (_, Inl c, l1, l2)] represents (@c l1) l2 *)
| CPatAtom of loc * reference option
| CPatOr of loc * cases_pattern_expr list
| CPatNotation of loc * notation * cases_pattern_notation_substitution
+ * cases_pattern_expr list (** CPatNotation (_, n, l1 ,l2) represents
+ (notation n applied with substitution l1)
+ applied to arguments l2 *)
| CPatPrim of loc * prim_token
| CPatRecord of loc * (reference * cases_pattern_expr) list
| CPatDelimiters of loc * string * cases_pattern_expr
diff --git a/parsing/egramcoq.ml b/parsing/egramcoq.ml
index ee8ec009d..323da812d 100644
--- a/parsing/egramcoq.ml
+++ b/parsing/egramcoq.ml
@@ -198,7 +198,7 @@ let extend_constr_notation (n,assoc,ntn,rules) =
let e = interp_constr_entry_key false (ETConstr (n,())) in
let nb = extend_constr e (ETConstr(n,()),assoc) (make_constr_action mkact) false rules in
(* Add the notation in cases_pattern *)
- let mkact loc env = CPatNotation (loc,ntn,env) in
+ let mkact loc env = CPatNotation (loc,ntn,env,[]) in
let e = interp_constr_entry_key true (ETConstr (n,())) in
let nb' = extend_constr e (ETConstr (n,()),assoc) (make_cases_pattern_action mkact)
true rules in
diff --git a/parsing/g_constr.ml4 b/parsing/g_constr.ml4
index ca462a702..f53cab6c6 100644
--- a/parsing/g_constr.ml4
+++ b/parsing/g_constr.ml4
@@ -344,12 +344,14 @@ GEXTEND Gram
| "9" RIGHTA
[ p = pattern; lp = LIST1 NEXT ->
(match p with
- | CPatAtom (_, Some r) -> CPatCstr (loc, r, lp)
+ | CPatAtom (_, Some r) -> CPatCstr (loc, r, [], lp)
+ | CPatCstr (_, r, l1, l2) -> CPatCstr (loc, r, l1 , l2@lp)
+ | CPatNotation (_, n, s, l) -> CPatNotation (loc, n , s, l@lp)
| _ -> Errors.user_err_loc
(cases_pattern_expr_loc p, "compound_pattern",
- Pp.str "Constructor expected."))
+ Pp.str "Such pattern cannot have arguments."))
|"@"; r = Prim.reference; lp = LIST1 NEXT ->
- CPatCstrExpl (loc, r, lp) ]
+ CPatCstr (loc, r, lp, []) ]
| "1" LEFTA
[ c = pattern; "%"; key=IDENT -> CPatDelimiters (loc,key,c) ]
| "0"
@@ -359,7 +361,7 @@ GEXTEND Gram
| "("; p = pattern LEVEL "200"; ")" ->
(match p with
CPatPrim (_,Numeral z) when Bigint.is_pos_or_zero z ->
- CPatNotation(loc,"( _ )",([p],[]))
+ CPatNotation(loc,"( _ )",([p],[]),[])
| _ -> p)
| n = INT -> CPatPrim (loc, Numeral (Bigint.of_string n))
| s = string -> CPatPrim (loc, String s) ] ]
diff --git a/plugins/decl_mode/decl_interp.ml b/plugins/decl_mode/decl_interp.ml
index 6d3a5be39..a067440cb 100644
--- a/plugins/decl_mode/decl_interp.ml
+++ b/plugins/decl_mode/decl_interp.ml
@@ -96,10 +96,11 @@ let rec add_vars_of_simple_pattern globs = function
(UserError ("simple_pattern",str "\"(_ | _)\" is not allowed here"))
| CPatDelimiters (_,_,p) ->
add_vars_of_simple_pattern globs p
- | CPatCstr (_,_,pl) | CPatCstrExpl (_,_,pl) ->
- List.fold_left add_vars_of_simple_pattern globs pl
- | CPatNotation(_,_,(pl,pll)) ->
- List.fold_left add_vars_of_simple_pattern globs (List.flatten (pl::pll))
+ | CPatCstr (_,_,pl1,pl2) ->
+ List.fold_left add_vars_of_simple_pattern
+ (List.fold_left add_vars_of_simple_pattern globs pl1) pl2
+ | CPatNotation(_,_,(pl,pll),pl') ->
+ List.fold_left add_vars_of_simple_pattern globs (List.flatten (pl::pl'::pll))
| CPatAtom (_,Some (Libnames.Ident (_,id))) -> add_var id globs
| _ -> globs
diff --git a/printing/ppconstr.ml b/printing/ppconstr.ml
index 2e3ce2103..78a2fd759 100644
--- a/printing/ppconstr.ml
+++ b/printing/ppconstr.ml
@@ -174,19 +174,24 @@ let rec pr_patt sep inh p =
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
- | CPatCstr (_,c,[]) -> pr_reference c, latom
- | CPatCstr (_,c,args) ->
+ | CPatCstr (_,c,[],[]) -> pr_reference c, latom
+ | CPatCstr (_,c,[],args) ->
pr_reference c ++ prlist (pr_patt spc (lapp,L)) args, lapp
- | CPatCstrExpl (_,c,args) ->
+ | CPatCstr (_,c,args,[]) ->
str "@" ++ pr_reference c ++ prlist (pr_patt spc (lapp,L)) args, lapp
+ | CPatCstr (_,c,expl_args,extra_args) ->
+ surround (str "@" ++ pr_reference c ++ prlist (pr_patt spc (lapp,L)) expl_args)
+ ++ prlist (pr_patt spc (lapp,L)) extra_args, lapp
| CPatAtom (_,None) -> str "_", latom
| CPatAtom (_,Some r) -> pr_reference r, latom
| CPatOr (_,pl) ->
hov 0 (prlist_with_sep pr_bar (pr_patt spc (lpator,L)) pl), lpator
- | CPatNotation (_,"( _ )",([p],[])) ->
+ | CPatNotation (_,"( _ )",([p],[]),[]) ->
pr_patt (fun()->str"(") (max_int,E) p ++ str")", latom
- | CPatNotation (_,s,(l,ll)) ->
- pr_notation (pr_patt mt) (fun _ _ _ -> mt()) s (l,ll,[])
+ | CPatNotation (_,s,(l,ll),args) ->
+ let strm_not, l_not = pr_notation (pr_patt mt) (fun _ _ _ -> mt()) s (l,ll,[]) in
+ (if args=[]||prec_less l_not (lapp,L) then strm_not else surround strm_not)
+ ++ prlist (pr_patt spc (lapp,L)) args, if args<>[] then lapp else l_not
| CPatPrim (_,p) -> pr_prim_token p, latom
| CPatDelimiters (_,k,p) -> pr_delimiters k (pr_patt mt lsimple p), 1
in