(************************************************************************) (* v * The Coq Proof Assistant / The Coq Development Team *) (* try conv_leq false env t1 t2 with NotConvertible -> raise (NotConvertibleVect i)) () v1 v2 let check_constraints cst env = if Environ.check_constraints cst env then () else error_unsatisfied_constraints env cst (* This should be a type (a priori without intension to be an assumption) *) let type_judgment env j = match kind_of_term(whd_all env 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 (************************************************) (* Incremental typing rules: builds a typing judgement given the *) (* judgements for the subterms. *) (*s Type of sorts *) (* Prop and Set *) let judge_of_prop = { uj_val = mkProp; uj_type = mkSort type1_sort } let judge_of_set = { uj_val = mkSet; uj_type = mkSort type1_sort } let judge_of_prop_contents = function | Null -> judge_of_prop | Pos -> judge_of_set (* Type of Type(i). *) let judge_of_type u = let uu = Universe.super u in { uj_val = mkType u; uj_type = mkType uu } (*s Type of a de Bruijn index. *) let judge_of_relative env n = try let typ = get_type (lookup_rel n env) in { uj_val = mkRel n; uj_type = lift n typ } with Not_found -> error_unbound_rel env n (* Type of variables *) let judge_of_variable env id = try let ty = named_type id env in make_judge (mkVar id) ty with Not_found -> error_unbound_var env id (* Management of context of variables. *) (* Checks if a context of variables can be instantiated by the variables of the current env. Order does not have to be checked assuming that all names are distinct *) let check_hyps_inclusion env c sign = Context.Named.fold_outside (fun d1 () -> let open Context.Named.Declaration in let id = get_id d1 in try let d2 = lookup_named id env in conv env (get_type d2) (get_type d1); (match d2,d1 with | LocalAssum _, LocalAssum _ -> () | LocalAssum _, LocalDef _ -> (* This is wrong, because we don't know if the body is needed or not for typechecking: *) () | LocalDef _, LocalAssum _ -> raise NotConvertible | LocalDef (_,b2,_), LocalDef (_,b1,_) -> conv env b2 b1); with Not_found | NotConvertible | Option.Heterogeneous -> error_reference_variables env id c) sign ~init:() (* Instantiation of terms on real arguments. *) (* Make a type polymorphic if an arity *) let extract_level env p = let _,c = dest_prod_assum env p in match kind_of_term c with Sort (Type u) -> Univ.Universe.level u | _ -> None let extract_context_levels env l = let fold l = function | LocalAssum (_,p) -> extract_level env p :: l | LocalDef _ -> l in List.fold_left fold [] l let make_polymorphic_if_constant_for_ind env {uj_val = c; uj_type = t} = let params, ccl = dest_prod_assum env t in match kind_of_term ccl with | Sort (Type u) -> let ind, l = decompose_app (whd_all env c) in if isInd ind && List.is_empty l then let mis = lookup_mind_specif env (fst (destInd ind)) in let nparams = Inductive.inductive_params mis in let paramsl = CList.lastn nparams params in let param_ccls = extract_context_levels env paramsl in let s = { template_param_levels = param_ccls; template_level = u} in TemplateArity (params,s) else RegularArity t | _ -> RegularArity t (* Type of constants *) let type_of_constant_type_knowing_parameters env t paramtyps = match t with | RegularArity t -> t | TemplateArity (sign,ar) -> let ctx = List.rev sign in let ctx,s = instantiate_universes env ctx ar paramtyps in mkArity (List.rev ctx,s) let type_of_constant_knowing_parameters env cst paramtyps = let cb = lookup_constant (fst cst) env in let () = check_hyps_inclusion env (mkConstU cst) cb.const_hyps in let ty, cu = constant_type env cst in type_of_constant_type_knowing_parameters env ty paramtyps, cu let type_of_constant_knowing_parameters_in env cst paramtyps = let cb = lookup_constant (fst cst) env in let () = check_hyps_inclusion env (mkConstU cst) cb.const_hyps in let ty = constant_type_in env cst in type_of_constant_type_knowing_parameters env ty paramtyps let type_of_constant_type env t = type_of_constant_type_knowing_parameters env t [||] let type_of_constant env cst = type_of_constant_knowing_parameters env cst [||] let type_of_constant_in env cst = let cb = lookup_constant (fst cst) env in let () = check_hyps_inclusion env (mkConstU cst) cb.const_hyps in let ar = constant_type_in env cst in type_of_constant_type_knowing_parameters env ar [||] let judge_of_constant_knowing_parameters env (kn,u as cst) args = let c = mkConstU cst in let ty, cu = type_of_constant_knowing_parameters env cst args in let () = check_constraints cu env in make_judge c ty let judge_of_constant env cst = judge_of_constant_knowing_parameters env cst [||] let type_of_projection env (p,u) = let cst = Projection.constant p in let cb = lookup_constant cst env in match cb.const_proj with | Some pb -> if cb.const_polymorphic then Vars.subst_instance_constr u pb.proj_type else pb.proj_type | None -> raise (Invalid_argument "type_of_projection: not a projection") (* Type of a lambda-abstraction. *) (* [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 ----------------------------------------------------------------------- env |- [name:typ]j.uj_val : (name:typ)j.uj_type Since all products are defined in the Calculus of Inductive Constructions and no upper constraint exists on the sort $s$, we don't need to compute $s$ *) 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 name defj typj j = { uj_val = mkLetIn (name, defj.uj_val, typj.utj_val, j.uj_val) ; uj_type = subst1 defj.uj_val j.uj_type } (* Type of an application. *) let judge_of_apply env funj argjv = let rec apply_rec n typ = function | [] -> { uj_val = mkApp (j_val funj, Array.map j_val argjv); uj_type = typ } | hj::restjl -> (match kind_of_term (whd_all env typ) with | Prod (_,c1,c2) -> (try let () = conv_leq false env hj.uj_type c1 in apply_rec (n+1) (subst1 hj.uj_val c2) restjl with NotConvertible -> error_cant_apply_bad_type env (n,c1, hj.uj_type) funj argjv) | _ -> error_cant_apply_not_functional env funj argjv) in apply_rec 1 funj.uj_type (Array.to_list argjv) (* Type of product *) let sort_of_product env domsort rangsort = match (domsort, rangsort) with (* Product rule (s,Prop,Prop) *) | (_, Prop Null) -> rangsort (* Product rule (Prop/Set,Set,Set) *) | (Prop _, Prop Pos) -> rangsort (* Product rule (Type,Set,?) *) | (Type u1, Prop Pos) -> if is_impredicative_set env then (* Rule is (Type,Set,Set) in the Set-impredicative calculus *) rangsort else (* Rule is (Type_i,Set,Type_i) in the Set-predicative calculus *) Type (Universe.sup Universe.type0 u1) (* Product rule (Prop,Type_i,Type_i) *) | (Prop Pos, Type u2) -> Type (Universe.sup Universe.type0 u2) (* Product rule (Prop,Type_i,Type_i) *) | (Prop Null, Type _) -> rangsort (* Product rule (Type_i,Type_i,Type_i) *) | (Type u1, Type u2) -> Type (Universe.sup u1 u2) (* [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 = sort_of_product env t1.utj_type t2.utj_type in { uj_val = mkProd (name, t1.utj_val, t2.utj_val); uj_type = mkSort s } (* Type of a type cast *) (* [judge_of_cast env (c,typ1) (typ2,s)] implements the rule env |- c:typ1 env |- typ2:s env |- typ1 <= typ2 --------------------------------------------------------------------- env |- c:typ2 *) let judge_of_cast env cj k tj = let expected_type = tj.utj_val in try let c, cst = match k with | VMcast -> mkCast (cj.uj_val, k, expected_type), Reduction.vm_conv CUMUL env cj.uj_type expected_type | DEFAULTcast -> mkCast (cj.uj_val, k, expected_type), default_conv ~l2r:false CUMUL env cj.uj_type expected_type | REVERTcast -> cj.uj_val, default_conv ~l2r:true CUMUL env cj.uj_type expected_type | NATIVEcast -> let sigma = Nativelambda.empty_evars in mkCast (cj.uj_val, k, expected_type), Nativeconv.native_conv CUMUL sigma env cj.uj_type expected_type in { uj_val = c; uj_type = expected_type } with NotConvertible -> error_actual_type env cj expected_type (* Inductive types. *) (* The type is parametric over the uniform parameters whose conclusion is in Type; to enforce the internal constraints between the parameters and the instances of Type occurring in the type of the constructors, we use the level variables _statically_ assigned to the conclusions of the parameters as mediators: e.g. if a parameter has conclusion Type(alpha), static constraints of the form alpha<=v exist between alpha and the Type's occurring in the constructor types; when the parameters is finally instantiated by a term of conclusion Type(u), then the constraints u<=alpha is computed in the App case of execute; from this constraints, the expected dynamic constraints of the form u<=v are enforced *) let judge_of_inductive_knowing_parameters env (ind,u as indu) args = let c = mkIndU indu in let (mib,mip) as spec = lookup_mind_specif env ind in check_hyps_inclusion env c mib.mind_hyps; let t,cst = Inductive.constrained_type_of_inductive_knowing_parameters env (spec,u) args in check_constraints cst env; make_judge c t let judge_of_inductive env (ind,u as indu) = let c = mkIndU indu in let (mib,mip) as spec = lookup_mind_specif env ind in check_hyps_inclusion env c mib.mind_hyps; let t,cst = Inductive.constrained_type_of_inductive env (spec,u) in check_constraints cst env; (make_judge c t) (* Constructors. *) let judge_of_constructor env (c,u as cu) = let constr = mkConstructU cu in let _ = let ((kn,_),_) = c in let mib = lookup_mind kn env in check_hyps_inclusion env constr mib.mind_hyps in let specif = lookup_mind_specif env (inductive_of_constructor c) in let t,cst = constrained_type_of_constructor cu specif in let () = check_constraints cst env in (make_judge constr t) (* Case. *) let check_branch_types env (ind,u) cj (lfj,explft) = try conv_leq_vecti env (Array.map j_type lfj) explft with NotConvertibleVect i -> error_ill_formed_branch env cj.uj_val ((ind,i+1),u) lfj.(i).uj_type explft.(i) | Invalid_argument _ -> error_number_branches env cj (Array.length explft) let judge_of_case env ci pj cj lfj = let (pind, _ as indspec) = try find_rectype env cj.uj_type with Not_found -> error_case_not_inductive env cj in let () = check_case_info env pind ci in let (bty,rslty) = type_case_branches env indspec pj cj.uj_val in let () = check_branch_types env pind cj (lfj,bty) in ({ uj_val = mkCase (ci, (*nf_betaiota*) pj.uj_val, cj.uj_val, Array.map j_val lfj); uj_type = rslty }) let judge_of_projection env p cj = let pb = lookup_projection p env in let (ind,u), args = try find_rectype env cj.uj_type with Not_found -> error_case_not_inductive env cj in assert(eq_mind pb.proj_ind (fst ind)); let ty = Vars.subst_instance_constr u pb.Declarations.proj_type in let ty = substl (cj.uj_val :: List.rev args) ty in {uj_val = mkProj (p,cj.uj_val); uj_type = ty} (* Fixpoints. *) (* Checks the type of a general (co)fixpoint, i.e. without checking *) (* the specific guard condition. *) let type_fixpoint env lna lar vdefj = let lt = Array.length vdefj in assert (Int.equal (Array.length lar) lt); try conv_leq_vecti env (Array.map j_type vdefj) (Array.map (fun ty -> lift lt ty) lar) with NotConvertibleVect i -> error_ill_typed_rec_body env i lna vdefj lar (************************************************************************) (************************************************************************) (* 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 = match kind_of_term cstr with (* Atomic terms *) | Sort (Prop c) -> judge_of_prop_contents c | Sort (Type u) -> judge_of_type u | Rel n -> judge_of_relative env n | Var id -> judge_of_variable env id | Const c -> judge_of_constant env c | Proj (p, c) -> let cj = execute env c in judge_of_projection env p cj (* Lambda calculus operators *) | App (f,args) -> let jl = execute_array env args in let j = match kind_of_term f with | Ind ind when Environ.template_polymorphic_pind ind env -> (* Sort-polymorphism of inductive types *) let args = Array.map (fun j -> lazy j.uj_type) jl in judge_of_inductive_knowing_parameters env ind args | Const cst when Environ.template_polymorphic_pconstant cst env -> (* Sort-polymorphism of constant *) let args = Array.map (fun j -> lazy j.uj_type) jl in judge_of_constant_knowing_parameters env cst args | _ -> (* No sort-polymorphism *) execute env f in judge_of_apply env j jl | Lambda (name,c1,c2) -> let varj = execute_type env c1 in let env1 = push_rel (LocalAssum (name,varj.utj_val)) env in let j' = execute env1 c2 in judge_of_abstraction env name varj j' | Prod (name,c1,c2) -> let varj = execute_type env c1 in let env1 = push_rel (LocalAssum (name,varj.utj_val)) env in let varj' = execute_type env1 c2 in judge_of_product env name varj varj' | LetIn (name,c1,c2,c3) -> let j1 = execute env c1 in let j2 = execute_type env c2 in let _ = judge_of_cast env j1 DEFAULTcast j2 in let env1 = push_rel (LocalDef (name,j1.uj_val,j2.utj_val)) env in let j' = execute env1 c3 in judge_of_letin env name j1 j2 j' | Cast (c,k,t) -> let cj = execute env c in let tj = execute_type env t in judge_of_cast env cj k tj (* Inductive types *) | Ind ind -> judge_of_inductive env ind | Construct c -> judge_of_constructor env c | Case (ci,p,c,lf) -> let cj = execute env c in let pj = execute env p in let lfj = execute_array env lf in judge_of_case env ci pj cj lfj | Fix ((vn,i as vni),recdef) -> let (fix_ty,recdef') = execute_recdef env recdef i in let fix = (vni,recdef') in check_fix env fix; make_judge (mkFix fix) fix_ty | CoFix (i,recdef) -> let (fix_ty,recdef') = execute_recdef env recdef i in let cofix = (i,recdef') in check_cofix env cofix; (make_judge (mkCoFix cofix) fix_ty) (* Partial proofs: unsupported by the kernel *) | Meta _ -> anomaly (Pp.str "the kernel does not support metavariables") | Evar _ -> anomaly (Pp.str "the kernel does not support existential variables") and execute_type env constr = let j = execute env constr in type_judgment env j and execute_recdef env (names,lar,vdef) i = let larj = execute_array env lar in let lara = Array.map (assumption_of_judgment env) larj in let env1 = push_rec_types (names,lara,vdef) env in let vdefj = execute_array env1 vdef in let vdefv = Array.map j_val vdefj in let () = type_fixpoint env1 names lara vdefj in (lara.(i),(names,lara,vdefv)) and execute_array env = Array.map (execute env) (* Derived functions *) let infer env constr = let j = execute env constr in assert (eq_constr j.uj_val constr); j (* let infer_key = Profile.declare_profile "infer" *) (* let infer = Profile.profile2 infer_key infer *) let infer_type env constr = let j = execute_type env constr in j let infer_v env cv = let jv = execute_array env cv in jv (* Typing of several terms. *) let infer_local_decl env id = function | LocalDefEntry c -> let j = infer env c in LocalDef (Name id, j.uj_val, j.uj_type) | LocalAssumEntry c -> let j = infer env c in LocalAssum (Name id, assumption_of_judgment env j) let infer_local_decls env decls = let rec inferec env = function | (id, d) :: l -> let (env, l) = inferec env l in let d = infer_local_decl env id d in (push_rel d env, Context.Rel.add d l) | [] -> (env, Context.Rel.empty) in inferec env decls