aboutsummaryrefslogtreecommitdiffhomepage
path: root/kernel/typeops.ml
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/typeops.ml')
-rw-r--r--kernel/typeops.ml1146
1 files changed, 339 insertions, 807 deletions
diff --git a/kernel/typeops.ml b/kernel/typeops.ml
index e8e8f35b9..a2c6fe686 100644
--- a/kernel/typeops.ml
+++ b/kernel/typeops.ml
@@ -8,7 +8,6 @@
(* $Id$ *)
-open Pp
open Util
open Names
open Univ
@@ -18,48 +17,42 @@ open Sign
open Environ
open Reduction
open Inductive
-
open Type_errors
-let make_judge v tj =
- { uj_val = v;
- uj_type = tj }
-
-let j_val j = j.uj_val
-(* This should be a type intended to be assumed *)
-let assumption_of_judgment env sigma j =
- match kind_of_term(whd_betadeltaiota env sigma (body_of_type j.uj_type)) with
- | IsSort s -> j.uj_val
- | _ -> error_assumption CCI env j.uj_val
+(* This should be a type (a priori without intension to be an assumption) *)
+let type_judgment env j =
+ match kind_of_term(whd_betadeltaiota env (body_of_type j.uj_type)) with
+ | Sort s -> {utj_val = j.uj_val; utj_type = s }
+ | _ -> error_not_type env j
+
+(* This should be a type intended to be assumed. The error message is *)
+(* not as useful as for [type_judgment]. *)
+let assumption_of_judgment env j =
+ try (type_judgment env j).utj_val
+ with TypeError _ ->
+ error_assumption env j
(*
let aojkey = Profile.declare_profile "assumption_of_judgment";;
-let assumption_of_judgment env sigma j
- = Profile.profile3 aojkey assumption_of_judgment env sigma j;;
+let assumption_of_judgment env j
+ = Profile.profile2 aojkey assumption_of_judgment env j;;
*)
-(* This should be a type (a priori without intension to be an assumption) *)
-let type_judgment env sigma j =
- match kind_of_term(whd_betadeltaiota env sigma (body_of_type j.uj_type)) with
- | IsSort s -> {utj_val = j.uj_val; utj_type = s }
- | _ -> error_not_type CCI env j
-
-
(************************************************)
(* Incremental typing rules: builds a typing judgement given the *)
(* judgements for the subterms. *)
-(* Type of sorts *)
+(*s Type of sorts *)
(* Prop and Set *)
let judge_of_prop =
- { uj_val = mkSort prop;
+ { uj_val = mkProp;
uj_type = mkSort type_0 }
let judge_of_set =
- { uj_val = mkSort spec;
+ { uj_val = mkSet;
uj_type = mkSort type_0 }
let judge_of_prop_contents = function
@@ -70,92 +63,84 @@ let judge_of_prop_contents = function
let judge_of_type u =
let (uu,c) = super u in
- { uj_val = mkSort (Type u);
- uj_type = mkSort (Type uu) },
+ { uj_val = mkType u;
+ uj_type = mkType uu },
c
-(*
-let type_of_sort c =
- match kind_of_term c with
- | IsSort (Type u) -> let (uu,cst) = super u in Type uu, cst
- | IsSort (Prop _) -> Type prop_univ, Constraint.empty
- | _ -> invalid_arg "type_of_sort"
-*)
-
-(* Type of a de Bruijn index. *)
+(*s Type of a de Bruijn index. *)
-let relative env n =
+let judge_of_relative env n =
try
- let (_,typ) = lookup_rel_type n env in
+ let (_,_,typ) = lookup_rel n env in
{ uj_val = mkRel n;
uj_type = type_app (lift n) typ }
with Not_found ->
- error_unbound_rel CCI env n
+ error_unbound_rel env n
(*
-let relativekey = Profile.declare_profile "relative";;
-let relative env sigma n = Profile.profile3 relativekey relative env sigma n;;
+let relativekey = Profile.declare_profile "judge_of_relative";;
+let judge_of_relative env n =
+ Profile.profile2 relativekey judge_of_relative env n;;
*)
(* Management of context of variables. *)
-(* Checks if a context of variable is included in another one. *)
-(*
-let rec hyps_inclusion env sigma sign1 sign2 =
- if sign1 = empty_named_context then true
- else
- let (id1,ty1) = hd_sign sign1 in
- let rec search sign2 =
- if sign2 = empty_named_context then false
- else
- let (id2,ty2) = hd_sign sign2 in
- if id1 = id2 then
- (is_conv env sigma (body_of_type ty1) (body_of_type ty2))
- &
- hyps_inclusion env sigma (tl_sign sign1) (tl_sign sign2)
- else
- search (tl_sign sign2)
- in
- search sign2
-*)
+(* Checks if a context of variable can be instanciated by the
+ variables of the current env *)
+(* TODO: check order? *)
+let rec check_hyps_inclusion env sign =
+ let env_sign = named_context env in
+ Sign.fold_named_context
+ (fun (id,_,ty1) () ->
+ let (_,_,ty2) = Sign.lookup_named id env_sign in
+ if not (eq_constr ty2 ty1) then
+ error "types do not match")
+ sign
+ ()
+
+
+let check_args env c hyps =
+ let hyps' = named_context env in
+ try check_hyps_inclusion env hyps
+ with UserError _ | Not_found ->
+ error_reference_variables env c
+
(* Checks if the given context of variables [hyps] is included in the
current context of [env]. *)
(*
-let check_hyps id env sigma hyps =
+let check_hyps id env hyps =
let hyps' = named_context env in
- if not (hyps_inclusion env sigma hyps hyps') then
- error_reference_variables CCI env id
+ if not (hyps_inclusion env hyps hyps') then
+ error_reference_variables env id
*)
(* Instantiation of terms on real arguments. *)
-let type_of_constant = Instantiate.constant_type
+(* Type of variables *)
+let judge_of_variable env id =
+ try
+ let (_,_,ty) = lookup_named id env in
+ make_judge (mkVar id) ty
+ with Not_found ->
+ error ("execute: variable " ^ (string_of_id id) ^ " not defined")
+
+(* Type of constants *)
+let judge_of_constant env cst =
+ let constr = mkConst cst in
+ let _ =
+ let ce = lookup_constant cst env in
+ check_args env constr ce.const_hyps in
+ make_judge constr (constant_type env cst)
(*
let tockey = Profile.declare_profile "type_of_constant";;
-let type_of_constant env sigma c
- = Profile.profile3 tockey type_of_constant env sigma c;;
+let type_of_constant env c
+ = Profile.profile3 tockey type_of_constant env c;;
*)
-(* Type of an existential variable. Not used in kernel. *)
-let type_of_existential env sigma ev =
- Instantiate.existential_type sigma ev
-
-
(* Type of a lambda-abstraction. *)
-let sort_of_product domsort rangsort g =
- match rangsort with
- (* Product rule (s,Prop,Prop) *)
- | Prop _ -> rangsort, Constraint.empty
- | Type u2 ->
- (match domsort with
- (* Product rule (Prop,Type_i,Type_i) *)
- | Prop _ -> rangsort, Constraint.empty
- (* Product rule (Type_i,Type_i,Type_i) *)
- | Type u1 -> let (u12,cst) = sup u1 u2 g in Type u12, cst)
-
-(* [abs_rel env sigma name var j] implements the rule
+(* [judge_of_abstraction env name var j] implements the rule
env, name:typ |- j.uj_val:j.uj_type env, |- (name:typ)j.uj_type : s
-----------------------------------------------------------------------
@@ -165,788 +150,335 @@ let sort_of_product domsort rangsort g =
and no upper constraint exists on the sort $s$, we don't need to compute $s$
*)
-let abs_rel env sigma name var j =
- { uj_val = mkLambda (name, var, j.uj_val);
- uj_type = mkProd (name, var, j.uj_type) },
- Constraint.empty
+let judge_of_abstraction env name var j =
+ { uj_val = mkLambda (name, var.utj_val, j.uj_val);
+ uj_type = mkProd (name, var.utj_val, j.uj_type) }
+
+(* Type of let-in. *)
-let judge_of_letin env sigma name defj j =
+let judge_of_letin env name defj j =
let v = match kind_of_term defj.uj_val with
- IsCast(c,t) -> c
+ Cast(c,t) -> c
| _ -> defj.uj_val in
- ({ uj_val = mkLetIn (name, v, defj.uj_type, j.uj_val) ;
- uj_type = type_app (subst1 v) j.uj_type },
- Constraint.empty)
-
-(* [gen_rel env sigma name (typ1,s1) (typ2,s2)] implements the rule
-
- env |- typ1:s1 env, name:typ |- typ2 : s2
- -------------------------------------------------------------------------
- s' >= (s1,s2), env |- (name:typ)j.uj_val : s'
-
- where j.uj_type is convertible to a sort s2
-*)
+ { uj_val = mkLetIn (name, v, defj.uj_type, j.uj_val) ;
+ uj_type = type_app (subst1 v) j.uj_type }
(* Type of an application. *)
-let apply_rel_list env sigma nocheck argjl funj =
+let judge_of_apply env funj argjv =
let rec apply_rec n typ cst = function
| [] ->
- { uj_val = applist (j_val funj, List.map j_val argjl);
- uj_type = type_app (fun _ -> typ) funj.uj_type },
+ { uj_val = mkApp (j_val funj, Array.map j_val argjv);
+ uj_type = typ },
cst
| hj::restjl ->
- match kind_of_term (whd_betadeltaiota env sigma typ) with
- | IsProd (_,c1,c2) ->
- if nocheck then
- apply_rec (n+1) (subst1 hj.uj_val c2) cst restjl
- else
- (try
- let c = conv_leq env sigma (body_of_type hj.uj_type) c1 in
- let cst' = Constraint.union cst c in
- apply_rec (n+1) (subst1 hj.uj_val c2) cst' restjl
- with NotConvertible ->
- error_cant_apply_bad_type CCI env
- (n,c1,body_of_type hj.uj_type)
- funj argjl)
+ (match kind_of_term (whd_betadeltaiota env typ) with
+ | Prod (_,c1,c2) ->
+ (try
+ let c = conv_leq env hj.uj_type c1 in
+ let cst' = Constraint.union cst c in
+ apply_rec (n+1) (subst1 hj.uj_val c2) cst' restjl
+ with NotConvertible ->
+ error_cant_apply_bad_type env
+ (n,c1,body_of_type hj.uj_type)
+ funj argjv)
| _ ->
- error_cant_apply_not_functional CCI env funj argjl
+ error_cant_apply_not_functional env funj argjv)
in
- apply_rec 1 (body_of_type funj.uj_type) Constraint.empty argjl
+ apply_rec 1
+ funj.uj_type
+ Constraint.empty
+ (Array.to_list argjv)
(*
-let applykey = Profile.declare_profile "apply_rel_list";;
-let apply_rel_list env sigma nocheck argjl funj
- = Profile.profile5 applykey apply_rel_list env sigma nocheck argjl funj;;
+let applykey = Profile.declare_profile "judge_of_apply";;
+let judge_of_apply env nocheck funj argjl
+ = Profile.profile5 applykey judge_of_apply env nocheck funj argjl;;
*)
+
(* Type of product *)
-let gen_rel env sigma name t1 t2 =
+
+let sort_of_product domsort rangsort g =
+ match rangsort with
+ (* Product rule (s,Prop,Prop) *)
+ | Prop _ -> rangsort, Constraint.empty
+ | Type u2 ->
+ (match domsort with
+ (* Product rule (Prop,Type_i,Type_i) *)
+ | Prop _ -> rangsort, Constraint.empty
+ (* Product rule (Type_i,Type_i,Type_i) *)
+ | Type u1 -> let (u12,cst) = sup u1 u2 g in Type u12, cst)
+
+(* [judge_of_product env name (typ1,s1) (typ2,s2)] implements the rule
+
+ env |- typ1:s1 env, name:typ1 |- typ2 : s2
+ -------------------------------------------------------------------------
+ s' >= (s1,s2), env |- (name:typ)j.uj_val : s'
+
+ where j.uj_type is convertible to a sort s2
+*)
+let judge_of_product env name t1 t2 =
let (s,g) = sort_of_product t1.utj_type t2.utj_type (universes env) in
{ uj_val = mkProd (name, t1.utj_val, t2.utj_val);
uj_type = mkSort s },
g
-(* [cast_rel env sigma (typ1,s1) j] implements the rule
+(* Type of a type cast *)
+
+(* [judge_of_cast env (c,typ1) (typ2,s)] implements the rule
- env, sigma |- cj.uj_val:cj.uj_type cst, env, sigma |- cj.uj_type = t
+ env |- c:typ1 env |- typ2:s env |- typ1 <= typ2
---------------------------------------------------------------------
- cst, env, sigma |- cj.uj_val:t
+ env |- c:typ2
*)
-(* Type of casts *)
-let cast_rel env sigma cj t =
+let judge_of_cast env cj tj =
try
- let cst = conv_leq env sigma (body_of_type cj.uj_type) t in
+ let cst = conv_leq env cj.uj_type tj.utj_val in
{ uj_val = j_val cj;
- uj_type = t },
+ uj_type = tj.utj_val },
cst
with NotConvertible ->
- error_actual_type CCI env cj.uj_val (body_of_type cj.uj_type) t
+ error_actual_type env cj tj.utj_val
(* Inductive types. *)
-let type_of_inductive env sigma i =
- (* TODO: check args *)
- mis_arity (lookup_mind_specif i env)
+let judge_of_inductive env i =
+ let constr = mkInd i in
+ let _ =
+ let (sp,_) = i in
+ let mib = lookup_mind sp env in
+ check_args env constr mib.mind_hyps in
+ make_judge constr (type_of_inductive env i)
(*
-let toikey = Profile.declare_profile "type_of_inductive";;
-let type_of_inductive env sigma i
- = Profile.profile3 toikey type_of_inductive env sigma i;;
+let toikey = Profile.declare_profile "judge_of_inductive";;
+let judge_of_inductive env i
+ = Profile.profile2 toikey judge_of_inductive env i;;
*)
(* Constructors. *)
-let type_of_constructor env sigma cstr =
- mis_constructor_type
- (index_of_constructor cstr)
- (lookup_mind_specif (inductive_of_constructor cstr) env)
+let judge_of_constructor env c =
+ let constr = mkConstruct c in
+ let _ =
+ let ((sp,_),_) = c in
+ let mib = lookup_mind sp env in
+ check_args env constr mib.mind_hyps in
+ make_judge constr (type_of_constructor env c)
(*
-let tockey = Profile.declare_profile "type_of_constructor";;
-let type_of_constructor env sigma cstr
- = Profile.profile3 tockey type_of_constructor env sigma cstr;;
+let tockey = Profile.declare_profile "judge_of_constructor";;
+let judge_of_constructor env cstr
+ = Profile.profile2 tockey judge_of_constructor env cstr;;
*)
(* Case. *)
-let rec mysort_of_arity env sigma c =
- match kind_of_term (whd_betadeltaiota env sigma c) with
- | IsSort s -> s
- | IsProd(_,_,c2) -> mysort_of_arity env sigma c2
- | _ -> invalid_arg "mysort_of_arity"
-
-let error_elim_expln env sigma kp ki =
- if is_info_arity env sigma kp && not (is_info_arity env sigma ki) then
- "non-informative objects may not construct informative ones."
- else
- match (kind_of_term kp,kind_of_term ki) with
- | IsSort (Type _), IsSort (Prop _) ->
- "strong elimination on non-small inductive types leads to paradoxes."
- | _ -> "wrong arity"
-
-exception Arity of (constr * constr * string) option
-
-let is_correct_arity env sigma kelim (c,pj) indf t =
- let rec srec (pt,t) u =
- let pt' = whd_betadeltaiota env sigma pt in
- let t' = whd_betadeltaiota env sigma t in
- match kind_of_term pt', kind_of_term t' with
- | IsProd (_,a1,a2), IsProd (_,a1',a2') ->
- let univ =
- try conv env sigma a1 a1'
- with NotConvertible -> raise (Arity None) in
- srec (a2,a2') (Constraint.union u univ)
- | IsProd (_,a1,a2), _ ->
- let k = whd_betadeltaiota env sigma a2 in
- let ksort = match kind_of_term k with
- | IsSort s -> family_of_sort s
- | _ -> raise (Arity None) in
- let ind = build_dependent_inductive indf in
- let univ =
- try conv env sigma a1 ind
- with NotConvertible -> raise (Arity None) in
- if List.exists ((=) ksort) kelim then
- ((true,k), Constraint.union u univ)
- else
- raise (Arity (Some(k,t',error_elim_expln env sigma k t')))
- | k, IsProd (_,_,_) ->
- raise (Arity None)
- | k, ki ->
- let ksort = match k with
- | IsSort s -> family_of_sort s
- | _ -> raise (Arity None) in
- if List.exists ((=) ksort) kelim then
- (false, pt'), u
- else
- raise (Arity (Some(pt',t',error_elim_expln env sigma pt' t')))
- in
- try srec (pj.uj_type,t) Constraint.empty
- with Arity kinds ->
- let create_sort = function
- | InProp -> prop
- | InSet -> spec
- | InType -> Type (Univ.new_univ ()) in
- let listarity =
- (List.map (fun s -> make_arity env true indf (create_sort s)) kelim)
- @(List.map (fun s -> make_arity env false indf (create_sort s)) kelim)
- in
- let ind = mis_inductive (fst (dest_ind_family indf)) in
- error_elim_arity CCI env ind listarity c pj kinds
-
-
-let find_case_dep_nparams env sigma (c,pj) (IndFamily (mis,_) as indf) =
- let kelim = mis_kelim mis in
- let arsign,s = get_arity indf in
- let glob_t = it_mkProd_or_LetIn (mkSort s) arsign in
- let ((dep,_),univ) =
- is_correct_arity env sigma kelim (c,pj) indf glob_t in
- (dep,univ)
-
-(* type_case_branches type un <p>Case c of ... end
- IndType (indf,realargs) = type de c
- pt = sorte de p
- type_case_branches retourne (lb, lr); lb est le vecteur des types
- attendus dans les branches du Case; lr est le type attendu du resultat
- *)
-
-let type_case_branches env sigma (IndType (indf,realargs)) pj c =
- let p = pj.uj_val in
- let (dep,univ) = find_case_dep_nparams env sigma (c,pj) indf in
- let constructs = get_constructors indf in
- let lc = Array.map (build_branch_type env dep p) constructs in
- if dep then
- (lc, beta_applist (p,(realargs@[c])), univ)
- else
- (lc, beta_applist (p,realargs), univ)
-
-let check_branches_message env sigma cj (explft,lft) =
- let expn = Array.length explft and n = Array.length lft in
- if n<>expn then error_number_branches CCI env cj expn;
- let univ = ref Constraint.empty in
- (for i = 0 to n-1 do
- try
- univ := Constraint.union !univ
- (conv_leq env sigma lft.(i) (explft.(i)))
- with NotConvertible ->
- error_ill_formed_branch CCI env cj.uj_val i lft.(i) explft.(i)
- done;
- !univ)
-
-let nparams_of (IndType (IndFamily (mis,_),_)) = mis_nparams mis
-
-let judge_of_case env sigma (np,_ as ci) pj cj lfj =
- let lft = Array.map (fun j -> body_of_type j.uj_type) lfj in
+let check_branch_types env cj (lft,explft) =
+ try conv_leq_vecti env lft explft
+ with
+ NotConvertibleVect i ->
+ error_ill_formed_branch env cj.uj_val i lft.(i) explft.(i)
+ | Invalid_argument _ ->
+ error_number_branches env cj (Array.length explft)
+
+let judge_of_case env ci pj cj lfj =
let indspec =
- try find_rectype env sigma (body_of_type cj.uj_type)
- with Induc -> error_case_not_inductive CCI env cj in
- if np <> nparams_of indspec then
- anomaly "judge_of_case: wrong parameters number";
- let (bty,rslty,univ) = type_case_branches env sigma indspec pj cj.uj_val in
- let kind = mysort_of_arity env sigma (body_of_type pj.uj_type) in
- let univ' = check_branches_message env sigma cj (bty,lft) in
- ({ uj_val = mkMutCase (ci, (nf_betaiota pj.uj_val), cj.uj_val, Array.map j_val lfj);
+ try find_rectype env cj.uj_type
+ with Induc -> error_case_not_inductive env cj in
+ let _ = check_case_info env (fst indspec) ci in
+ let (bty,rslty,univ) =
+ type_case_branches env indspec pj cj.uj_val in
+ let (_,kind) = dest_arity env pj.uj_type in
+ let lft = Array.map j_type lfj in
+ let univ' = check_branch_types env cj (lft,bty) in
+ ({ uj_val = mkCase (ci, nf_betaiota pj.uj_val, cj.uj_val,
+ Array.map j_val lfj);
uj_type = rslty },
Constraint.union univ univ')
(*
-let tocasekey = Profile.declare_profile "type_of_case";;
-let type_of_case env sigma ci pj cj lfj
- = Profile.profile6 tocasekey type_of_case env sigma ci pj cj lfj;;
+let tocasekey = Profile.declare_profile "judge_of_case";;
+let judge_of_case env ci pj cj lfj
+ = Profile.profile6 tocasekey judge_of_case env ci pj cj lfj;;
*)
(* Fixpoints. *)
-(* Check if t is a subterm of Rel n, and gives its specification,
- assuming lst already gives index of
- subterms with corresponding specifications of recursive arguments *)
-
-(* A powerful notion of subterm *)
-
-let find_sorted_assoc p =
- let rec findrec = function
- | (a,ta)::l ->
- if a < p then findrec l else if a = p then ta else raise Not_found
- | _ -> raise Not_found
- in
- findrec
-
-let map_lift_fst_n m = List.map (function (n,t)->(n+m,t))
-let map_lift_fst = map_lift_fst_n 1
-
-let rec instantiate_recarg sp lrc ra =
- match ra with
- | Mrec(j) -> Imbr((sp,j),lrc)
- | Imbr(ind_sp,l) -> Imbr(ind_sp, List.map (instantiate_recarg sp lrc) l)
- | Norec -> Norec
- | Param(k) -> List.nth lrc k
-
-(* To each inductive definition corresponds an array describing the
- structure of recursive arguments for each constructor, we call it
- the recursive spec of the type (it has type recargs vect). For
- checking the guard, we start from the decreasing argument (Rel n)
- with its recursive spec. During checking the guardness condition,
- we collect patterns variables corresponding to subterms of n, each
- of them with its recursive spec. They are organised in a list lst
- of type (int * recargs) list which is sorted with respect to the
- first argument.
-*)
-
-(*
- f is a function of type
- env -> int -> (int * recargs) list -> constr -> 'a
-
- c is a branch of an inductive definition corresponding to the spec
- lrec. mind_recvec is the recursive spec of the inductive
- definition of the decreasing argument n.
-
- check_term env mind_recvec f n lst (lrec,c) will pass the lambdas
- of c corresponding to pattern variables and collect possibly new
- subterms variables and apply f to the body of the branch with the
- correct env and decreasing arg.
-*)
-
-let check_term env mind_recvec f =
- let rec crec env n lst (lrec,c) =
- let c' = strip_outer_cast c in
- match lrec, kind_of_term c' with
- (ra::lr,IsLambda (x,a,b)) ->
- let lst' = map_lift_fst lst
- and env' = push_rel_assum (x,a) env
- and n'=n+1
- in begin match ra with
- Mrec(i) -> crec env' n' ((1,mind_recvec.(i))::lst') (lr,b)
- | Imbr((sp,i) as ind_sp,lrc) ->
- let sprecargs =
- mis_recargs (lookup_mind_specif ind_sp env) in
- let lc = Array.map
- (List.map (instantiate_recarg sp lrc)) sprecargs.(i)
- in crec env' n' ((1,lc)::lst') (lr,b)
- | _ -> crec env' n' lst' (lr,b) end
- | (_,IsLetIn (x,c,a,b)) ->
- let env' = push_rel_def (x,c,a) env in
- crec env' (n+1) (map_lift_fst lst) (lrec,(subst1 c b))
- | (_,_) -> f env n lst c'
- in crec env
-
-(* c is supposed to be in beta-delta-iota head normal form *)
-
-let is_inst_var k c =
- match kind_of_term (fst (decomp_app c)) with
- | IsRel n -> n=k
- | _ -> false
-
-(*
- is_subterm_specif env sigma lcx mind_recvec n lst c
-
- n is the principal arg and has recursive spec lcx, lst is the list
- of subterms of n with spec. is_subterm_specif should test if c is
- a subterm of n and fails with Not_found if not. In case it is, it
- should send its recursive specification. This recursive spec
- should be the same size as the number of constructors of the type
- of c. A problem occurs when c is built by contradiction. In that
- case no spec is given.
-
-*)
-let is_subterm_specif env sigma lcx mind_recvec =
- let rec crec env n lst c =
- let f,l = whd_betadeltaiota_stack env sigma c in
- match kind_of_term f with
- | IsRel k -> Some (find_sorted_assoc k lst)
-
- | IsMutCase ( _,_,c,br) ->
- if Array.length br = 0 then None
-
- else
- let def = Array.create (Array.length br) []
- in let lcv =
- (try
- if is_inst_var n c then lcx
- else match crec env n lst c with Some lr -> lr | None -> def
- with Not_found -> def)
- in
- assert (Array.length br = Array.length lcv);
- let stl =
- array_map2
- (fun lc a ->
- check_term env mind_recvec crec n lst (lc,a)) lcv br
- in let stl0 = stl.(0) in
- if array_for_all (fun st -> st=stl0) stl then stl0
- else None
-
- | IsFix ((recindxs,i),(_,typarray,bodies as recdef)) ->
- let nbfix = Array.length typarray in
- let decrArg = recindxs.(i) in
- let theBody = bodies.(i) in
- let sign,strippedBody = decompose_lam_n_assum (decrArg+1) theBody in
- let nbOfAbst = nbfix+decrArg+1 in
-(* when proving that the fixpoint f(x)=e is less than n, it is enough
- to prove that e is less than n assuming f is less than n
- furthermore when f is applied to a term which is strictly less than
- n, one may assume that x itself is strictly less than n
-*)
- let newlst =
- let lst' = (nbOfAbst,lcx) :: (map_lift_fst_n nbOfAbst lst) in
- if List.length l < (decrArg+1) then lst'
- else let theDecrArg = List.nth l decrArg in
- try
- match crec env n lst theDecrArg with
- (Some recArgsDecrArg) -> (1,recArgsDecrArg) :: lst'
- | None -> lst'
- with Not_found -> lst'
- in let env' = push_rec_types recdef env in
- let env'' = push_rels sign env' in
- crec env'' (n+nbOfAbst) newlst strippedBody
-
- | IsLambda (x,a,b) when l=[] ->
- let lst' = map_lift_fst lst in
- crec (push_rel_assum (x, a) env) (n+1) lst' b
-
- (*** Experimental change *************************)
- | IsMeta _ -> None
- | _ -> raise Not_found
- in
- crec env
-
-let spec_subterm_strict env sigma lcx mind_recvec n lst c nb =
- try match is_subterm_specif env sigma lcx mind_recvec n lst c
- with Some lr -> lr | None -> Array.create nb []
- with Not_found -> Array.create nb []
+(* Checks the type of a general (co)fixpoint, i.e. without checking *)
+(* the specific guard condition. *)
-let spec_subterm_large env sigma lcx mind_recvec n lst c nb =
- if is_inst_var n c then lcx
- else spec_subterm_strict env sigma lcx mind_recvec n lst c nb
-
-
-let is_subterm env sigma lcx mind_recvec n lst c =
- try
- let _ = is_subterm_specif env sigma lcx mind_recvec n lst c in true
- with Not_found ->
- false
-
-
-exception FixGuardError of guard_error
-
-(* Auxiliary function: it checks a condition f depending on a deBrujin
- index for a certain number of abstractions *)
-
-let rec check_subterm_rec_meta env sigma vectn k def =
- (* If k<0, it is a general fixpoint *)
- (k < 0) or
- (let nfi = Array.length vectn in
- (* check fi does not appear in the k+1 first abstractions,
- gives the type of the k+1-eme abstraction *)
- let rec check_occur env n def =
- match kind_of_term (strip_outer_cast def) with
- | IsLambda (x,a,b) ->
- if noccur_with_meta n nfi a then
- let env' = push_rel_assum (x, a) env in
- if n = k+1 then (env', lift 1 a, b)
- else check_occur env' (n+1) b
- else
- anomaly "check_subterm_rec_meta: Bad occurrence of recursive call"
- | _ -> raise (FixGuardError NotEnoughAbstractionInFixBody) in
- let (env',c,d) = check_occur env 1 def in
- let ((sp,tyi) as mind, largs) =
- try find_inductive env' sigma c
- with Induc -> raise (FixGuardError RecursionNotOnInductiveType) in
- let mind_recvec = mis_recargs (lookup_mind_specif mind env') in
- let lcx = mind_recvec.(tyi) in
- (* n = decreasing argument in the definition;
- lst = a mapping var |-> recargs
- t = the term to be checked
- *)
- let rec check_rec_call env n lst t =
- (* n gives the index of the recursive variable *)
- (noccur_with_meta (n+k+1) nfi t) or
- (* no recursive call in the term *)
- (let f,l = whd_betaiotazeta_stack t in
- match kind_of_term f with
- | IsRel p ->
- if n+k+1 <= p & p < n+k+nfi+1 then
- (* recursive call *)
- let glob = nfi+n+k-p in (* the index of the recursive call *)
- let np = vectn.(glob) in (* the decreasing arg of the rec call *)
- if List.length l > np then
- (match list_chop np l with
- (la,(z::lrest)) ->
- if (is_subterm env sigma lcx mind_recvec n lst z)
- then List.for_all (check_rec_call env n lst) (la@lrest)
- else raise (FixGuardError RecursionOnIllegalTerm)
- | _ -> assert false)
- else raise (FixGuardError NotEnoughArgumentsForFixCall)
- else List.for_all (check_rec_call env n lst) l
-
- | IsMutCase (ci,p,c_0,lrest) ->
- let lc = spec_subterm_large env sigma lcx mind_recvec n lst c_0
- (Array.length lrest)
- in
- (array_for_all2
- (fun c0 a ->
- check_term env mind_recvec check_rec_call n lst (c0,a))
- lc lrest)
- && (List.for_all (check_rec_call env n lst) (c_0::p::l))
-
- (* Enables to traverse Fixpoint definitions in a more intelligent
- way, ie, the rule :
-
- if - g = Fix g/1 := [y1:T1]...[yp:Tp]e &
- - f is guarded with respect to the set of pattern variables S
- in a1 ... am &
- - f is guarded with respect to the set of pattern variables S
- in T1 ... Tp &
- - ap is a sub-term of the formal argument of f &
- - f is guarded with respect to the set of pattern variables S+{yp}
- in e
- then f is guarded with respect to S in (g a1 ... am).
-
- Eduardo 7/9/98 *)
-
- | IsFix ((recindxs,i),(_,typarray,bodies as recdef)) ->
- (List.for_all (check_rec_call env n lst) l) &&
- (array_for_all (check_rec_call env n lst) typarray) &&
- let nbfix = Array.length typarray in
- let decrArg = recindxs.(i)
- and env' = push_rec_types recdef env
- and n' = n+nbfix
- and lst' = map_lift_fst_n nbfix lst
- in
- if (List.length l < (decrArg+1)) then
- array_for_all (check_rec_call env' n' lst') bodies
- else
- let theDecrArg = List.nth l decrArg in
- (try
- match
- is_subterm_specif env sigma lcx mind_recvec n lst theDecrArg
- with
- Some recArgsDecrArg ->
- let theBody = bodies.(i) in
- check_rec_call_fix_body
- env' n' lst' (decrArg+1) recArgsDecrArg theBody
- | None ->
- array_for_all (check_rec_call env' n' lst') bodies
- with Not_found ->
- array_for_all (check_rec_call env' n' lst') bodies)
-
- | IsCast (a,b) ->
- (check_rec_call env n lst a) &&
- (check_rec_call env n lst b) &&
- (List.for_all (check_rec_call env n lst) l)
-
- | IsLambda (x,a,b) ->
- (check_rec_call env n lst a) &&
- (check_rec_call (push_rel_assum (x, a) env)
- (n+1) (map_lift_fst lst) b) &&
- (List.for_all (check_rec_call env n lst) l)
-
- | IsProd (x,a,b) ->
- (check_rec_call env n lst a) &&
- (check_rec_call (push_rel_assum (x, a) env)
- (n+1) (map_lift_fst lst) b) &&
- (List.for_all (check_rec_call env n lst) l)
-
- | IsLetIn (x,a,b,c) ->
- anomaly "check_rec_call: should have been reduced"
-
- | IsMutInd _ ->
- (List.for_all (check_rec_call env n lst) l)
-
- | IsMutConstruct _ ->
- (List.for_all (check_rec_call env n lst) l)
-
- | IsConst sp ->
- (try
- (List.for_all (check_rec_call env n lst) l)
- with (FixGuardError _ ) as e
- -> if evaluable_constant env sp then
- check_rec_call env n lst (whd_betadeltaiota env sigma t)
- else raise e)
-
- | IsApp (f,la) ->
- (check_rec_call env n lst f) &&
- (array_for_all (check_rec_call env n lst) la) &&
- (List.for_all (check_rec_call env n lst) l)
-
- | IsCoFix (i,(_,typarray,bodies as recdef)) ->
- let nbfix = Array.length typarray in
- let env' = push_rec_types recdef env in
- (array_for_all (check_rec_call env n lst) typarray) &&
- (List.for_all (check_rec_call env n lst) l) &&
- (array_for_all
- (check_rec_call env' (n+nbfix) (map_lift_fst_n nbfix lst))
- bodies)
-
- | IsEvar (_,la) ->
- (array_for_all (check_rec_call env n lst) la) &&
- (List.for_all (check_rec_call env n lst) l)
-
- | IsMeta _ -> true
-
- | IsVar _ | IsSort _ -> List.for_all (check_rec_call env n lst) l
- )
-
- and check_rec_call_fix_body env n lst decr recArgsDecrArg body =
- if decr = 0 then
- check_rec_call env n ((1,recArgsDecrArg)::lst) body
- else
- match kind_of_term body with
- | IsLambda (x,a,b) ->
- (check_rec_call env n lst a) &
- (check_rec_call_fix_body
- (push_rel_assum (x, a) env) (n+1)
- (map_lift_fst lst) (decr-1) recArgsDecrArg b)
- | _ -> anomaly "Not enough abstractions in fix body"
-
- in
- check_rec_call env' 1 [] d)
-
-(* vargs is supposed to be built from A1;..Ak;[f1]..[fk][|d1;..;dk|]
-and vdeft is [|t1;..;tk|] such that f1:A1,..,fk:Ak |- di:ti
-nvect is [|n1;..;nk|] which gives for each recursive definition
-the inductive-decreasing index
-the function checks the convertibility of ti with Ai *)
-
-let check_fix env sigma ((nvect,bodynum),(names,types,bodies as recdef)) =
- let nbfix = Array.length bodies in
- if nbfix = 0
- or Array.length nvect <> nbfix
- or Array.length types <> nbfix
- or Array.length names <> nbfix
- or bodynum < 0
- or bodynum >= nbfix
- then anomaly "Ill-formed fix term";
- for i = 0 to nbfix - 1 do
- let fixenv = push_rec_types recdef env in
- try
- let _ = check_subterm_rec_meta fixenv sigma nvect nvect.(i) bodies.(i)
- in ()
- with FixGuardError err ->
- error_ill_formed_rec_body CCI fixenv err names i bodies
- done
-
-(*
-let cfkey = Profile.declare_profile "check_fix";;
-let check_fix env sigma fix = Profile.profile3 cfkey check_fix env sigma fix;;
-*)
-
-(* Co-fixpoints. *)
-
-exception CoFixGuardError of guard_error
-
-let check_guard_rec_meta env sigma nbfix def deftype =
- let rec codomain_is_coind env c =
- let b = whd_betadeltaiota env sigma (strip_outer_cast c) in
- match kind_of_term b with
- | IsProd (x,a,b) ->
- codomain_is_coind (push_rel_assum (x, a) env) b
- | _ ->
- try
- find_coinductive env sigma b
- with Induc ->
- raise (CoFixGuardError (CodomainNotInductiveType b))
- in
- let (mind, _) = codomain_is_coind env deftype in
- let (sp,tyi) = mind in
- let lvlra = mis_recargs (lookup_mind_specif mind env) in
- let vlra = lvlra.(tyi) in
- let rec check_rec_call env alreadygrd n vlra t =
- if noccur_with_meta n nbfix t then
- true
- else
- let c,args = whd_betadeltaiota_stack env sigma t in
- match kind_of_term c with
- | IsMeta _ -> true
-
- | IsRel p ->
- if n <= p && p < n+nbfix then
- (* recursive call *)
- if alreadygrd then
- if List.for_all (noccur_with_meta n nbfix) args then
- true
- else
- raise (CoFixGuardError NestedRecursiveOccurrences)
- else
- raise (CoFixGuardError (UnguardedRecursiveCall t))
- else
- error "check_guard_rec_meta: ???" (* ??? *)
-
- | IsMutConstruct (_,i as cstr_sp) ->
- let lra =vlra.(i-1) in
- let mI = inductive_of_constructor cstr_sp in
- let mis = lookup_mind_specif mI env in
- let _,realargs = list_chop (mis_nparams mis) args in
- let rec process_args_of_constr l lra =
- match l with
- | [] -> true
- | t::lr ->
- (match lra with
- | [] ->
- anomalylabstrm "check_guard_rec_meta"
- [< 'sTR "a constructor with an empty list";
- 'sTR "of recargs is being applied" >]
- | (Mrec i)::lrar ->
- let newvlra = lvlra.(i) in
- (check_rec_call env true n newvlra t) &&
- (process_args_of_constr lr lrar)
-
- | (Imbr((sp,i) as ind_sp,lrc)::lrar) ->
- let mis = lookup_mind_specif ind_sp env in
- let sprecargs = mis_recargs mis in
- let lc = (Array.map
- (List.map
- (instantiate_recarg sp lrc))
- sprecargs.(i))
- in (check_rec_call env true n lc t) &
- (process_args_of_constr lr lrar)
-
- | _::lrar ->
- if (noccur_with_meta n nbfix t)
- then (process_args_of_constr lr lrar)
- else raise (CoFixGuardError
- (RecCallInNonRecArgOfConstructor t)))
- in (process_args_of_constr realargs lra)
-
-
- | IsLambda (x,a,b) ->
- assert (args = []);
- if (noccur_with_meta n nbfix a) then
- check_rec_call (push_rel_assum (x, a) env)
- alreadygrd (n+1) vlra b
- else
- raise (CoFixGuardError (RecCallInTypeOfAbstraction t))
-
- | IsCoFix (j,(_,varit,vdefs as recdef)) ->
- if (List.for_all (noccur_with_meta n nbfix) args)
- then
- let nbfix = Array.length vdefs in
- if (array_for_all (noccur_with_meta n nbfix) varit) then
- let env' = push_rec_types recdef env in
- (array_for_all
- (check_rec_call env' alreadygrd (n+1) vlra) vdefs)
- &&
- (List.for_all (check_rec_call env alreadygrd (n+1) vlra) args)
- else
- raise (CoFixGuardError (RecCallInTypeOfDef c))
- else
- raise (CoFixGuardError (UnguardedRecursiveCall c))
-
- | IsMutCase (_,p,tm,vrest) ->
- if (noccur_with_meta n nbfix p) then
- if (noccur_with_meta n nbfix tm) then
- if (List.for_all (noccur_with_meta n nbfix) args) then
- (array_for_all (check_rec_call env alreadygrd n vlra) vrest)
- else
- raise (CoFixGuardError (RecCallInCaseFun c))
- else
- raise (CoFixGuardError (RecCallInCaseArg c))
- else
- raise (CoFixGuardError (RecCallInCasePred c))
-
- | _ -> raise (CoFixGuardError NotGuardedForm)
-
- in
- check_rec_call env false 1 vlra def
-
-(* The function which checks that the whole block of definitions
- satisfies the guarded condition *)
-
-let check_cofix env sigma (bodynum,(names,types,bodies as recdef)) =
- let nbfix = Array.length bodies in
- for i = 0 to nbfix-1 do
- let fixenv = push_rec_types recdef env in
- try
- let _ = check_guard_rec_meta fixenv sigma nbfix bodies.(i) types.(i)
- in ()
- with CoFixGuardError err ->
- error_ill_formed_rec_body CCI fixenv err names i bodies
- done
-
-(* Checks the type of a (co)fixpoint.
- Fix and CoFix are typed the same way; only the guard condition differs. *)
-
-exception IllBranch of int
-
-let type_fixpoint env sigma lna lar vdefj =
+let type_fixpoint env lna lar vdefj =
let lt = Array.length vdefj in
assert (Array.length lar = lt);
try
- conv_forall2_i
- (fun i env sigma def ar ->
- try conv_leq env sigma def (lift lt ar)
- with NotConvertible -> raise (IllBranch i))
- env sigma
+ conv_leq_vecti env
(Array.map (fun j -> body_of_type j.uj_type) vdefj)
- (Array.map body_of_type lar)
- with IllBranch i ->
- error_ill_typed_rec_body CCI env i lna vdefj lar
-
-
-(* A function which checks that a term well typed verifies both
- syntaxic conditions *)
-
-let control_only_guard env sigma =
- let rec control_rec c = match kind_of_term c with
- | IsRel _ | IsVar _ -> ()
- | IsSort _ | IsMeta _ -> ()
- | IsMutInd _ -> ()
- | IsMutConstruct _ -> ()
- | IsConst _ -> ()
- | IsCoFix (_,(_,tys,bds) as cofix) ->
- check_cofix env sigma cofix;
- Array.iter control_rec tys;
- Array.iter control_rec bds;
- | IsFix (_,(_,tys,bds) as fix) ->
- check_fix env sigma fix;
- Array.iter control_rec tys;
- Array.iter control_rec bds;
- | IsMutCase(_,p,c,b) ->control_rec p;control_rec c;Array.iter control_rec b
- | IsEvar (_,cl) -> Array.iter control_rec cl
- | IsApp (_,cl) -> Array.iter control_rec cl
- | IsCast (c1,c2) -> control_rec c1; control_rec c2
- | IsProd (_,c1,c2) -> control_rec c1; control_rec c2
- | IsLambda (_,c1,c2) -> control_rec c1; control_rec c2
- | IsLetIn (_,c1,c2,c3) -> control_rec c1; control_rec c2; control_rec c3
- in
- control_rec
+ (Array.map (fun ty -> lift lt (body_of_type ty)) lar)
+ with NotConvertibleVect i ->
+ error_ill_typed_rec_body env i lna vdefj lar
+
+(***********************************************************************)
+(***********************************************************************)
+
+(* This combinator adds the universe constraints both in the local
+ graph and in the universes of the environment. This is to ensure
+ that the infered local graph is satisfiable. *)
+let univ_combinator (cst,univ) (j,c') =
+ (j,(Constraint.union cst c', merge_constraints c' univ))
+
+(* The typing machine. *)
+ (* ATTENTION : faudra faire le typage du contexte des Const,
+ Ind et Constructsi un jour cela devient des constructions
+ arbitraires et non plus des variables *)
+let rec execute env cstr cu =
+ match kind_of_term cstr with
+ (* Atomic terms *)
+ | Sort (Prop c) ->
+ (judge_of_prop_contents c, cu)
+
+ | Sort (Type u) ->
+ univ_combinator cu (judge_of_type u)
+
+ | Rel n ->
+ (judge_of_relative env n, cu)
+
+ | Var id ->
+ (judge_of_variable env id, cu)
+
+ | Const c ->
+ (judge_of_constant env c, cu)
+
+ (* Lambda calculus operators *)
+ | App (f,args) ->
+ let (j,cu1) = execute env f cu in
+ let (jl,cu2) = execute_array env args cu1 in
+ univ_combinator cu2
+ (judge_of_apply env j jl)
+
+ | Lambda (name,c1,c2) ->
+ let (varj,cu1) = execute_type env c1 cu in
+ let env1 = push_rel (name,None,varj.utj_val) env in
+ let (j',cu2) = execute env1 c2 cu1 in
+ (judge_of_abstraction env name varj j', cu2)
+
+ | Prod (name,c1,c2) ->
+ let (varj,cu1) = execute_type env c1 cu in
+ let env1 = push_rel (name,None,varj.utj_val) env in
+ let (varj',cu2) = execute_type env1 c2 cu1 in
+ univ_combinator cu2
+ (judge_of_product env name varj varj')
+
+ | LetIn (name,c1,c2,c3) ->
+ let (j,cu1) = execute env (mkCast(c1,c2)) cu in
+ let env1 = push_rel (name,Some j.uj_val,j.uj_type) env in
+ let (j',cu2) = execute env1 c3 cu1 in
+ (judge_of_letin env name j j', cu2)
+
+ | Cast (c,t) ->
+ let (cj,cu1) = execute env c cu in
+ let (tj,cu2) = execute_type env t cu1 in
+ univ_combinator cu2
+ (judge_of_cast env cj tj)
+
+ (* Inductive types *)
+ | Ind ind ->
+ (judge_of_inductive env ind, cu)
+
+ | Construct c ->
+ (judge_of_constructor env c, cu)
+
+ | Case (ci,p,c,lf) ->
+ let (cj,cu1) = execute env c cu in
+ let (pj,cu2) = execute env p cu1 in
+ let (lfj,cu3) = execute_array env lf cu2 in
+ univ_combinator cu3
+ (judge_of_case env ci pj cj lfj)
+
+ | Fix ((vn,i as vni),recdef) ->
+ let ((fix_ty,recdef'),cu1) = execute_recdef env recdef i cu in
+ let fix = (vni,recdef') in
+ check_fix env fix;
+ (make_judge (mkFix fix) fix_ty, cu1)
+
+ | CoFix (i,recdef) ->
+ let ((fix_ty,recdef'),cu1) = execute_recdef env recdef i cu in
+ let cofix = (i,recdef') in
+ check_cofix env cofix;
+ (make_judge (mkCoFix cofix) fix_ty, cu1)
+
+ (* Partial proofs: unsupported by the kernel *)
+ | Meta _ ->
+ anomaly "the kernel does not support metavariables"
+
+ | Evar _ ->
+ anomaly "the kernel does not support existential variables"
+
+and execute_type env constr cu =
+ let (j,cu1) = execute env constr cu in
+ (type_judgment env j, cu1)
+
+and execute_recdef env (names,lar,vdef) i cu =
+ let (larj,cu1) = execute_array env lar cu in
+ let lara = Array.map (assumption_of_judgment env) larj in
+ let env1 = push_rec_types (names,lara,vdef) env in
+ let (vdefj,cu2) = execute_array env1 vdef cu1 in
+ let vdefv = Array.map j_val vdefj in
+ let cst = type_fixpoint env1 names lara vdefj in
+ univ_combinator cu2
+ ((lara.(i),(names,lara,vdefv)),cst)
+
+and execute_array env v cu =
+ let (jl,cu1) = execute_list env (Array.to_list v) cu in
+ (Array.of_list jl, cu1)
+
+and execute_list env l cu =
+ match l with
+ | [] ->
+ ([], cu)
+ | c::r ->
+ let (j,cu1) = execute env c cu in
+ let (jr,cu2) = execute_list env r cu1 in
+ (j::jr, cu2)
+
+(* Derived functions *)
+let infer env constr =
+ let (j,(cst,_)) =
+ execute env constr (Constraint.empty, universes env) in
+ (j, cst)
+
+let infer_type env constr =
+ let (j,(cst,_)) =
+ execute_type env constr (Constraint.empty, universes env) in
+ (j, cst)
+
+let infer_v env cv =
+ let (jv,(cst,_)) =
+ execute_array env cv (Constraint.empty, universes env) in
+ (jv, cst)
+
+(* Typing of several terms. *)
+
+type local_entry =
+ | LocalDef of constr
+ | LocalAssum of constr
+
+let infer_local_decl env id = function
+ | LocalDef c ->
+ let (j,cst) = infer env c in
+ (Name id, Some j.uj_val, j.uj_type), cst
+ | LocalAssum c ->
+ let (j,cst) = infer env c in
+ (Name id, None, assumption_of_judgment env j), cst
+
+let infer_local_decls env decls =
+ let rec inferec env = function
+ | (id, d) :: l ->
+ let env, l, cst1 = inferec env l in
+ let d, cst2 = infer_local_decl env id d in
+ push_rel d env, d :: l, Constraint.union cst1 cst2
+ | [] -> env, [], Constraint.empty in
+ inferec env decls