diff options
author | Samuel Mimram <smimram@debian.org> | 2006-04-28 14:59:16 +0000 |
---|---|---|
committer | Samuel Mimram <smimram@debian.org> | 2006-04-28 14:59:16 +0000 |
commit | 3ef7797ef6fc605dfafb32523261fe1b023aeecb (patch) | |
tree | ad89c6bb57ceee608fcba2bb3435b74e0f57919e /pretyping/indrec.ml | |
parent | 018ee3b0c2be79eb81b1f65c3f3fa142d24129c8 (diff) |
Imported Upstream version 8.0pl3+8.1alphaupstream/8.0pl3+8.1alpha
Diffstat (limited to 'pretyping/indrec.ml')
-rw-r--r-- | pretyping/indrec.ml | 249 |
1 files changed, 159 insertions, 90 deletions
diff --git a/pretyping/indrec.ml b/pretyping/indrec.ml index 0b9283ae..a587dd20 100644 --- a/pretyping/indrec.ml +++ b/pretyping/indrec.ml @@ -6,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(* $Id: indrec.ml,v 1.20.2.3 2004/07/16 19:30:44 herbelin Exp $ *) +(* $Id: indrec.ml 7662 2005-12-17 22:03:35Z herbelin $ *) open Pp open Util @@ -19,14 +19,21 @@ open Declarations open Entries open Inductive open Inductiveops -open Instantiate open Environ open Reductionops open Typeops open Type_errors -open Indtypes (* pour les erreurs *) open Safe_typing open Nametab +open Sign + +(* Errors related to recursors building *) +type recursion_scheme_error = + | NotAllowedCaseAnalysis of bool * sorts * inductive + | BadInduction of bool * identifier * sorts + | NotMutualInScheme + +exception RecursionSchemeError of recursion_scheme_error let make_prod_dep dep env = if dep then prod_name env else mkProd let mkLambda_string s t c = mkLambda (Name (id_of_string s), t, c) @@ -42,18 +49,18 @@ let mkLambda_string s t c = mkLambda (Name (id_of_string s), t, c) lifter les paramètres globaux *) let mis_make_case_com depopt env sigma (ind,mib,mip) kind = - let lnamespar = mip.mind_params_ctxt in + let lnamespar = mib.mind_params_ctxt in let dep = match depopt with | None -> mip.mind_sort <> (Prop Null) | Some d -> d in if not (List.exists ((=) kind) mip.mind_kelim) then raise - (InductiveError + (RecursionSchemeError (NotAllowedCaseAnalysis (dep,(new_sort_in_family kind),ind))); - let nbargsprod = mip.mind_nrealargs + 1 in + let ndepar = mip.mind_nrealargs + 1 in (* Pas génant car env ne sert pas à typer mais juste à renommer les Anonym *) (* mais pas très joli ... (mais manque get_sort_of à ce niveau) *) @@ -65,22 +72,28 @@ let mis_make_case_com depopt env sigma (ind,mib,mip) kind = let rec add_branch env k = if k = Array.length mip.mind_consnames then let nbprod = k+1 in - let indf = make_ind_family(ind,extended_rel_list nbprod lnamespar) in - let lnamesar,_ = get_arity env indf in + + let indf' = lift_inductive_family nbprod indf in + let arsign,_ = get_arity env indf' in + let depind = build_dependent_inductive env indf' in + let deparsign = (Anonymous,None,depind)::arsign in + let ci = make_default_case_info env RegularStyle ind in - let depind = build_dependent_inductive env indf in - let deparsign = (Anonymous,None,depind)::lnamesar in - let p = - it_mkLambda_or_LetIn_name env' - (appvect - (mkRel ((if dep then nbargsprod else mip.mind_nrealargs) + nbprod), - if dep then extended_rel_vect 0 deparsign - else extended_rel_vect 0 lnamesar)) - (if dep then deparsign else lnamesar) in + let pbody = + appvect + (mkRel (ndepar + nbprod), + if dep then extended_rel_vect 0 deparsign + else extended_rel_vect 1 arsign) in + let p = + it_mkLambda_or_LetIn_name env' + ((if dep then mkLambda_name env' else mkLambda) + (Anonymous,depind,pbody)) + arsign + in it_mkLambda_or_LetIn_name env' - (mkCase (ci, lift nbargsprod p, + (mkCase (ci, lift ndepar p, mkRel 1, - rel_vect nbargsprod k)) + rel_vect ndepar k)) deparsign else let cs = lift_constructor (k+1) constrs.(k) in @@ -186,7 +199,7 @@ let type_rec_branch is_rec dep env sigma (vargs,depPvect,decP) tyi cs recargs = let c = it_mkProd_or_LetIn base cs.cs_args in process_constr env 0 c recargs nhyps [] -let make_rec_branch_arg env sigma (nparams,fvect,decF) f cstr recargs = +let make_rec_branch_arg env sigma (nparrec,fvect,decF) f cstr recargs = let process_pos env fk = let rec prec env i hyps p = let p',largs = whd_betadeltaiota_nolet_stack env sigma p in @@ -198,7 +211,7 @@ let make_rec_branch_arg env sigma (nparams,fvect,decF) f cstr recargs = let d = (n,Some b,t) in mkLetIn (n,b,t,prec (push_rel d env) (i+1) (d::hyps) c) | Ind _ -> - let realargs = list_skipn nparams largs + let realargs = list_skipn nparrec largs and arg = appvect (mkRel (i+1),extended_rel_vect 0 hyps) in applist(lift i fk,realargs@[arg]) | _ -> assert false @@ -239,10 +252,24 @@ let make_rec_branch_arg env sigma (nparams,fvect,decF) f cstr recargs = in process_constr env 0 f (List.rev cstr.cs_args, recargs) + +(* Cut a context ctx in 2 parts (ctx1,ctx2) with ctx1 containing k + variables *) +let context_chop k ctx = + let rec chop_aux acc = function + | (0, l2) -> (List.rev acc, l2) + | (n, ((_,Some _,_ as h)::t)) -> chop_aux (h::acc) (n, t) + | (n, (h::t)) -> chop_aux (h::acc) (pred n, t) + | (_, []) -> failwith "context_chop" + in chop_aux [] (k,ctx) + + (* Main function *) -let mis_make_indrec env sigma listdepkind (ind,mib,mip) = - let nparams = mip.mind_nparams in - let lnamespar = mip.mind_params_ctxt in +let mis_make_indrec env sigma listdepkind mib = + let nparams = mib.mind_nparams in + let nparrec = mib. mind_nparams_rec in + let lnonparrec,lnamesparrec = + context_chop (nparams-nparrec) mib.mind_params_ctxt in let nrec = List.length listdepkind in let depPvec = Array.create mib.mind_ntypes (None : (bool * constr) option) in @@ -257,6 +284,11 @@ let mis_make_indrec env sigma listdepkind (ind,mib,mip) = assign nrec listdepkind in let recargsvec = Array.map (fun mip -> mip.mind_recargs) mib.mind_packets in + (* recarg information for non recursive parameters *) + let rec recargparn l n = + if n = 0 then l else recargparn (mk_norec::l) (n-1) + in + let recargpar = recargparn [] (nparams-nparrec) in let make_one_rec p = let makefix nbconstruct = let rec mrec i ln ltyp ldef = function @@ -267,59 +299,86 @@ let mis_make_indrec env sigma listdepkind (ind,mib,mip) = (* arity in the context of the fixpoint, i.e. P1..P_nrec f1..f_nbconstruct *) - let args = extended_rel_list (nrec+nbconstruct) lnamespar in + let args = extended_rel_list (nrec+nbconstruct) lnamesparrec in let indf = make_ind_family(indi,args) in - let lnames,_ = get_arity env indf in - let nar = mipi.mind_nrealargs in - let dect = nar+nrec+nbconstruct in + let arsign,_ = get_arity env indf in + let depind = build_dependent_inductive env indf in + let deparsign = (Anonymous,None,depind)::arsign in + + let nonrecpar = rel_context_length lnonparrec in + let larsign = rel_context_length deparsign in + let ndepar = larsign - nonrecpar in + let dect = larsign+nrec+nbconstruct in - let branches = (* constructors in context of the Cases expr, i.e. - P1..P_nrec f1..f_nbconstruct F_1..F_nrec a_1..a_nar x:I *) - let args' = extended_rel_list (dect+nrec+1) lnamespar in - let indf' = make_ind_family(indi,args') in + P1..P_nrec f1..f_nbconstruct F_1..F_nrec a_1..a_nar x:I *) + let args' = extended_rel_list (dect+nrec) lnamesparrec in + let args'' = extended_rel_list ndepar lnonparrec in + let indf' = make_ind_family(indi,args'@args'') in + + let branches = let constrs = get_constructors env indf' in - let vecfi = rel_vect (dect+1-i-nctyi) nctyi in + let fi = rel_vect (dect-i-nctyi) nctyi in + let vecfi = Array.map + (fun f -> appvect (f,extended_rel_vect ndepar lnonparrec)) + fi + in array_map3 - (make_rec_branch_arg env sigma (nparams,depPvec,nar+1)) - vecfi constrs (dest_subterms recargsvec.(tyi)) in + (make_rec_branch_arg env sigma + (nparrec,depPvec,larsign)) + vecfi constrs (dest_subterms recargsvec.(tyi)) + in + let j = (match depPvec.(tyi) with | Some (_,c) when isRel c -> destRel c - | _ -> assert false) in + | _ -> assert false) + in + + (* Predicate in the context of the case *) + + let depind' = build_dependent_inductive env indf' in + let arsign',_ = get_arity env indf' in + let deparsign' = (Anonymous,None,depind')::arsign' in + + let pargs = + let nrpar = extended_rel_list (2*ndepar) lnonparrec + and nrar = if dep then extended_rel_list 0 deparsign' + else extended_rel_list 1 arsign' + in nrpar@nrar + + in + + (* body of i-th component of the mutual fixpoint *) let deftyi = let ci = make_default_case_info env RegularStyle indi in - let indf' = lift_inductive_family nrec indf in - let depind = build_dependent_inductive env indf' in - let lnames' = Termops.lift_rel_context nrec lnames in - let p = - let arsign = - if dep then (Anonymous,None,depind)::lnames' else lnames' in - it_mkLambda_or_LetIn_name env - (appvect - (mkRel ((if dep then 1 else 0) + dect + j), - extended_rel_vect 0 arsign)) arsign + let concl = applist (mkRel (dect+j+ndepar),pargs) in + let pred = + it_mkLambda_or_LetIn_name env + ((if dep then mkLambda_name env else mkLambda) + (Anonymous,depind',concl)) + arsign' in it_mkLambda_or_LetIn_name env - (lambda_create env - (depind,mkCase (ci, lift (nar+1) p, mkRel 1, branches))) - lnames' + (mkCase (ci, pred, + mkRel 1, + branches)) + (lift_rel_context nrec deparsign) in - let typtyi = - let ind = build_dependent_inductive env indf in - it_mkProd_or_LetIn_name env - (prod_create env - (ind, - (if dep then - let ext_lnames = (Anonymous,None,ind)::lnames in - let args = extended_rel_list 0 ext_lnames in - applist (mkRel (nbconstruct+nar+j+1), args) - else - let args = extended_rel_list 1 lnames in - applist (mkRel (nbconstruct+nar+j+1), args)))) - lnames - in - mrec (i+nctyi) (nar::ln) (typtyi::ltyp) (deftyi::ldef) rest + + (* type of i-th component of the mutual fixpoint *) + + let typtyi = + let concl = + let pargs = if dep then extended_rel_vect 0 deparsign + else extended_rel_vect 1 arsign + in appvect (mkRel (nbconstruct+ndepar+nonrecpar+j),pargs) + in it_mkProd_or_LetIn_name env + concl + deparsign + in + mrec (i+nctyi) (rel_context_nhyps arsign ::ln) (typtyi::ltyp) + (deftyi::ldef) rest | [] -> let fixn = Array.of_list (List.rev ln) in let fixtyi = Array.of_list (List.rev ltyp) in @@ -327,7 +386,7 @@ let mis_make_indrec env sigma listdepkind (ind,mib,mip) = let names = Array.create nrec (Name(id_of_string "F")) in mkFix ((fixn,p),(names,fixtyi,fixdef)) in - mrec 0 [] [] [] + mrec 0 [] [] [] in let rec make_branch env i = function | (indi,mibi,mipi,dep,_)::rest -> @@ -338,8 +397,8 @@ let mis_make_indrec env sigma listdepkind (ind,mib,mip) = make_branch env (i+j) rest else let recarg = (dest_subterms recargsvec.(tyi)).(j) in - let vargs = extended_rel_list (nrec+i+j) lnamespar in - let indf = (indi, vargs) in + let recarg = recargpar@recarg in + let vargs = extended_rel_list (nrec+i+j) lnamesparrec in let cs = get_constructor (indi,mibi,mipi,vargs) (j+1) in let p_0 = type_rec_branch @@ -353,23 +412,28 @@ let mis_make_indrec env sigma listdepkind (ind,mib,mip) = in let rec put_arity env i = function | (indi,_,_,dep,kinds)::rest -> - let indf = make_ind_family (indi,extended_rel_list i lnamespar) in + let indf = make_ind_family (indi,extended_rel_list i lnamesparrec) in let typP = make_arity env dep indf (new_sort_in_family kinds) in mkLambda_string "P" typP (put_arity (push_rel (Anonymous,None,typP) env) (i+1) rest) | [] -> make_branch env 0 listdepkind in + + (* Body on make_one_rec *) let (indi,mibi,mipi,dep,kind) = List.nth listdepkind p in - let env' = push_rel_context lnamespar env in + if mis_is_recursive_subset (List.map (fun (indi,_,_,_,_) -> snd indi) listdepkind) mipi.mind_recargs then - it_mkLambda_or_LetIn_name env (put_arity env' 0 listdepkind) lnamespar + let env' = push_rel_context lnamesparrec env in + it_mkLambda_or_LetIn_name env (put_arity env' 0 listdepkind) + lnamesparrec else mis_make_case_com (Some dep) env sigma (indi,mibi,mipi) kind in + (* Body of mis_make_indrec *) list_tabulate make_one_rec nrec (**********************************************************************) @@ -385,20 +449,21 @@ let make_case_gen env = make_case_com None env (**********************************************************************) -(* [instanciate_indrec_scheme s rec] replace the sort of the scheme +(* [instantiate_indrec_scheme s rec] replace the sort of the scheme [rec] by [s] *) let change_sort_arity sort = let rec drec a = match kind_of_term a with - | Cast (c,t) -> drec c + | Cast (c,_,_) -> drec c | Prod (n,t,c) -> mkProd (n, t, drec c) + | LetIn (n,b,t,c) -> mkLetIn (n,b, t, drec c) | Sort _ -> mkSort sort | _ -> assert false in drec (* [npar] is the number of expected arguments (then excluding letin's) *) -let instanciate_indrec_scheme sort = +let instantiate_indrec_scheme sort = let rec drec npar elim = match kind_of_term elim with | Lambda (n,t,c) -> @@ -407,13 +472,13 @@ let instanciate_indrec_scheme sort = else mkLambda (n, t, drec (npar-1) c) | LetIn (n,b,t,c) -> mkLetIn (n,b,t,drec npar c) - | _ -> anomaly "instanciate_indrec_scheme: wrong elimination type" + | _ -> anomaly "instantiate_indrec_scheme: wrong elimination type" in drec (* Change the sort in the type of an inductive definition, builds the corresponding eta-expanded term *) -let instanciate_type_indrec_scheme sort npars term = +let instantiate_type_indrec_scheme sort npars term = let rec drec np elim = match kind_of_term elim with | Prod (n,t,c) -> @@ -426,22 +491,27 @@ let instanciate_type_indrec_scheme sort npars term = mkProd (n, t, c'), mkLambda (n, t, term') | LetIn (n,b,t,c) -> let c',term' = drec np c in mkLetIn (n,b,t,c'), mkLetIn (n,b,t,term') - | _ -> anomaly "instanciate_type_indrec_scheme: wrong elimination type" + | _ -> anomaly "instantiate_type_indrec_scheme: wrong elimination type" in drec npars (**********************************************************************) (* Interface to build complex Scheme *) +(* Check inductive types only occurs once +(otherwise we obtain a meaning less scheme) *) let check_arities listdepkind = - List.iter - (function (indi,mibi,mipi,dep,kind) -> + let _ = List.fold_left + (fun ln ((_,ni),mibi,mipi,dep,kind) -> let id = mipi.mind_typename in let kelim = mipi.mind_kelim in - if not (List.exists ((=) kind) kelim) then - raise - (InductiveError (BadInduction (dep, id, new_sort_in_family kind)))) - listdepkind + if not (List.exists ((=) kind) kelim) then raise + (RecursionSchemeError (BadInduction (dep,id,new_sort_in_family kind))) + else if List.mem ni ln then raise + (RecursionSchemeError NotMutualInScheme) + else ni::ln) + [] listdepkind + in true let build_mutual_indrec env sigma = function | (mind,mib,mip,dep,s)::lrecspec -> @@ -455,18 +525,18 @@ let build_mutual_indrec env sigma = function let (mibi',mipi') = lookup_mind_specif env mind' in (mind',mibi',mipi',dep',s') else - raise (InductiveError NotMutualInScheme)) + raise (RecursionSchemeError NotMutualInScheme)) lrecspec) in let _ = check_arities listdepkind in - mis_make_indrec env sigma listdepkind (mind,mib,mip) + mis_make_indrec env sigma listdepkind mib | _ -> anomaly "build_indrec expects a non empty list of inductive types" let build_indrec env sigma ind = let (mib,mip) = lookup_mind_specif env ind in let kind = family_of_sort mip.mind_sort in let dep = kind <> InProp in - List.hd (mis_make_indrec env sigma [(ind,mib,mip,dep,kind)] (ind,mib,mip)) + List.hd (mis_make_indrec env sigma [(ind,mib,mip,dep,kind)] mib) (**********************************************************************) (* To handle old Case/Match syntax in Pretyping *) @@ -483,7 +553,6 @@ let type_rec_branches recursive env sigma indt p c = let tyi = snd ind in let init_depPvec i = if i = tyi then Some(true,p) else None in let depPvec = Array.init mib.mind_ntypes init_depPvec in - let vargs = Array.of_list params in let constructors = get_constructors env indf in let lft = array_map2 @@ -513,14 +582,14 @@ let lookup_eliminator ind_sp s = let id = add_suffix ind_id (elimination_suffix s) in (* Try first to get an eliminator defined in the same section as the *) (* inductive type *) - let ref = ConstRef (make_kn mp dp (label_of_id id)) in + let ref = ConstRef (make_con mp dp (label_of_id id)) in try let _ = sp_of_global ref in - constr_of_reference ref + constr_of_global ref with Not_found -> (* Then try to get a user-defined eliminator in some other places *) (* using short name (e.g. for "eq_rec") *) - try constr_of_reference (Nametab.locate (make_short_qualid id)) + try constr_of_global (Nametab.locate (make_short_qualid id)) with Not_found -> errorlabstrm "default_elim" (str "Cannot find the elimination combinator " ++ @@ -541,7 +610,7 @@ let lookup_eliminator ind_sp s = with Not_found -> (* Then try to get a user-defined eliminator in some other places *) (* using short name (e.g. for "eq_rec") *) - try constr_of_reference (Nametab.locate (make_short_qualid id)) + try constr_of_global (Nametab.locate (make_short_qualid id)) with Not_found -> errorlabstrm "default_elim" (str "Cannot find the elimination combinator " ++ |