aboutsummaryrefslogtreecommitdiff
path: root/interp/constrintern.ml
diff options
context:
space:
mode:
Diffstat (limited to 'interp/constrintern.ml')
-rw-r--r--interp/constrintern.ml104
1 files changed, 72 insertions, 32 deletions
diff --git a/interp/constrintern.ml b/interp/constrintern.ml
index 190369e8fa..3d484a02da 100644
--- a/interp/constrintern.ml
+++ b/interp/constrintern.ml
@@ -46,7 +46,7 @@ open Context.Rel.Declaration
types and recursive definitions and of projection names in records *)
type var_internalization_type =
- | Inductive of Id.t list (* list of params *)
+ | Inductive of Id.t list (* list of params *) * bool (* true = check for possible capture *)
| Recursive
| Method
| Variable
@@ -176,7 +176,7 @@ let parsing_explicit = ref false
let empty_internalization_env = Id.Map.empty
let compute_explicitable_implicit imps = function
- | Inductive params ->
+ | Inductive (params,_) ->
(* In inductive types, the parameters are fixed implicit arguments *)
let sub_impl,_ = List.chop (List.length params) imps in
let sub_impl' = List.filter is_status_implicit sub_impl in
@@ -190,10 +190,10 @@ let compute_internalization_data env ty typ impl =
let expls_impl = compute_explicitable_implicit impl ty in
(ty, expls_impl, impl, compute_arguments_scope typ)
-let compute_internalization_env env ty =
+let compute_internalization_env env ?(impls=empty_internalization_env) ty =
List.fold_left3
(fun map id typ impl -> Id.Map.add id (compute_internalization_data env ty typ impl) map)
- empty_internalization_env
+ impls
(**********************************************************************)
(* Contracting "{ _ }" in notations *)
@@ -358,16 +358,17 @@ let locate_if_hole ?loc na = function
let reset_hidden_inductive_implicit_test env =
{ env with impls = Id.Map.map (function
- | (Inductive _,b,c,d) -> (Inductive [],b,c,d)
+ | (Inductive (params,_),b,c,d) -> (Inductive (params,false),b,c,d)
| x -> x) env.impls }
-let check_hidden_implicit_parameters id impls =
+let check_hidden_implicit_parameters ?loc id impls =
if Id.Map.exists (fun _ -> function
- | (Inductive indparams,_,_,_) -> Id.List.mem id indparams
+ | (Inductive (indparams,check),_,_,_) when check -> Id.List.mem id indparams
| _ -> false) impls
then
- user_err (strbrk "A parameter of an inductive type " ++
- pr_id id ++ strbrk " is not allowed to be used as a bound variable in the type of its constructor.")
+ user_err ?loc (pr_id id ++ strbrk " is already used as name of " ++
+ strbrk "a parameter of the inductive type; bound variables in " ++
+ strbrk "the type of a constructor shall use a different name.")
let push_name_env ?(global_level=false) ntnvars implargs env =
function
@@ -376,7 +377,7 @@ let push_name_env ?(global_level=false) ntnvars implargs env =
user_err ?loc (str "Anonymous variables not allowed");
env
| loc,Name id ->
- check_hidden_implicit_parameters id env.impls ;
+ 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;
@@ -616,7 +617,7 @@ let instantiate_notation_constr loc intern ntnvars subst infos c =
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,[])
with Not_found ->
- anomaly (Pp.str "Inconsistent substitution of recursive notation") in
+ 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
@@ -659,7 +660,7 @@ let instantiate_notation_constr loc intern ntnvars subst infos c =
termin bl in
make_letins letins res
with Not_found ->
- anomaly (Pp.str "Inconsistent substitution of recursive notation"))
+ 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
@@ -962,6 +963,45 @@ let check_constructor_length env loc cstr len_pl pl0 =
(error_wrong_numarg_constructor ?loc env cstr
(Inductiveops.constructor_nrealargs cstr)))
+open Term
+open Declarations
+
+(* Similar to Cases.adjust_local_defs but on RCPat *)
+let insert_local_defs_in_pattern (ind,j) l =
+ let (mib,mip) = Global.lookup_inductive ind in
+ if mip.mind_consnrealdecls.(j-1) = mip.mind_consnrealargs.(j-1) then
+ (* Optimisation *) l
+ else
+ let typi = mip.mind_nf_lc.(j-1) in
+ let (_,typi) = decompose_prod_n_assum (Context.Rel.length mib.mind_params_ctxt) typi in
+ let (decls,_) = decompose_prod_assum typi in
+ let rec aux decls args =
+ match decls, args with
+ | Context.Rel.Declaration.LocalDef _ :: decls, args -> (CAst.make @@ RCPatAtom None) :: aux decls args
+ | _, [] -> [] (* In particular, if there were trailing local defs, they have been inserted *)
+ | Context.Rel.Declaration.LocalAssum _ :: decls, a :: args -> a :: aux decls args
+ | _ -> assert false in
+ aux (List.rev decls) l
+
+let add_local_defs_and_check_length loc env g pl args = match g with
+ | ConstructRef cstr ->
+ (* We consider that no variables corresponding to local binders
+ have been given in the "explicit" arguments, which come from a
+ "@C args" notation or from a custom user notation *)
+ let pl' = insert_local_defs_in_pattern cstr pl in
+ let maxargs = Inductiveops.constructor_nalldecls cstr in
+ if List.length pl' + List.length args > maxargs then
+ error_wrong_numarg_constructor ?loc env cstr (Inductiveops.constructor_nrealargs cstr);
+ (* Two possibilities: either the args are given with explict
+ variables for local definitions, then we give the explicit args
+ extended with local defs, so that there is nothing more to be
+ added later on; or the args are not enough to have all arguments,
+ which a priori means local defs to add in the [args] part, so we
+ postpone the insertion of local defs in the explicit args *)
+ (* Note: further checks done later by check_constructor_length *)
+ if List.length pl' + List.length args = maxargs then pl' else pl
+ | _ -> pl
+
let add_implicits_check_length fail nargs nargs_with_letin impls_st len_pl1 pl2 =
let impl_list = if Int.equal len_pl1 0
then select_impargs_size (List.length pl2) impls_st
@@ -1070,7 +1110,7 @@ let sort_fields ~complete loc fields completer =
let global_record_id = ConstructRef record.Recordops.s_CONST in
try Qualid (loc, shortest_qualid_of_global Id.Set.empty global_record_id)
with Not_found ->
- anomaly (str "Environment corruption for records") in
+ anomaly (str "Environment corruption for records.") in
let () = check_duplicate loc fields in
let (end_index, (* one past the last field index *)
first_field_index, (* index of the first field of the record *)
@@ -1085,7 +1125,7 @@ let sort_fields ~complete loc fields completer =
let field_glob_ref = ConstRef field_glob_id in
let first_field = eq_gr field_glob_ref first_field_glob_ref in
begin match proj_kinds with
- | [] -> anomaly (Pp.str "Number of projections mismatch")
+ | [] -> anomaly (Pp.str "Number of projections mismatch.")
| (_, regular) :: proj_kinds ->
(* "regular" is false when the field is defined
by a let-in in the record declaration
@@ -1199,7 +1239,7 @@ let rec subst_pat_iterator y t = CAst.(map (function
| RCPatAlias (p,a) -> RCPatAlias (subst_pat_iterator y t p,a)
| RCPatOr pl -> RCPatOr (List.map (subst_pat_iterator y t) pl)))
-let drop_notations_pattern looked_for =
+let drop_notations_pattern looked_for genv =
(* At toplevel, Constructors and Inductives are accepted, in recursive calls
only constructor are allowed *)
let ensure_kind top loc g =
@@ -1218,7 +1258,7 @@ let drop_notations_pattern looked_for =
| GHole (_,_,_) -> RCPatAtom (None)
| GRef (g,_) -> RCPatCstr (g,[],[])
| GApp ({ v = GRef (g,_) }, l) -> RCPatCstr (g, List.map rcp_of_glob l,[])
- | _ -> CErrors.anomaly Pp.(str "Invalid return pattern from Notation.interp_prim_token_cases_pattern_expr "))) x
+ | _ -> CErrors.anomaly Pp.(str "Invalid return pattern from Notation.interp_prim_token_cases_pattern_expr."))) x
in
let rec drop_syndef top scopes re pats =
let (loc,qid) = qualid_of_reference re in
@@ -1345,7 +1385,7 @@ let drop_notations_pattern looked_for =
in_pat top (scopt,subscopes@snd scopes) a
with Not_found ->
if Id.equal id ldots_var then CAst.make ?loc @@ RCPatAtom (Some id) else
- anomaly (str "Unbound pattern notation variable: " ++ Id.print id)
+ anomaly (str "Unbound pattern notation variable: " ++ Id.print id ++ str ".")
end
| NRef g ->
ensure_kind top loc g;
@@ -1354,9 +1394,9 @@ let drop_notations_pattern looked_for =
| NApp (NRef g,pl) ->
ensure_kind top loc g;
let (argscs1,argscs2) = find_remaining_scopes pl args g in
- CAst.make ?loc @@ RCPatCstr (g,
- List.map2 (fun x -> in_not false loc (x,snd scopes) fullsubst []) argscs1 pl @
- List.map (in_pat false scopes) args, [])
+ 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
+ CAst.make ?loc @@ RCPatCstr (g, pl @ List.map (in_pat false scopes) args, [])
| NList (x,y,iter,terminator,lassoc) ->
if not (List.is_empty args) then user_err ?loc
(strbrk "Application of arguments to a recursive notation not supported in patterns.");
@@ -1370,7 +1410,7 @@ let drop_notations_pattern looked_for =
subst_pat_iterator ldots_var t u)
(if lassoc then List.rev l else l) termin
with Not_found ->
- anomaly (Pp.str "Inconsistent substitution of recursive notation"))
+ anomaly (Pp.str "Inconsistent substitution of recursive notation."))
| NHole _ ->
let () = assert (List.is_empty args) in
CAst.make ?loc @@ RCPatAtom None
@@ -1417,7 +1457,7 @@ let rec intern_pat genv aliases pat =
let intern_cases_pattern genv scopes aliases pat =
intern_pat genv aliases
- (drop_notations_pattern (function ConstructRef _ -> () | _ -> raise Not_found) scopes pat)
+ (drop_notations_pattern (function ConstructRef _ -> () | _ -> raise Not_found) genv scopes pat)
let _ =
intern_cases_pattern_fwd :=
@@ -1426,7 +1466,7 @@ let _ =
let intern_ind_pattern genv scopes pat =
let no_not =
try
- drop_notations_pattern (function (IndRef _ | ConstructRef _) -> () | _ -> raise Not_found) scopes pat
+ drop_notations_pattern (function (IndRef _ | ConstructRef _) -> () | _ -> raise Not_found) genv scopes pat
with InternalizationError(loc,NotAConstructor _) -> error_bad_inductive_type ?loc
in
let loc = no_not.CAst.loc in
@@ -1464,7 +1504,7 @@ let get_implicit_name n imps =
let set_hole_implicit i b = function
| {loc; v = GRef (r,_) } | { v = GApp ({loc; v = GRef (r,_)},_) } -> Loc.tag ?loc (Evar_kinds.ImplicitArg (r,i,b),Misctypes.IntroAnonymous,None)
| {loc; v = GVar id } -> Loc.tag ?loc (Evar_kinds.ImplicitArg (VarRef id,i,b),Misctypes.IntroAnonymous,None)
- | _ -> anomaly (Pp.str "Only refs have implicits")
+ | _ -> anomaly (Pp.str "Only refs have implicits.")
let exists_implicit_name id =
List.exists (fun imp -> is_status_implicit imp && Id.equal id (name_of_implicit imp))
@@ -1506,7 +1546,7 @@ let extract_explicit_arg imps args =
(**********************************************************************)
(* Main loop *)
-let internalize globalenv env allow_patvar (_, ntnvars as lvar) c =
+let internalize globalenv env pattern_mode (_, ntnvars as lvar) c =
let rec intern env = CAst.with_loc_val (fun ?loc -> function
| CRef (ref,us) ->
let (c,imp,subscopes,l),_ =
@@ -1749,12 +1789,12 @@ let internalize globalenv env allow_patvar (_, ntnvars as lvar) c =
CAst.make ?loc @@
GHole (k, naming, solve)
(* Parsing pattern variables *)
- | CPatVar n when allow_patvar ->
+ | CPatVar n when pattern_mode ->
CAst.make ?loc @@
- GPatVar (true,n)
- | CEvar (n, []) when allow_patvar ->
+ GPatVar (Evar_kinds.SecondOrderPatVar n)
+ | CEvar (n, []) when pattern_mode ->
CAst.make ?loc @@
- GPatVar (false,n)
+ GPatVar (Evar_kinds.FirstOrderPatVar n)
(* end *)
(* Parsing existential variables *)
| CEvar (n, l) ->
@@ -1944,13 +1984,13 @@ let empty_ltac_sign = {
}
let intern_gen kind env
- ?(impls=empty_internalization_env) ?(allow_patvar=false) ?(ltacvars=empty_ltac_sign)
+ ?(impls=empty_internalization_env) ?(pattern_mode=false) ?(ltacvars=empty_ltac_sign)
c =
let tmp_scope = scope_of_type_kind kind in
internalize env {ids = extract_ids env; unb = false;
tmp_scope = tmp_scope; scopes = [];
impls = impls}
- allow_patvar (ltacvars, Id.Map.empty) c
+ pattern_mode (ltacvars, Id.Map.empty) c
let intern_constr env c = intern_gen WithoutTypeConstraint env c
@@ -2023,7 +2063,7 @@ let interp_type_evars env evdref ?(impls=empty_internalization_env) c =
let intern_constr_pattern env ?(as_type=false) ?(ltacvars=empty_ltac_sign) c =
let c = intern_gen (if as_type then IsType else WithoutTypeConstraint)
- ~allow_patvar:true ~ltacvars env c in
+ ~pattern_mode:true ~ltacvars env c in
pattern_of_glob_constr c
let interp_notation_constr ?(impls=empty_internalization_env) nenv a =