aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Hugo Herbelin <Hugo.Herbelin@inria.fr>2014-10-20 12:56:43 +0200
committerGravatar Hugo Herbelin <Hugo.Herbelin@inria.fr>2014-10-20 23:29:19 +0200
commit7efeff178470ab204e531cd07176091bf5022da6 (patch)
treeafdc79d6eb2a371fa2cec235aabea3c5425d46b9
parentf00f8482e1d21ef8b03044ed2162cb29d9e4537d (diff)
A patch for printing "match" when constructors are defined with let-in
but the internal representation dropped let-in. Ideally, the internal representation of the "match" should use contexts for the predicate and the branches. This would however be a rather significant change. In the meantime, just a hack. To do, there is still an extra @ in the constructor name that does not need to be there.
-rw-r--r--checker/cic.mli3
-rw-r--r--interp/constrextern.ml4
-rw-r--r--intf/pattern.mli4
-rw-r--r--kernel/constr.ml17
-rw-r--r--kernel/constr.mli3
-rw-r--r--kernel/context.ml7
-rw-r--r--kernel/context.mli2
-rw-r--r--kernel/indtypes.ml3
-rw-r--r--kernel/nativecode.ml2
-rw-r--r--kernel/term.ml2
-rw-r--r--kernel/term.mli2
-rw-r--r--pretyping/detyping.ml128
-rw-r--r--pretyping/detyping.mli12
-rw-r--r--pretyping/inductiveops.ml9
-rw-r--r--pretyping/patternops.ml20
-rw-r--r--test-suite/output/Cases.out8
-rw-r--r--test-suite/output/Cases.v5
17 files changed, 141 insertions, 90 deletions
diff --git a/checker/cic.mli b/checker/cic.mli
index 1313208a3..f00c95705 100644
--- a/checker/cic.mli
+++ b/checker/cic.mli
@@ -53,7 +53,8 @@ type metavariable = int
type case_style = LetStyle | IfStyle | LetPatternStyle | MatchStyle
| RegularStyle (** infer printing form from number of constructor *)
type case_printing =
- { ind_nargs : int; (** length of the arity of the inductive type *)
+ { ind_tags : bool list; (* tell whether letin or lambda in the arity of the inductive type *)
+ cstr_tags : bool list array; (* whether each pattern var of each constructor is a let-in (true) or not (false) *)
style : case_style }
(** the integer is the number of real args, needed for reduction *)
diff --git a/interp/constrextern.ml b/interp/constrextern.ml
index 8e6485b7b..40e0901be 100644
--- a/interp/constrextern.ml
+++ b/interp/constrextern.ml
@@ -999,7 +999,7 @@ let rec glob_of_pat env sigma = function
| PIf (c,b1,b2) ->
GIf (loc, glob_of_pat env sigma c, (Anonymous,None),
glob_of_pat env sigma b1, glob_of_pat env sigma b2)
- | PCase ({cip_style=LetStyle; cip_ind_args=None},PMeta None,tm,[(0,n,b)]) ->
+ | PCase ({cip_style=LetStyle; cip_ind_tags=None},PMeta None,tm,[(0,n,b)]) ->
let nal,b = it_destRLambda_or_LetIn_names n (glob_of_pat env sigma b) in
GLetTuple (loc,nal,(Anonymous,None),glob_of_pat env sigma tm,b)
| PCase (info,p,tm,bl) ->
@@ -1012,7 +1012,7 @@ let rec glob_of_pat env sigma = function
in
let mat = if info.cip_extensible then mat @ [any_any_branch] else mat
in
- let indnames,rtn = match p, info.cip_ind, info.cip_ind_args with
+ let indnames,rtn = match p, info.cip_ind, info.cip_ind_tags with
| PMeta None, _, _ -> (Anonymous,None),None
| _, Some ind, Some nargs ->
return_type_of_predicate ind nargs (glob_of_pat env sigma p)
diff --git a/intf/pattern.mli b/intf/pattern.mli
index 4fa5f418d..b04db3bfa 100644
--- a/intf/pattern.mli
+++ b/intf/pattern.mli
@@ -55,7 +55,7 @@ type extended_patvar_map = constr_under_binders Id.Map.t
type case_info_pattern =
{ cip_style : case_style;
cip_ind : inductive option;
- cip_ind_args : int option; (** number of params and args *)
+ cip_ind_tags : bool list option; (** indicates LetIn/Lambda in arity *)
cip_extensible : bool (** does this match end with _ => _ ? *) }
type constr_pattern =
@@ -73,7 +73,7 @@ type constr_pattern =
| PMeta of patvar option
| PIf of constr_pattern * constr_pattern * constr_pattern
| PCase of case_info_pattern * constr_pattern * constr_pattern *
- (int * int * constr_pattern) list (** index of constructor, nb of args *)
+ (int * bool list * constr_pattern) list (** index of constructor, nb of args *)
| PFix of fixpoint
| PCoFix of cofixpoint
diff --git a/kernel/constr.ml b/kernel/constr.ml
index 912067629..f688cca45 100644
--- a/kernel/constr.ml
+++ b/kernel/constr.ml
@@ -38,7 +38,8 @@ type cast_kind = VMcast | NATIVEcast | DEFAULTcast | REVERTcast
(* This defines Cases annotations *)
type case_style = LetStyle | IfStyle | LetPatternStyle | MatchStyle | RegularStyle
type case_printing =
- { ind_nargs : int; (* length of the arity of the inductive type *)
+ { ind_tags : bool list; (** tell whether letin or lambda in the arity of the inductive type *)
+ cstr_tags : bool list array; (* whether each pattern var of each constructor is a let-in (true) or not (false) *)
style : case_style }
type case_info =
{ ci_ind : inductive;
@@ -933,7 +934,8 @@ struct
type u = inductive -> inductive
let hashcons hind ci = { ci with ci_ind = hind ci.ci_ind }
let pp_info_equal info1 info2 =
- Int.equal info1.ind_nargs info2.ind_nargs &&
+ List.equal (==) info1.ind_tags info2.ind_tags &&
+ Array.equal (List.equal (==)) info1.cstr_tags info2.cstr_tags &&
info1.style == info2.style
let equal ci ci' =
ci.ci_ind == ci'.ci_ind &&
@@ -942,15 +944,18 @@ struct
Array.equal Int.equal ci.ci_cstr_nargs ci'.ci_cstr_nargs && (* we use [Array.equal] on purpose *)
pp_info_equal ci.ci_pp_info ci'.ci_pp_info (* we use (=) on purpose *)
open Hashset.Combine
+ let hash_bool b = if b then 0 else 1
+ let hash_bool_list = List.fold_left (fun n b -> combine n (hash_bool b))
let hash_pp_info info =
- let h = match info.style with
+ let h1 = match info.style with
| LetStyle -> 0
| IfStyle -> 1
| LetPatternStyle -> 2
| MatchStyle -> 3
- | RegularStyle -> 4
- in
- combine info.ind_nargs h
+ | RegularStyle -> 4 in
+ let h2 = hash_bool_list 0 info.ind_tags in
+ let h3 = Array.fold_left hash_bool_list 0 info.cstr_tags in
+ combine3 h1 h2 h3
let hash ci =
let h1 = ind_hash ci.ci_ind in
let h2 = Int.hash ci.ci_npar in
diff --git a/kernel/constr.mli b/kernel/constr.mli
index da7ac6a0d..1e23911dd 100644
--- a/kernel/constr.mli
+++ b/kernel/constr.mli
@@ -26,7 +26,8 @@ type metavariable = int
type case_style = LetStyle | IfStyle | LetPatternStyle | MatchStyle
| RegularStyle (** infer printing form from number of constructor *)
type case_printing =
- { ind_nargs : int; (** length of the arity of the inductive type *)
+ { ind_tags : bool list; (** tell whether letin or lambda in the arity of the inductive type *)
+ cstr_tags : bool list array; (** tell whether letin or lambda in the signature of each constructor *)
style : case_style }
(** the integer is the number of real args, needed for reduction *)
diff --git a/kernel/context.ml b/kernel/context.ml
index 5256ee417..5cb964b9c 100644
--- a/kernel/context.ml
+++ b/kernel/context.ml
@@ -76,6 +76,13 @@ let rel_context_nhyps hyps =
| (_,Some _,_)::hyps -> nhyps acc hyps in
nhyps 0 hyps
+let rel_context_tags ctx =
+ let rec aux l = function
+ | [] -> l
+ | (_,Some _,_)::ctx -> aux (true::l) ctx
+ | (_,None _,_)::ctx -> aux (false::l) ctx
+ in aux [] ctx
+
(*s Signatures of named hypotheses. Used for section variables and
goal assumptions. *)
diff --git a/kernel/context.mli b/kernel/context.mli
index 1d732d273..b7eb7a76a 100644
--- a/kernel/context.mli
+++ b/kernel/context.mli
@@ -115,3 +115,5 @@ val lookup_rel : int -> rel_context -> rel_declaration
val rel_context_length : rel_context -> int
(** Size of the [rel_context] without LetIns *)
val rel_context_nhyps : rel_context -> int
+(** Indicates whether a LetIn or a Lambda, starting from oldest declaration *)
+val rel_context_tags : rel_context -> bool list
diff --git a/kernel/indtypes.ml b/kernel/indtypes.ml
index 39455a7d2..45e0261d3 100644
--- a/kernel/indtypes.ml
+++ b/kernel/indtypes.ml
@@ -666,7 +666,8 @@ let compute_projections ((kn, _ as ind), u as indsp) n x nparamargs params
let mp, dp, l = repr_mind kn in
let rp = mkApp (mkIndU indsp, rel_vect 0 nparamargs) in
let ci =
- let print_info = { ind_nargs = 0; style = LetStyle } in
+ let print_info =
+ { ind_tags = []; cstr_tags = [|rel_context_tags ctx|]; style = LetStyle } in
{ ci_ind = ind;
ci_npar = nparamargs;
ci_cstr_ndecls = mind_consnrealdecls;
diff --git a/kernel/nativecode.ml b/kernel/nativecode.ml
index 041751ecf..c8a4fa897 100644
--- a/kernel/nativecode.ml
+++ b/kernel/nativecode.ml
@@ -1807,7 +1807,7 @@ let compile_constant env sigma prefix ~interactive con cb =
let ci = { ci_ind = ind; ci_npar = mib.mind_nparams;
ci_cstr_nargs = [|0|];
ci_cstr_ndecls = [||] (*FIXME*);
- ci_pp_info = { ind_nargs = 0; style = RegularStyle } } in
+ ci_pp_info = { ind_tags = []; cstr_tags = [||] (*FIXME*); style = RegularStyle } } in
let asw = { asw_ind = ind; asw_prefix = prefix; asw_ci = ci;
asw_reloc = tbl; asw_finite = true } in
let c_uid = fresh_lname Anonymous in
diff --git a/kernel/term.ml b/kernel/term.ml
index 734b7853f..3adfa5e37 100644
--- a/kernel/term.ml
+++ b/kernel/term.ml
@@ -40,7 +40,7 @@ type case_style = Constr.case_style =
LetStyle | IfStyle | LetPatternStyle | MatchStyle | RegularStyle
type case_printing = Constr.case_printing =
- { ind_nargs : int; style : case_style }
+ { ind_tags : bool list; cstr_tags : bool list array; style : case_style }
type case_info = Constr.case_info =
{ ci_ind : inductive;
diff --git a/kernel/term.mli b/kernel/term.mli
index 50cd433e9..c5e85b1e5 100644
--- a/kernel/term.mli
+++ b/kernel/term.mli
@@ -47,7 +47,7 @@ type case_style = Constr.case_style =
LetStyle | IfStyle | LetPatternStyle | MatchStyle | RegularStyle
type case_printing = Constr.case_printing =
- { ind_nargs : int; style : case_style }
+ { ind_tags : bool list; cstr_tags : bool list array; style : case_style }
type case_info = Constr.case_info =
{ ci_ind : inductive;
diff --git a/pretyping/detyping.ml b/pretyping/detyping.ml
index e9a1174b4..2d7c7b146 100644
--- a/pretyping/detyping.ml
+++ b/pretyping/detyping.ml
@@ -172,7 +172,7 @@ let computable p k =
works for normal eta-expanded term. For non eta-expanded or
non-normal terms, it may affirm the pred is synthetisable
because of an undetected ultimate dependent variable in the second
- clause, or else, it may affirms the pred non synthetisable
+ clause, or else, it may affirm the pred non synthetisable
because of a non normal term in the fourth clause.
A solution could be to store, in the MutCase, the eta-expanded
normal form of pred to decide if it depends on its variables
@@ -239,26 +239,29 @@ let update_name na ((_,(e,_)),c) =
| _ ->
na
-let rec decomp_branch ndecls nargs nal b (avoid,env as e) c =
+let rec decomp_branch tags nal b (avoid,env as e) c =
let flag = if b then RenamingForGoal else RenamingForCasesPattern (fst env,c) in
- if Int.equal ndecls 0 then (List.rev nal,(e,c))
- else
- let na,c,f,nargs',body,t =
- match kind_of_term (strip_outer_cast c) with
- | Lambda (na,t,c) -> na,c,compute_displayed_let_name_in,nargs-1,None,Some t
- | LetIn (na,b,t,c) when ndecls>nargs ->
- na,c,compute_displayed_name_in,nargs,Some b,Some t
- | _ ->
+ match tags with
+ | [] -> (List.rev nal,(e,c))
+ | b::tags ->
+ let na,c,f,body,t =
+ match kind_of_term (strip_outer_cast c), b with
+ | Lambda (na,t,c),false -> na,c,compute_displayed_let_name_in,None,Some t
+ | LetIn (na,b,t,c),true ->
+ na,c,compute_displayed_name_in,Some b,Some t
+ | _, false ->
Name default_dependent_ident,(applist (lift 1 c, [mkRel 1])),
- compute_displayed_name_in,nargs-1,None,None
+ compute_displayed_name_in,None,None
+ | _, true ->
+ Anonymous,lift 1 c,compute_displayed_name_in,None,None
in
let na',avoid' = f flag avoid na c in
- decomp_branch (ndecls-1) nargs' (na'::nal) b
+ decomp_branch tags (na'::nal) b
(avoid', add_name_opt na' body t env) c
let rec build_tree na isgoal e ci cl =
let mkpat n rhs pl = PatCstr(dl,(ci.ci_ind,n+1),pl,update_name na rhs) in
- let cnl = ci.ci_cstr_ndecls in
+ let cnl = ci.ci_pp_info.cstr_tags in
let cna = ci.ci_cstr_nargs in
List.flatten
(List.init (Array.length cl)
@@ -271,7 +274,7 @@ and align_tree nal isgoal (e,c as rhs) = match nal with
| Case (ci,p,c,cl) when
eq_constr c (mkRel (List.index Name.equal na (fst (snd e))))
&& (* don't contract if p dependent *)
- computable p (ci.ci_pp_info.ind_nargs) ->
+ computable p (List.length ci.ci_pp_info.ind_tags) (* FIXME: can do better *) ->
let clauses = build_tree na isgoal e ci cl in
List.flatten
(List.map (fun (pat,rhs) ->
@@ -284,7 +287,7 @@ and align_tree nal isgoal (e,c as rhs) = match nal with
List.map (fun (hd,rest) -> pat::hd,rest) mat
and contract_branch isgoal e (cdn,can,mkpat,b) =
- let nal,rhs = decomp_branch cdn can [] isgoal e b in
+ let nal,rhs = decomp_branch cdn [] isgoal e b in
let mat = align_tree nal isgoal rhs in
List.map (fun (hd,rhs) -> (mkpat rhs hd,rhs)) mat
@@ -292,27 +295,32 @@ and contract_branch isgoal e (cdn,can,mkpat,b) =
(* Transform internal representation of pattern-matching into list of *)
(* clauses *)
-let is_nondep_branch c n =
+let is_nondep_branch c l =
try
- let sign,ccl = decompose_lam_n_assum n c in
+ (* FIXME: do better using tags from l *)
+ let sign,ccl = decompose_lam_n_assum (List.length l) c in
noccur_between 1 (rel_context_length sign) ccl
with e when Errors.noncritical e -> (* Not eta-expanded or not reduced *)
false
-let extract_nondep_branches test c b n =
- let rec strip n r = if Int.equal n 0 then r else
- match r with
- | GLambda (_,_,_,_,t) -> strip (n-1) t
- | GLetIn (_,_,_,t) -> strip (n-1) t
- | _ -> assert false in
- if test c n then Some (strip n b) else None
-
-let it_destRLambda_or_LetIn_names n c =
- let rec aux n nal c =
- if Int.equal n 0 then (List.rev nal,c) else match c with
- | GLambda (_,na,_,_,c) -> aux (n-1) (na::nal) c
- | GLetIn (_,na,_,c) -> aux (n-1) (na::nal) c
- | _ ->
+let extract_nondep_branches test c b l =
+ let rec strip l r =
+ match r,l with
+ | r, [] -> r
+ | GLambda (_,_,_,_,t), false::l -> strip l t
+ | GLetIn (_,_,_,t), true::l -> strip l t
+ (* FIXME: do we need adjustment? *)
+ | _,_ -> assert false in
+ if test c l then Some (strip l b) else None
+
+let it_destRLambda_or_LetIn_names l c =
+ let rec aux l nal c =
+ match c, l with
+ | _, [] -> (List.rev nal,c)
+ | GLambda (_,na,_,_,c), false::l -> aux l (na::nal) c
+ | GLetIn (_,na,_,c), true::l -> aux l (na::nal) c
+ | _, true::l -> (* let-expansion *) aux l (Anonymous :: nal) c
+ | _, false::l ->
(* eta-expansion *)
let next l =
let x = next_ident_away default_dependent_ident l in
@@ -322,14 +330,14 @@ let it_destRLambda_or_LetIn_names n c =
in
let x = next (free_glob_vars c) in
let a = GVar (dl,x) in
- aux (n-1) (Name x :: nal)
+ aux l (Name x :: nal)
(match c with
| GApp (loc,p,l) -> GApp (loc,p,l@[a])
| _ -> (GApp (dl,c,[a])))
- in aux n [] c
+ in aux l [] c
let detype_case computable detype detype_eqns testdep avoid data p c bl =
- let (indsp,st,consnargsl,k) = data in
+ let (indsp,st,constagsl,k) = data in
let synth_type = synthetize_type () in
let tomatch = detype c in
let alias, aliastyp, pred=
@@ -367,20 +375,20 @@ let detype_case computable detype detype_eqns testdep avoid data p c bl =
match tag, aliastyp with
| LetStyle, None ->
let bl' = Array.map detype bl in
- let (nal,d) = it_destRLambda_or_LetIn_names consnargsl.(0) bl'.(0) in
+ let (nal,d) = it_destRLambda_or_LetIn_names constagsl.(0) bl'.(0) in
GLetTuple (dl,nal,(alias,pred),tomatch,d)
| IfStyle, None ->
let bl' = Array.map detype bl in
let nondepbrs =
- Array.map3 (extract_nondep_branches testdep) bl bl' consnargsl in
+ Array.map3 (extract_nondep_branches testdep) bl bl' constagsl in
if Array.for_all ((!=) None) nondepbrs then
GIf (dl,tomatch,(alias,pred),
Option.get nondepbrs.(0),Option.get nondepbrs.(1))
else
- let eqnl = detype_eqns constructs consnargsl bl in
+ let eqnl = detype_eqns constructs constagsl bl in
GCases (dl,tag,pred,[tomatch,(alias,aliastyp)],eqnl)
| _ ->
- let eqnl = detype_eqns constructs consnargsl bl in
+ let eqnl = detype_eqns constructs constagsl bl in
GCases (dl,tag,pred,[tomatch,(alias,aliastyp)],eqnl)
let detype_sort = function
@@ -513,12 +521,12 @@ let rec detype flags avoid env sigma t =
| Construct (cstr_sp,u) ->
GRef (dl, ConstructRef cstr_sp, detype_instance u)
| Case (ci,p,c,bl) ->
- let comp = computable p (ci.ci_pp_info.ind_nargs) in
+ let comp = computable p (List.length (ci.ci_pp_info.ind_tags)) in
detype_case comp (detype flags avoid env sigma)
(detype_eqns flags avoid env sigma ci comp)
is_nondep_branch avoid
(ci.ci_ind,ci.ci_pp_info.style,
- ci.ci_cstr_ndecls,ci.ci_pp_info.ind_nargs)
+ ci.ci_pp_info.cstr_tags,ci.ci_pp_info.ind_tags)
(Some p) c bl
| Fix (nvn,recdef) -> detype_fix flags avoid env sigma nvn recdef
| CoFix (n,recdef) -> detype_cofix flags avoid env sigma n recdef
@@ -610,31 +618,35 @@ and detype_eqn (lax,isgoal as flags) avoid env sigma constr construct_nargs bran
let na,avoid' = compute_displayed_name_in flag avoid x b in
PatVar (dl,na),avoid',(add_name na body ty env),add_vname ids na
in
- let rec buildrec ids patlist avoid env n b =
- if Int.equal n 0 then
- (dl, Id.Set.elements ids,
- [PatCstr(dl, constr, List.rev patlist,Anonymous)],
- detype flags avoid env sigma b)
- else
- match kind_of_term b with
- | Lambda (x,t,b) ->
+ let rec buildrec ids patlist avoid env l b =
+ match kind_of_term b, l with
+ | _, [] ->
+ (dl, Id.Set.elements ids,
+ [PatCstr(dl, constr, List.rev patlist,Anonymous)],
+ detype flags avoid env sigma b)
+ | Lambda (x,t,b), false::l ->
let pat,new_avoid,new_env,new_ids = make_pat x avoid env b None t ids in
- buildrec new_ids (pat::patlist) new_avoid new_env (n-1) b
+ buildrec new_ids (pat::patlist) new_avoid new_env l b
- | LetIn (x,b,t,b') ->
+ | LetIn (x,b,t,b'), true::l ->
let pat,new_avoid,new_env,new_ids = make_pat x avoid env b' (Some b) t ids in
- buildrec new_ids (pat::patlist) new_avoid new_env (n-1) b'
+ buildrec new_ids (pat::patlist) new_avoid new_env l b'
+
+ | Cast (c,_,_), l -> (* Oui, il y a parfois des cast *)
+ buildrec ids patlist avoid env l c
- | Cast (c,_,_) -> (* Oui, il y a parfois des cast *)
- buildrec ids patlist avoid env n c
+ | _, true::l ->
+ let pat = PatVar (dl,Anonymous) in
+ buildrec ids (pat::patlist) avoid env l b
- | _ -> (* eta-expansion : n'arrivera plus lorsque tous les
- termes seront construits à partir de la syntaxe Cases *)
+ | _, false::l ->
+ (* eta-expansion : n'arrivera plus lorsque tous les
+ termes seront construits à partir de la syntaxe Cases *)
(* nommage de la nouvelle variable *)
let new_b = applist (lift 1 b, [mkRel 1]) in
let pat,new_avoid,new_env,new_ids =
make_pat Anonymous avoid env new_b None mkProp ids in
- buildrec new_ids (pat::patlist) new_avoid new_env (n-1) new_b
+ buildrec new_ids (pat::patlist) new_avoid new_env l new_b
in
buildrec Id.Set.empty [] avoid env construct_nargs branch
@@ -800,6 +812,6 @@ let simple_cases_matrix_of_branches ind brs =
(Loc.ghost,ids,[p],c))
brs
-let return_type_of_predicate ind nrealargs_ctxt pred =
- let nal,p = it_destRLambda_or_LetIn_names (nrealargs_ctxt+1) pred in
+let return_type_of_predicate ind nrealargs_tags pred =
+ let nal,p = it_destRLambda_or_LetIn_names (nrealargs_tags@[false]) pred in
(List.hd nal, Some (Loc.ghost, ind, List.tl nal)), Some p
diff --git a/pretyping/detyping.mli b/pretyping/detyping.mli
index b2fc92557..8a8312990 100644
--- a/pretyping/detyping.mli
+++ b/pretyping/detyping.mli
@@ -34,10 +34,10 @@ val detype : ?lax:bool -> bool -> Id.t list -> env -> evar_map -> constr -> glob
val detype_case :
bool -> ('a -> glob_constr) ->
- (constructor array -> int array -> 'a array ->
+ (constructor array -> bool list array -> 'a array ->
(Loc.t * Id.t list * cases_pattern list * glob_constr) list) ->
- ('a -> int -> bool) ->
- Id.t list -> inductive * case_style * int array * int ->
+ ('a -> bool list -> bool) ->
+ Id.t list -> inductive * case_style * bool list array * bool list ->
'a option -> 'a -> 'a array -> glob_constr
val detype_sort : sorts -> glob_sort
@@ -55,11 +55,11 @@ val synthetize_type : unit -> bool
(** Utilities to transform kernel cases to simple pattern-matching problem *)
-val it_destRLambda_or_LetIn_names : int -> glob_constr -> Name.t list * glob_constr
+val it_destRLambda_or_LetIn_names : bool list -> glob_constr -> Name.t list * glob_constr
val simple_cases_matrix_of_branches :
- inductive -> (int * int * glob_constr) list -> cases_clauses
+ inductive -> (int * bool list * glob_constr) list -> cases_clauses
val return_type_of_predicate :
- inductive -> int -> glob_constr -> predicate_pattern * glob_constr option
+ inductive -> bool list -> glob_constr -> predicate_pattern * glob_constr option
val subst_genarg_hook :
(substitution -> Genarg.glob_generic_argument -> Genarg.glob_generic_argument) Hook.t
diff --git a/pretyping/inductiveops.ml b/pretyping/inductiveops.ml
index 91072dce8..70c670e3f 100644
--- a/pretyping/inductiveops.ml
+++ b/pretyping/inductiveops.ml
@@ -273,7 +273,14 @@ let projection_nparams p = projection_nparams_env (Global.env ()) p
(* Annotation for cases *)
let make_case_info env ind style =
let (mib,mip) = Inductive.lookup_mind_specif env ind in
- let print_info = { ind_nargs = mip.mind_nrealdecls; style = style } in
+ let ind_tags =
+ rel_context_tags (List.firstn mip.mind_nrealargs mip.mind_arity_ctxt) in
+ let cstr_tags =
+ Array.map2 (fun c n ->
+ let d,_ = decompose_prod_assum c in
+ rel_context_tags (List.firstn n d))
+ mip.mind_nf_lc mip.mind_consnrealdecls in
+ let print_info = { ind_tags; cstr_tags; style } in
{ ci_ind = ind;
ci_npar = mib.mind_nparams;
ci_cstr_ndecls = mip.mind_consnrealdecls;
diff --git a/pretyping/patternops.ml b/pretyping/patternops.ml
index 8c553f613..0576ec57b 100644
--- a/pretyping/patternops.ml
+++ b/pretyping/patternops.ml
@@ -26,7 +26,7 @@ open Environ
let case_info_pattern_eq i1 i2 =
i1.cip_style == i2.cip_style &&
Option.equal eq_ind i1.cip_ind i2.cip_ind &&
- Option.equal Int.equal i1.cip_ind_args i2.cip_ind_args &&
+ Option.equal (List.equal (==)) i1.cip_ind_tags i2.cip_ind_tags &&
i1.cip_extensible == i2.cip_extensible
let rec constr_pattern_eq p1 p2 = match p1, p2 with
@@ -63,7 +63,7 @@ let rec constr_pattern_eq p1 p2 = match p1, p2 with
(** FIXME: fixpoint and cofixpoint should be relativized to pattern *)
and pattern_eq (i1, j1, p1) (i2, j2, p2) =
- Int.equal i1 i2 && Int.equal j1 j2 && constr_pattern_eq p1 p2
+ Int.equal i1 i2 && List.equal (==) j1 j2 && constr_pattern_eq p1 p2
and fixpoint_eq ((arg1, i1), r1) ((arg2, i2), r2) =
Int.equal i1 i2 &&
@@ -167,11 +167,11 @@ let pattern_of_constr env sigma t =
let cip =
{ cip_style = ci.ci_pp_info.style;
cip_ind = Some ci.ci_ind;
- cip_ind_args = Some (ci.ci_pp_info.ind_nargs);
+ cip_ind_tags = Some ci.ci_pp_info.ind_tags;
cip_extensible = false }
in
let branch_of_constr i c =
- (i, ci.ci_cstr_ndecls.(i), pattern_of_constr env c)
+ (i, ci.ci_pp_info.cstr_tags.(i), pattern_of_constr env c)
in
PCase (cip, pattern_of_constr env p, pattern_of_constr env a,
Array.to_list (Array.mapi branch_of_constr br))
@@ -360,17 +360,18 @@ let rec pat_of_raw metas vars = function
let cip =
{ cip_style = LetStyle;
cip_ind = None;
- cip_ind_args = None;
+ cip_ind_tags = None;
cip_extensible = false }
in
+ let tags = List.map (fun _ -> false) nal (* Approximation which can be without let-ins... *) in
PCase (cip, PMeta None, pat_of_raw metas vars b,
- [0,1,pat_of_raw metas vars c])
+ [0,tags,pat_of_raw metas vars c])
| GCases (loc,sty,p,[c,(na,indnames)],brs) ->
let get_ind = function
| (_,_,[PatCstr(_,(ind,_),_,_)],_)::_ -> Some ind
| _ -> None
in
- let ind_nargs,ind = match indnames with
+ let ind_tags,ind = match indnames with
| Some (_,ind,nal) -> Some (List.length nal), Some ind
| None -> None, get_ind brs
in
@@ -385,7 +386,7 @@ let rec pat_of_raw metas vars = function
let info =
{ cip_style = sty;
cip_ind = ind;
- cip_ind_args = ind_nargs;
+ cip_ind_tags = None;
cip_extensible = ext }
in
(* Nota : when we have a non-trivial predicate,
@@ -416,7 +417,8 @@ and pats_of_glob_branches loc metas vars ind brs =
let vars' = List.rev lna @ vars in
let pat = rev_it_mkPLambda lna (pat_of_raw metas vars' br) in
let ext,pats = get_pat (Int.Set.add (j-1) indexes) brs in
- ext, ((j-1, List.length lv, pat) :: pats)
+ let tags = List.map (fun _ -> false) lv (* approximation, w/o let-in *) in
+ ext, ((j-1, tags, pat) :: pats)
| (loc,_,_,_) :: _ -> err loc (Pp.str "Non supported pattern.")
in
get_pat Int.Set.empty brs
diff --git a/test-suite/output/Cases.out b/test-suite/output/Cases.out
index c768f09ce..0ebc251bc 100644
--- a/test-suite/output/Cases.out
+++ b/test-suite/output/Cases.out
@@ -8,6 +8,14 @@ fix F (t : t) : P t :=
(let x := t in forall x0 : x, P x0 -> P (k x0)) -> forall t : t, P t
t_rect is not universe polymorphic
+ = fun d : A => match d with
+ | @C _ _ b => b
+ end
+ : A -> 0 = 0
+ = fun d : A => match d with
+ | @C _ _ b => b
+ end
+ : A -> 0 = 0
proj =
fun (x y : nat) (P : nat -> Type) (def : P x) (prf : P y) =>
match Nat.eq_dec x y with
diff --git a/test-suite/output/Cases.v b/test-suite/output/Cases.v
index 30ef8778d..ef3a3a71e 100644
--- a/test-suite/output/Cases.v
+++ b/test-suite/output/Cases.v
@@ -5,6 +5,11 @@ Inductive t : Set :=
Print t_rect.
+Record A : Type := C { a := 0 : nat; c: nat; b : a=a }.
+
+Eval cbv in fun d:A => match d return 0 = 0 with C a _ b => b end.
+Eval lazy in fun d:A => match d return 0 = 0 with C a _ b => b end.
+
(* Do not contract nested patterns with dependent return type *)
(* see bug #1699 *)