+ | (_,h1,_,_,C.Fixpoint (true,fl,_)), Ref.Ref (_,Ref.Fix (i,recno2,h2)) ->
+ let _,_,recno1,arity,_ = List.nth fl i in
+ if h1 <> h2 || recno1 <> recno2 then error ();
+ arity
+ | (_,_,_,_,C.Constant (_,_,None,ty,_)), Ref.Ref (_,Ref.Decl) -> ty
+ | (_,h1,_,_,C.Constant (_,_,Some _,ty,_)), Ref.Ref (_,Ref.Def h2) ->
+ if h1 <> h2 then error ();
+ ty
+ | _ ->
+ raise (AssertFailure
+ (lazy ("type_of_constant: environment/reference: " ^
+ Ref.string_of_reference ref)))
+
+and get_relevance ~metasenv ~subst context t args =
+ let ty = typeof ~subst ~metasenv context t in
+ let rec aux context ty = function
+ | [] -> []
+ | arg::tl -> match R.whd ~subst context ty with
+ | C.Prod (_,so,de) ->
+ let sort = typeof ~subst ~metasenv context so in
+ let new_ty = S.subst ~avoid_beta_redexes:true arg de in
+ (*prerr_endline ("so: " ^ PP.ppterm ~subst ~metasenv:[]
+ ~context so);
+ prerr_endline ("sort: " ^ PP.ppterm ~subst ~metasenv:[]
+ ~context sort);*)
+ (match R.whd ~subst context sort with
+ | C.Sort C.Prop ->
+ false::(aux context new_ty tl)
+ | C.Sort _
+ | C.Meta _ -> true::(aux context new_ty tl)
+ | _ -> raise (TypeCheckerFailure (lazy (Printf.sprintf
+ "Prod: the type %s of the source of %s is not a sort"
+ (PP.ppterm ~subst ~metasenv ~context sort)
+ (PP.ppterm ~subst ~metasenv ~context so)))))
+ | _ ->
+ raise
+ (TypeCheckerFailure
+ (lazy (Printf.sprintf
+ "Appl: %s is not a function, it cannot be applied"
+ (PP.ppterm ~subst ~metasenv ~context
+ (let res = List.length tl in
+ let eaten = List.length args - res in
+ (C.Appl
+ (t::fst
+ (HExtlib.split_nth eaten args))))))))
+ in aux context ty args
+;;
+
+let typecheck_context ~metasenv ~subst context =
+ ignore
+ (List.fold_right
+ (fun d context ->
+ begin
+ match d with
+ _,C.Decl t -> ignore (typeof ~metasenv ~subst:[] context t)
+ | name,C.Def (te,ty) ->
+ ignore (typeof ~metasenv ~subst:[] context ty);
+ let ty' = typeof ~metasenv ~subst:[] context te in
+ if not (R.are_convertible ~metasenv ~subst context ty' ty) then
+ raise (AssertFailure (lazy (Printf.sprintf (
+ "the type of the definiens for %s in the context is not "^^
+ "convertible with the declared one.\n"^^
+ "inferred type:\n%s\nexpected type:\n%s")
+ name (PP.ppterm ~subst ~metasenv ~context ty')
+ (PP.ppterm ~subst ~metasenv ~context ty))))
+ end;
+ d::context
+ ) context [])
+;;
+
+let typecheck_metasenv metasenv =
+ ignore
+ (List.fold_left
+ (fun metasenv (i,(_,context,ty) as conj) ->
+ if List.mem_assoc i metasenv then
+ raise (TypeCheckerFailure (lazy ("duplicate meta " ^ string_of_int i ^
+ " in metasenv")));
+ typecheck_context ~metasenv ~subst:[] context;
+ ignore (typeof ~metasenv ~subst:[] context ty);
+ metasenv @ [conj]
+ ) [] metasenv)
+;;
+
+let typecheck_subst ~metasenv subst =
+ ignore
+ (List.fold_left
+ (fun subst (i,(_,context,ty,bo) as conj) ->
+ if List.mem_assoc i subst then
+ raise (AssertFailure (lazy ("duplicate meta " ^ string_of_int i ^
+ " in substitution")));
+ if List.mem_assoc i metasenv then
+ raise (AssertFailure (lazy ("meta " ^ string_of_int i ^
+ " is both in the metasenv and in the substitution")));
+ typecheck_context ~metasenv ~subst context;
+ ignore (typeof ~metasenv ~subst context ty);
+ let ty' = typeof ~metasenv ~subst context bo in
+ if not (R.are_convertible ~metasenv ~subst context ty' ty) then
+ raise (AssertFailure (lazy (Printf.sprintf (
+ "the type of the definiens for %d in the substitution is not "^^
+ "convertible with the declared one.\n"^^
+ "inferred type:\n%s\nexpected type:\n%s")
+ i
+ (PP.ppterm ~subst ~metasenv ~context ty')
+ (PP.ppterm ~subst ~metasenv ~context ty))));
+ subst @ [conj]
+ ) [] subst)
+;;
+
+let height_of_term tl =
+ let h = ref 0 in
+ let get_height (NReference.Ref (uri,_)) =
+ let _,height,_,_,_ = NCicEnvironment.get_checked_obj uri in
+ height in
+ let rec aux =
+ function
+ NCic.Meta (_,(_,NCic.Ctx l)) -> List.iter aux l
+ | NCic.Meta _ -> ()
+ | NCic.Rel _
+ | NCic.Sort _ -> ()
+ | NCic.Implicit _ -> assert false
+ | NCic.Const nref -> h := max !h (get_height nref)
+ | NCic.Prod (_,t1,t2)
+ | NCic.Lambda (_,t1,t2) -> aux t1; aux t2
+ | NCic.LetIn (_,s,ty,t) -> aux s; aux ty; aux t
+ | NCic.Appl l -> List.iter aux l
+ | NCic.Match (_,outty,t,pl) -> aux outty; aux t; List.iter aux pl
+ in
+ List.iter aux tl;
+ 1 + !h
+;;
+
+let height_of_obj_kind uri ~subst =
+ function
+ NCic.Inductive _
+ | NCic.Constant (_,_,None,_,_)
+ | NCic.Fixpoint (false,_,_) -> 0
+ | NCic.Fixpoint (true,ifl,_) ->
+ let iflno = List.length ifl in
+ height_of_term
+ (List.fold_left
+ (fun l (_,_,_,ty,bo) ->
+ let bo = debruijn uri iflno [] ~subst bo in
+ ty::bo::l
+ ) [] ifl)
+ | NCic.Constant (_,_,Some bo,ty,_) -> height_of_term [bo;ty]