diff options
Diffstat (limited to 'kernel/indtypes.ml')
-rw-r--r-- | kernel/indtypes.ml | 256 |
1 files changed, 205 insertions, 51 deletions
diff --git a/kernel/indtypes.ml b/kernel/indtypes.ml index 33a26c800..1255e9787 100644 --- a/kernel/indtypes.ml +++ b/kernel/indtypes.ml @@ -10,24 +10,34 @@ open Util open Names +open Univ open Term open Declarations open Inductive open Sign open Environ -open Instantiate open Reduction open Typeops -(* In the following, each time an [evar_map] is required, then [Evd.empty] - is given, since inductive types are typed in an environment without - existentials. *) - (* [check_constructors_names id s cl] checks that all the constructors names appearing in [l] are not present in the set [s], and returns the new set of names. The name [id] is the name of the current inductive type, used when reporting the error. *) +(*s Declaration. *) + +type one_inductive_entry = { + mind_entry_nparams : int; + mind_entry_params : (identifier * local_entry) list; + mind_entry_typename : identifier; + mind_entry_arity : constr; + mind_entry_consnames : identifier list; + mind_entry_lc : constr list } + +type mutual_inductive_entry = { + mind_entry_finite : bool; + mind_entry_inds : one_inductive_entry list } + (***********************************************************************) (* Various well-formedness check for inductive declarations *) @@ -85,7 +95,7 @@ let mind_extract_params = decompose_prod_n_assum let mind_check_arities env mie = let check_arity id c = - if not (is_arity env Evd.empty c) then + if not (is_arity env c) then raise (InductiveError (NotAnArity id)) in List.iter @@ -98,6 +108,143 @@ let mind_check_wellformed env mie = mind_check_arities env mie (***********************************************************************) +(***********************************************************************) + +(* Typing the arities and constructor types *) + +let is_info_arity env c = + match dest_arity env c with + | (_,Prop Null) -> false + | (_,Prop Pos) -> true + | (_,Type _) -> true + +let is_info_type env t = + let s = t.utj_type in + if s = mk_Set then true + else if s = mk_Prop then false + else + try is_info_arity env t.utj_val + with UserError _ -> true + +(* [infos] is a sequence of pair [islogic,issmall] for each type in + the product of a constructor or arity *) + +let is_small infos = List.for_all (fun (logic,small) -> small) infos +let is_logic_constr infos = List.for_all (fun (logic,small) -> logic) infos +let is_logic_arity infos = + List.for_all (fun (logic,small) -> logic || small) infos + +let is_unit arinfos constrsinfos = + match constrsinfos with (* One info = One constructor *) + | [constrinfos] -> is_logic_constr constrinfos && is_logic_arity arinfos + | _ -> false + +let rec infos_and_sort env t = + match kind_of_term t with + | Prod (name,c1,c2) -> + let (varj,_) = infer_type env c1 in + let env1 = Environ.push_rel (name,None,varj.utj_val) env in + let logic = not (is_info_type env varj) in + let small = Term.is_small varj.utj_type in + (logic,small) :: (infos_and_sort env1 c2) + | Cast (c,_) -> infos_and_sort env c + | _ -> [] + +let small_unit constrsinfos (env_ar_par,short_arity) = + let issmall = List.for_all is_small constrsinfos in + let arinfos = infos_and_sort env_ar_par short_arity in + let isunit = is_unit arinfos constrsinfos in + issmall, isunit + +(* This (re)computes informations relevant to extraction and the sort of an + arity or type constructor; we do not to recompute universes constraints *) + +(* [smax] is the max of the sorts of the products of the constructor type *) + +let enforce_type_constructor arsort smax cst = + match smax, arsort with + | Type uc, Type ua -> enforce_geq ua uc cst + | _,_ -> cst + +let type_one_constructor env_ar_par params arsort c = + let infos = infos_and_sort env_ar_par c in + + (* Each constructor is typed-checked here *) + let (j,cst) = infer_type env_ar_par c in + let full_cstr_type = it_mkProd_or_LetIn j.utj_val params in + + (* If the arity is at some level Type arsort, then the sort of the + constructor must be below arsort; here we consider constructors with the + global parameters (which add a priori more constraints on their sort) *) + let cst2 = enforce_type_constructor arsort j.utj_type cst in + + (infos, full_cstr_type, cst2) + +let infer_constructor_packet env_ar params short_arity arsort vc = + let env_ar_par = push_rel_context params env_ar in + let (constrsinfos,jlc,cst) = + List.fold_right + (fun c (infosl,l,cst) -> + let (infos,ct,cst') = + type_one_constructor env_ar_par params arsort c in + (infos::infosl,ct::l, Constraint.union cst cst')) + vc + ([],[],Constraint.empty) in + let vc' = Array.of_list jlc in + let issmall,isunit = small_unit constrsinfos (env_ar_par,short_arity) in + (issmall,isunit,vc', cst) + +let type_inductive env mie = + (* We first type params and arity of each inductive definition *) + (* This allows to build the environment of arities and to share *) + (* the set of constraints *) + let cst, arities, rev_params_arity_list = + List.fold_left + (fun (cst,arities,l) ind -> + (* Params are typed-checked here *) + let params = ind.mind_entry_params in + let env_params, params, cst1 = + infer_local_decls env params in + (* Arities (without params) are typed-checked here *) + let arity, cst2 = + infer_type env_params ind.mind_entry_arity in + (* We do not need to generate the universe of full_arity; if + later, after the validation of the inductive definition, + full_arity is used as argument or subject to cast, an + upper universe will be generated *) + let id = ind.mind_entry_typename in + let full_arity = it_mkProd_or_LetIn arity.utj_val params in + Constraint.union cst (Constraint.union cst1 cst2), + Sign.add_rel_decl (Name id, None, full_arity) arities, + (params, id, full_arity, arity.utj_val)::l) + (Constraint.empty,empty_rel_context,[]) + mie.mind_entry_inds in + + let env_arities = push_rel_context arities env in + + let params_arity_list = List.rev rev_params_arity_list in + + (* Now, we type the constructors (without params) *) + let inds,cst = + List.fold_right2 + (fun ind (params,id,full_arity,short_arity) (inds,cst) -> + let (_,arsort) = dest_arity env full_arity in + let lc = ind.mind_entry_lc in + let (issmall,isunit,lc',cst') = + infer_constructor_packet env_arities params short_arity arsort lc + in + let nparams = ind.mind_entry_nparams in + let consnames = ind.mind_entry_consnames in + let ind' = (params,nparams,id,full_arity,consnames,issmall,isunit,lc') + in + (ind'::inds, Constraint.union cst cst')) + mie.mind_entry_inds + params_arity_list + ([],cst) in + (env_arities, inds, cst) + +(***********************************************************************) +(***********************************************************************) let allowed_sorts issmall isunit = function | Type _ -> @@ -118,7 +265,7 @@ exception IllFormedInd of ill_formed_ind let explain_ind_err ntyp env0 nbpar c err = let (lpar,c') = mind_extract_params nbpar c in - let env = push_rels lpar env0 in + let env = push_rel_context lpar env0 in match err with | LocalNonPos kt -> raise (InductiveError (NonPos (env,c',mkRel (kt+nbpar)))) @@ -150,8 +297,8 @@ let check_correct_par env hyps nparams ntypes n l largs = | [] -> () | (_,Some _,_)::hyps -> check k (index+1) hyps | _::hyps -> - match kind_of_term (whd_betadeltaiotaeta env Evd.empty lpar.(k)) with - | IsRel w when w = index -> check (k-1) (index+1) hyps + match kind_of_term (whd_betadeltaiota env lpar.(k)) with + | Rel w when w = index -> check (k-1) (index+1) hyps | _ -> raise (IllFormedInd (LocalNonPar (k+1,l))) in check (nparams-1) (n-nhyps) hyps; if not (array_for_all (noccur_between n ntypes) largs') then @@ -166,20 +313,20 @@ let abstract_mind_lc env ntyps npars lc = list_tabulate (function i -> lambda_implicit_lift npars (mkRel (i+1))) ntyps in - Array.map (compose nf_beta (substl make_abs)) lc + Array.map (substl make_abs) lc let listrec_mconstr env ntypes hyps nparams i indlc = let nhyps = List.length hyps in (* check the inductive types occur positively in [c] *) let rec check_pos env n c = - let x,largs = whd_betadeltaiota_stack env Evd.empty c in + let x,largs = decompose_app (whd_betadeltaiota env c) in match kind_of_term x with - | IsProd (na,b,d) -> + | Prod (na,b,d) -> assert (largs = []); if not (noccur_between n ntypes b) then raise (IllFormedInd (LocalNonPos n)); - check_pos (push_rel_assum (na, b) env) (n+1) d - | IsRel k -> + check_pos (push_rel (na, None, b) env) (n+1) d + | Rel k -> if k >= n && k<n+ntypes then begin check_correct_par env hyps nparams ntypes n (k-n+1) largs; Mrec(n+ntypes-k-1) @@ -189,7 +336,7 @@ let listrec_mconstr env ntypes hyps nparams i indlc = else Norec else raise (IllFormedInd (LocalNonPos n)) - | IsMutInd ind_sp -> + | Ind ind_sp -> if List.for_all (noccur_between n ntypes) largs then Norec else Imbr(ind_sp,imbr_positive env n ind_sp largs) @@ -199,27 +346,29 @@ let listrec_mconstr env ntypes hyps nparams i indlc = then Norec else raise (IllFormedInd (LocalNonPos n)) + (* accesses to the environment are not factorised, but does it worth + it? *) and imbr_positive env n mi largs = - let mispeci = lookup_mind_specif mi env in - let auxnpar = mis_nparams mispeci in + let (mib,mip) = lookup_mind_specif env mi in + let auxnpar = mip.mind_nparams in let (lpar,auxlargs) = list_chop auxnpar largs in if not (List.for_all (noccur_between n ntypes) auxlargs) then raise (IllFormedInd (LocalNonPos n)); - let auxlc = mis_nf_lc mispeci - and auxntyp = mis_ntypes mispeci in + let auxlc = arities_of_constructors env mi in + let auxntyp = mib.mind_ntypes in if auxntyp <> 1 then raise (IllFormedInd (LocalNonPos n)); let lrecargs = List.map (check_weak_pos env n) lpar in (* The abstract imbricated inductive type with parameters substituted *) let auxlcvect = abstract_mind_lc env auxntyp auxnpar auxlc in let newidx = n + auxntyp in (* Extends the environment with a variable corresponding to the inductive def *) - let env' = push_rel_assum (Anonymous,mis_arity mispeci) env in + let env' = push_rel (Anonymous,None,type_of_inductive env mi) env in let _ = (* fails if the inductive type occurs non positively *) (* when substituted *) Array.map (function c -> - let c' = hnf_prod_applist env Evd.empty c + let c' = hnf_prod_applist env c (List.map (lift auxntyp) lpar) in check_construct env' false newidx c') auxlcvect @@ -240,16 +389,16 @@ let listrec_mconstr env ntypes hyps nparams i indlc = Abstractions may occur in imbricated recursive ocurrences, but I am not sure if they make sense in a form of constructor. This is why I chose to duplicated the code. Eduardo 13/7/99. *) - (* Since Lambda can no longer occur after a product or a MutInd, + (* Since Lambda can no longer occur after a product or a Ind, I have branched the remaining cases on check_pos. HH 28/1/00 *) and check_weak_pos env n c = - let x = whd_betadeltaiota env Evd.empty c in + let x = whd_betadeltaiota env c in match kind_of_term x with (* The extra case *) - | IsLambda (na,b,d) -> + | Lambda (na,b,d) -> if noccur_between n ntypes b - then check_weak_pos (push_rel_assum (na,b) env) (n+1) d + then check_weak_pos (push_rel (na,None,b) env) (n+1) d else raise (IllFormedInd (LocalNonPos n)) (******************) | _ -> check_pos env n x @@ -260,29 +409,29 @@ let listrec_mconstr env ntypes hyps nparams i indlc = and check_construct env check_head = let rec check_constr_rec env lrec n c = - let x,largs = whd_betadeltaiota_stack env Evd.empty c in + let x,largs = decompose_app (whd_betadeltaiota env c) in match kind_of_term x with - | IsProd (na,b,d) -> + | Prod (na,b,d) -> assert (largs = []); let recarg = check_pos env n b in - check_constr_rec (push_rel_assum (na, b) env) + check_constr_rec (push_rel (na, None, b) env) (recarg::lrec) (n+1) d (* LetIn's must be free of occurrence of the inductive types and they do not contribute to recargs *) - | IsLetIn (na,b,t,d) -> + | LetIn (na,b,t,d) -> assert (largs = []); if not (noccur_between n ntypes b & noccur_between n ntypes t) then - check_constr_rec (push_rel_def (na,b, b) env) + check_constr_rec (push_rel (na,Some b, b) env) lrec n (subst1 b d) else let recarg = check_pos env n b in - check_constr_rec (push_rel_def (na,b, b) env) + check_constr_rec (push_rel (na,Some b, b) env) lrec (n+1) d | hd -> if check_head then - if hd = IsRel (n+ntypes-i) then + if hd = Rel (n+ntypes-i) then check_correct_par env hyps nparams ntypes n (ntypes-i+1) largs else raise (IllFormedInd LocalNotConstructor) @@ -296,7 +445,7 @@ let listrec_mconstr env ntypes hyps nparams i indlc = (fun c -> let c = body_of_type c in let sign, rawc = mind_extract_params nhyps c in - let env' = push_rels sign env in + let env' = push_rel_context sign env in try check_construct env' true (1+nhyps) rawc with IllFormedInd err -> @@ -317,19 +466,19 @@ let abstract_inductive ntypes hyps (par,np,id,arity,cnames,issmall,isunit,lc) = let nhyps = List.length hyps in let nparams = Array.length args in (* nparams = nhyps - nb(letin) *) let new_refs = - list_tabulate (fun k -> appvect(mkRel (k+nhyps+1),args)) ntypes in + list_tabulate (fun k -> mkApp (mkRel (k+nhyps+1),args)) ntypes in let abs_constructor b = it_mkNamedProd_or_LetIn (substl new_refs b) hyps in let lc' = Array.map abs_constructor lc in let arity' = it_mkNamedProd_or_LetIn arity hyps in let par' = push_named_to_rel_context hyps par in (par',np+nparams,id,arity',cnames,issmall,isunit,lc') -let cci_inductive locals env env_ar kind finite inds cst = +let cci_inductive env env_ar finite inds cst = let ntypes = List.length inds in let ids = List.fold_left (fun acc (_,_,_,ar,_,_,_,lc) -> - Idset.union (global_vars_set env (body_of_type ar)) + Idset.union (Environ.global_vars_set env (body_of_type ar)) (Array.fold_left (fun acc c -> Idset.union (global_vars_set env (body_of_type c)) acc) @@ -337,41 +486,46 @@ let cci_inductive locals env env_ar kind finite inds cst = lc)) Idset.empty inds in - let hyps = keep_hyps env ids (named_context env) in + let hyps = keep_hyps env ids in let one_packet i (params,nparams,id,ar,cnames,issmall,isunit,lc) = let recargs = listrec_mconstr env_ar ntypes params nparams i lc in let isunit = isunit && ntypes = 1 && (not (is_recursive [0] recargs)) in - let (ar_sign,ar_sort) = splay_arity env Evd.empty (body_of_type ar) in + let (ar_sign,ar_sort) = dest_arity env ar in - let nf_ar,user_ar = - if isArity (body_of_type ar) then ar,None - else (prod_it (mkSort ar_sort) ar_sign, Some ar) in + let nf_ar = + if isArity (body_of_type ar) then ar + else it_mkProd_or_LetIn (mkSort ar_sort) ar_sign in let kelim = allowed_sorts issmall isunit ar_sort in - let lc_bodies = Array.map body_of_type lc in - let splayed_lc = Array.map (splay_prod_assum env_ar Evd.empty) lc_bodies in + let splayed_lc = Array.map (dest_prod_assum env_ar) lc in let nf_lc = array_map2 (fun (d,b) c -> it_mkProd_or_LetIn b d) splayed_lc lc in - let nf_lc,user_lc = if nf_lc = lc then lc,None else nf_lc, Some lc in + let nf_lc = if nf_lc = lc then lc else nf_lc in { mind_consnames = Array.of_list cnames; mind_typename = id; - mind_user_lc = user_lc; + mind_user_lc = lc; mind_nf_lc = nf_lc; - mind_user_arity = user_ar; + mind_user_arity = ar; mind_nf_arity = nf_ar; mind_nrealargs = List.length ar_sign - nparams; mind_sort = ar_sort; mind_kelim = kelim; mind_listrec = recargs; - mind_finite = finite; mind_nparams = nparams; mind_params_ctxt = params } in - let sp_hyps = List.map (fun (id,b,t) -> (List.assoc id locals,b,t)) hyps in let packets = Array.of_list (list_map_i one_packet 1 inds) in - { mind_kind = kind; - mind_ntypes = ntypes; - mind_hyps = sp_hyps; + { mind_ntypes = ntypes; + mind_finite = finite; + mind_hyps = hyps; mind_packets = packets; mind_constraints = cst; mind_singl = None } + +(***********************************************************************) +(***********************************************************************) + +let check_inductive env mie = + mind_check_wellformed env mie; + let (env_arities, inds, cst) = type_inductive env mie in + cci_inductive env env_arities mie.mind_entry_finite inds cst |