(************************************************************************) (* v * The Coq Proof Assistant / The Coq Development Team *) (* anomaly ~label:"dirpath_prefix" (Pp.str "empty dirpath") | _::l -> DirPath.make l let pop_mind kn = let (mp,dir,l) = Names.repr_mind kn in Names.make_mind mp (pop_dirpath dir) l let pop_con con = let (mp,dir,l) = Names.repr_con con in Names.make_con mp (pop_dirpath dir) l type my_global_reference = | ConstRef of constant | IndRef of inductive | ConstructRef of constructor module RefHash = struct type t = my_global_reference let equal gr1 gr2 = match gr1, gr2 with | ConstRef c1, ConstRef c2 -> Constant.SyntacticOrd.equal c1 c2 | IndRef i1, IndRef i2 -> eq_syntactic_ind i1 i2 | ConstructRef c1, ConstructRef c2 -> eq_syntactic_constructor c1 c2 | _ -> false open Hashset.Combine let hash = function | ConstRef c -> combinesmall 1 (Constant.SyntacticOrd.hash c) | IndRef i -> combinesmall 2 (ind_syntactic_hash i) | ConstructRef c -> combinesmall 3 (constructor_syntactic_hash c) end module RefTable = Hashtbl.Make(RefHash) let instantiate_my_gr gr u = match gr with | ConstRef c -> mkConstU (c, u) | IndRef i -> mkIndU (i, u) | ConstructRef c -> mkConstructU (c, u) let share cache r (cstl,knl) = try RefTable.find cache r with Not_found -> let f,(u,l) = match r with | IndRef (kn,i) -> IndRef (pop_mind kn,i), Mindmap.find kn knl | ConstructRef ((kn,i),j) -> ConstructRef ((pop_mind kn,i),j), Mindmap.find kn knl | ConstRef cst -> ConstRef (pop_con cst), Cmap.find cst cstl in let c = (f, (u, Array.map mkVar l)) in RefTable.add cache r c; c let share_univs cache r u l = let r', (u', args) = share cache r l in mkApp (instantiate_my_gr r' (Instance.append u' u), args) let update_case_info cache ci modlist = try let ind, n = match share cache (IndRef ci.ci_ind) modlist with | (IndRef f,(u,l)) -> (f, Array.length l) | _ -> assert false in { ci with ci_ind = ind; ci_npar = ci.ci_npar + n } with Not_found -> ci let is_empty_modlist (cm, mm) = Cmap.is_empty cm && Mindmap.is_empty mm let expmod_constr cache modlist c = let share_univs = share_univs cache in let update_case_info = update_case_info cache in let rec substrec c = match kind_of_term c with | Case (ci,p,t,br) -> map_constr substrec (mkCase (update_case_info ci modlist,p,t,br)) | Ind (ind,u) -> (try share_univs (IndRef ind) u modlist with | Not_found -> map_constr substrec c) | Construct (cstr,u) -> (try share_univs (ConstructRef cstr) u modlist with | Not_found -> map_constr substrec c) | Const (cst,u) -> (try share_univs (ConstRef cst) u modlist with | Not_found -> map_constr substrec c) | Proj (p, c') -> (try let p' = share_univs (ConstRef (Projection.constant p)) Univ.Instance.empty modlist in let make c = Projection.make c (Projection.unfolded p) in match kind_of_term p' with | Const (p',_) -> mkProj (make p', substrec c') | App (f, args) -> (match kind_of_term f with | Const (p', _) -> mkProj (make p', substrec c') | _ -> assert false) | _ -> assert false with Not_found -> map_constr substrec c) | _ -> map_constr substrec c in if is_empty_modlist modlist then c else substrec c let abstract_constant_type = List.fold_left (fun c d -> mkNamedProd_wo_LetIn d c) let abstract_constant_body = List.fold_left (fun c d -> mkNamedLambda_or_LetIn d c) type recipe = { from : constant_body; info : Opaqueproof.cooking_info } type inline = bool type result = constant_def * constant_type * projection_body option * bool * constant_universes * inline * Context.section_context option let on_body ml hy f = function | Undef _ as x -> x | Def cs -> Def (Mod_subst.from_val (f (Mod_subst.force_constr cs))) | OpaqueDef o -> OpaqueDef (Opaqueproof.discharge_direct_opaque ~cook_constr:f { Opaqueproof.modlist = ml; abstract = hy } o) let constr_of_def otab = function | Undef _ -> assert false | Def cs -> Mod_subst.force_constr cs | OpaqueDef lc -> Opaqueproof.force_proof otab lc let expmod_constr_subst cache modlist subst c = let c = expmod_constr cache modlist c in Vars.subst_univs_level_constr subst c let cook_constr { Opaqueproof.modlist ; abstract } c = let cache = RefTable.create 13 in let expmod = expmod_constr_subst cache modlist (pi2 abstract) in let hyps = Context.Named.map expmod (pi1 abstract) in abstract_constant_body (expmod c) hyps let lift_univs cb subst = if cb.const_polymorphic && not (Univ.LMap.is_empty subst) then let inst = Univ.UContext.instance cb.const_universes in let cstrs = Univ.UContext.constraints cb.const_universes in let len = Univ.LMap.cardinal subst in let subst = Array.fold_left_i (fun i acc v -> Univ.LMap.add (Level.var i) (Level.var (i + len)) acc) subst (Univ.Instance.to_array inst) in let cstrs' = Univ.subst_univs_level_constraints subst cstrs in subst, Univ.UContext.make (inst,cstrs') else subst, cb.const_universes let cook_constant env { from = cb; info } = let { Opaqueproof.modlist; abstract } = info in let cache = RefTable.create 13 in let abstract, usubst, abs_ctx = abstract in let usubst, univs = lift_univs cb usubst in let expmod = expmod_constr_subst cache modlist usubst in let hyps = Context.Named.map expmod abstract in let body = on_body modlist (hyps, usubst, abs_ctx) (fun c -> abstract_constant_body (expmod c) hyps) cb.const_body in let const_hyps = Context.Named.fold_outside (fun decl hyps -> let open Context.Named.Declaration in List.filter (fun decl' -> not (Id.equal (get_id decl) (get_id decl'))) hyps) hyps ~init:cb.const_hyps in let typ = match cb.const_type with | RegularArity t -> let typ = abstract_constant_type (expmod t) hyps in RegularArity typ | TemplateArity (ctx,s) -> let t = mkArity (ctx,Type s.template_level) in let typ = abstract_constant_type (expmod t) hyps in let j = make_judge (constr_of_def (opaque_tables env) body) typ in Typeops.make_polymorphic_if_constant_for_ind env j in let projection pb = let c' = abstract_constant_body (expmod pb.proj_body) hyps in let etab = abstract_constant_body (expmod (fst pb.proj_eta)) hyps in let etat = abstract_constant_body (expmod (snd pb.proj_eta)) hyps in let ((mind, _), _), n' = try let c' = share_univs cache (IndRef (pb.proj_ind,0)) Univ.Instance.empty modlist in match kind_of_term c' with | App (f,l) -> (destInd f, Array.length l) | Ind ind -> ind, 0 | _ -> assert false with Not_found -> (((pb.proj_ind,0),Univ.Instance.empty), 0) in let typ = (* By invariant, a regular arity *) match typ with RegularArity t -> t | TemplateArity _ -> assert false in let ctx, ty' = decompose_prod_n (n' + pb.proj_npars + 1) typ in { proj_ind = mind; proj_npars = pb.proj_npars + n'; proj_arg = pb.proj_arg; proj_eta = etab, etat; proj_type = ty'; proj_body = c' } in let univs = let abs' = if cb.const_polymorphic then abs_ctx else instantiate_univ_context abs_ctx in UContext.union abs' univs in (body, typ, Option.map projection cb.const_proj, cb.const_polymorphic, univs, cb.const_inline_code, Some const_hyps) (* let cook_constant_key = Profile.declare_profile "cook_constant" *) (* let cook_constant = Profile.profile2 cook_constant_key cook_constant *) let expmod_constr modlist c = expmod_constr (RefTable.create 13) modlist c