summaryrefslogtreecommitdiff
path: root/toplevel/record.ml
diff options
context:
space:
mode:
Diffstat (limited to 'toplevel/record.ml')
-rw-r--r--toplevel/record.ml478
1 files changed, 296 insertions, 182 deletions
diff --git a/toplevel/record.ml b/toplevel/record.ml
index 86a9411f..55f53351 100644
--- a/toplevel/record.ml
+++ b/toplevel/record.ml
@@ -1,107 +1,169 @@
(************************************************************************)
(* v * The Coq Proof Assistant / The Coq Development Team *)
-(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2014 *)
+(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2015 *)
(* \VV/ **************************************************************)
(* // * This file is distributed under the terms of the *)
(* * GNU Lesser General Public License Version 2.1 *)
(************************************************************************)
open Pp
+open Errors
open Util
open Names
-open Libnames
+open Globnames
open Nameops
open Term
+open Context
+open Vars
open Environ
open Declarations
open Entries
open Declare
-open Nametab
open Constrintern
-open Command
-open Inductive
-open Safe_typing
open Decl_kinds
-open Indtypes
open Type_errors
-open Topconstr
+open Constrexpr
+open Constrexpr_ops
+open Goptions
(********** definition d'un record (structure) **************)
-let interp_evars evdref env impls k typ =
- let typ' = intern_gen true ~impls !evdref env typ in
- let imps = Implicit_quantifiers.implicits_of_glob_constr typ' in
- imps, Pretyping.Default.understand_tcc_evars evdref env k typ'
+(** Flag governing use of primitive projections. Disabled by default. *)
+let primitive_flag = ref false
+let _ =
+ declare_bool_option
+ { optsync = true;
+ optdepr = false;
+ optname = "use of primitive projections";
+ optkey = ["Primitive";"Projections"];
+ optread = (fun () -> !primitive_flag) ;
+ optwrite = (fun b -> primitive_flag := b) }
-let interp_fields_evars evars env impls_env nots l =
+let typeclasses_strict = ref false
+let _ =
+ declare_bool_option
+ { optsync = true;
+ optdepr = false;
+ optname = "strict typeclass resolution";
+ optkey = ["Typeclasses";"Strict";"Resolution"];
+ optread = (fun () -> !typeclasses_strict);
+ optwrite = (fun b -> typeclasses_strict := b); }
+
+let typeclasses_unique = ref false
+let _ =
+ declare_bool_option
+ { optsync = true;
+ optdepr = false;
+ optname = "unique typeclass instances";
+ optkey = ["Typeclasses";"Unique";"Instances"];
+ optread = (fun () -> !typeclasses_unique);
+ optwrite = (fun b -> typeclasses_unique := b); }
+
+let interp_fields_evars env evars impls_env nots l =
List.fold_left2
(fun (env, uimpls, params, impls) no ((loc, i), b, t) ->
- let impl, t' = interp_evars evars env impls Pretyping.IsType t in
- let b' = Option.map (fun x -> snd (interp_evars evars env impls (Pretyping.OfType (Some t')) x)) b in
+ let t', impl = interp_type_evars_impls env evars ~impls t in
+ let b' = Option.map (fun x -> fst (interp_casted_constr_evars_impls env evars ~impls x t')) b in
let impls =
match i with
| Anonymous -> impls
- | Name id -> Idmap.add id (compute_internalization_data env Constrintern.Method t' impl) impls
+ | Name id -> Id.Map.add id (compute_internalization_data env Constrintern.Method t' impl) impls
in
let d = (i,b',t') in
List.iter (Metasyntax.set_notation_for_interpretation impls) no;
(push_rel d env, impl :: uimpls, d::params, impls))
(env, [], [], impls_env) nots l
+let compute_constructor_level evars env l =
+ List.fold_right (fun (n,b,t as d) (env, univ) ->
+ let univ =
+ if b = None then
+ let s = Retyping.get_sort_of env evars t in
+ Univ.sup (univ_of_sort s) univ
+ else univ
+ in (push_rel d env, univ))
+ l (env, Univ.type0m_univ)
+
let binder_of_decl = function
| Vernacexpr.AssumExpr(n,t) -> (n,None,t)
- | Vernacexpr.DefExpr(n,c,t) -> (n,Some c, match t with Some c -> c | None -> CHole (fst n, None))
+ | Vernacexpr.DefExpr(n,c,t) -> (n,Some c, match t with Some c -> c | None -> CHole (fst n, None, Misctypes.IntroAnonymous, None))
let binders_of_decls = List.map binder_of_decl
-let typecheck_params_and_fields id t ps nots fs =
+let typecheck_params_and_fields def id t ps nots fs =
let env0 = Global.env () in
- let evars = ref Evd.empty in
+ let evars = ref (Evd.from_env env0) in
let _ =
let error bk (loc, name) =
- match bk with
- | Default _ ->
- if name = Anonymous then
- user_err_loc (loc, "record", str "Record parameters must be named")
+ match bk, name with
+ | Default _, Anonymous ->
+ user_err_loc (loc, "record", str "Record parameters must be named")
| _ -> ()
in
List.iter
(function LocalRawDef (b, _) -> error default_binder_kind b
| LocalRawAssum (ls, bk, ce) -> List.iter (error bk) ls) ps
in
- let impls_env, ((env1,newps), imps) = interp_context_evars evars env0 ps in
- let fullarity = it_mkProd_or_LetIn (Option.cata (fun x -> x) (Termops.new_Type ()) t) newps in
+ let impls_env, ((env1,newps), imps) = interp_context_evars env0 evars ps in
+ let t', template = match t with
+ | Some t ->
+ let env = push_rel_context newps env0 in
+ let s = interp_type_evars env evars ~impls:empty_internalization_env t in
+ let sred = Reductionops.whd_betadeltaiota env !evars s in
+ (match kind_of_term sred with
+ | Sort s' ->
+ (match Evd.is_sort_variable !evars s' with
+ | Some l -> evars := Evd.make_flexible_variable !evars true (* (not def) *) l;
+ sred, true
+ | None -> s, false)
+ | _ -> user_err_loc (constr_loc t,"", str"Sort expected."))
+ | None ->
+ let uvarkind = if (* not def *) true then Evd.univ_flexible_alg else Evd.univ_flexible in
+ mkSort (Evarutil.evd_comb0 (Evd.new_sort_variable uvarkind) evars), false
+ in
+ let fullarity = it_mkProd_or_LetIn t' newps in
let env_ar = push_rel_context newps (push_rel (Name id,None,fullarity) env0) in
let env2,impls,newfs,data =
- interp_fields_evars evars env_ar impls_env nots (binders_of_decls fs)
+ interp_fields_evars env_ar evars impls_env nots (binders_of_decls fs)
in
- let evars = Evarconv.consider_remaining_unif_problems env_ar !evars in
- let evars = Typeclasses.resolve_typeclasses env_ar evars in
- let sigma = evars in
- let newps = Evarutil.nf_rel_context_evar sigma newps in
- let newfs = Evarutil.nf_rel_context_evar sigma newfs in
+ let sigma =
+ Pretyping.solve_remaining_evars Pretyping.all_and_fail_flags env_ar !evars (Evd.empty,!evars) in
+ let evars, nf = Evarutil.nf_evars_and_universes sigma in
+ let arity = nf t' in
+ let evars =
+ let _, univ = compute_constructor_level evars env_ar newfs in
+ let ctx, aritysort = Reduction.dest_arity env0 arity in
+ assert(List.is_empty ctx); (* Ensured by above analysis *)
+ if Sorts.is_prop aritysort ||
+ (Sorts.is_set aritysort && engagement env0 = Some ImpredicativeSet) then
+ evars
+ else Evd.set_leq_sort env_ar evars (Type univ) aritysort
+ in
+ let evars, nf = Evarutil.nf_evars_and_universes evars in
+ let newps = map_rel_context nf newps in
+ let newfs = map_rel_context nf newfs in
let ce t = Evarutil.check_evars env0 Evd.empty evars t in
List.iter (fun (n, b, t) -> Option.iter ce b; ce t) (List.rev newps);
List.iter (fun (n, b, t) -> Option.iter ce b; ce t) (List.rev newfs);
- imps, newps, impls, newfs
+ Evd.universe_context evars, nf arity, template, imps, newps, impls, newfs
let degenerate_decl (na,b,t) =
let id = match na with
| Name id -> id
- | Anonymous -> anomaly "Unnamed record variable" in
+ | Anonymous -> anomaly (Pp.str "Unnamed record variable") in
match b with
| None -> (id, Entries.LocalAssum t)
| Some b -> (id, Entries.LocalDef b)
type record_error =
- | MissingProj of identifier * identifier list
- | BadTypedProj of identifier * env * Type_errors.type_error
+ | MissingProj of Id.t * Id.t list
+ | BadTypedProj of Id.t * env * Type_errors.type_error
let warning_or_error coe indsp err =
let st = match err with
| MissingProj (fi,projs) ->
let s,have = if List.length projs > 1 then "s","were" else "","was" in
- (str(string_of_id fi) ++
+ (str(Id.to_string fi) ++
strbrk" cannot be defined because the projection" ++ str s ++ spc () ++
prlist_with_sep pr_comma pr_id projs ++ spc () ++ str have ++
strbrk " not defined.")
@@ -121,10 +183,10 @@ let warning_or_error coe indsp err =
(pr_id fi ++ strbrk " cannot be defined because it is not typable.")
in
if coe then errorlabstrm "structure" st;
- Flags.if_verbose ppnl (hov 0 (str"Warning: " ++ st))
+ Flags.if_verbose msg_warning (hov 0 st)
type field_status =
- | NoProjection of name
+ | NoProjection of Name.t
| Projection of constr
exception NotDefinable of record_error
@@ -148,7 +210,7 @@ let subst_projection fid l c =
| NoProjection (Name id) -> bad_projs := id :: !bad_projs; mkRel k
| NoProjection Anonymous ->
errorlabstrm "" (str "Field " ++ pr_id fid ++
- str " depends on the " ++ str (ordinal (k-depth-1)) ++ str
+ str " depends on the " ++ pr_nth (k-depth-1) ++ str
" field which has no name.")
else
mkRel (k-lv)
@@ -156,88 +218,121 @@ let subst_projection fid l c =
in
let c' = lift 1 c in (* to get [c] defined in ctxt [[params;fields;x:ind]] *)
let c'' = substrec 0 c' in
- if !bad_projs <> [] then
+ if not (List.is_empty !bad_projs) then
raise (NotDefinable (MissingProj (fid,List.rev !bad_projs)));
c''
-let instantiate_possibly_recursive_type indsp paramdecls fields =
- let subst = list_map_i (fun i _ -> mkRel i) 1 paramdecls in
- Termops.substl_rel_context (subst@[mkInd indsp]) fields
+let instantiate_possibly_recursive_type indu paramdecls fields =
+ let subst = List.map_i (fun i _ -> mkRel i) 1 paramdecls in
+ Termops.substl_rel_context (subst@[mkIndU indu]) fields
(* We build projections *)
-let declare_projections indsp ?(kind=StructureComponent) ?name coers fieldimpls fields =
+let declare_projections indsp ?(kind=StructureComponent) binder_name coers fieldimpls fields =
let env = Global.env() in
let (mib,mip) = Global.lookup_inductive indsp in
- let paramdecls = mib.mind_params_ctxt in
- let r = mkInd indsp in
+ let u = Declareops.inductive_instance mib in
+ let paramdecls = Inductive.inductive_paramdecls (mib, u) in
+ let poly = mib.mind_polymorphic and ctx = Univ.instantiate_univ_context mib.mind_universes in
+ let indu = indsp, u in
+ let r = mkIndU (indsp,u) in
let rp = applist (r, Termops.extended_rel_list 0 paramdecls) in
let paramargs = Termops.extended_rel_list 1 paramdecls in (*def in [[params;x:rp]]*)
- let x = match name with Some n -> Name n | None -> Namegen.named_hd (Global.env()) r Anonymous in
- let fields = instantiate_possibly_recursive_type indsp paramdecls fields in
+ let x = Name binder_name in
+ let fields = instantiate_possibly_recursive_type indu paramdecls fields in
let lifted_fields = Termops.lift_rel_context 1 fields in
- let (_,kinds,sp_projs,_) =
- list_fold_left3
- (fun (nfi,kinds,sp_projs,subst) coe (fi,optci,ti) impls ->
- let (sp_projs,subst) =
+ let primitive =
+ if !primitive_flag then
+ let is_primitive =
+ match mib.mind_record with
+ | Some (Some _) -> true
+ | Some None | None -> false
+ in
+ if not is_primitive then
+ Flags.if_verbose msg_warning
+ (hov 0 (str "The record " ++ Printer.pr_inductive env indsp ++
+ str" could not be defined as a primitive record"));
+ is_primitive
+ else false
+ in
+ let (_,_,kinds,sp_projs,_) =
+ List.fold_left3
+ (fun (nfi,i,kinds,sp_projs,subst) coe (fi,optci,ti) impls ->
+ let (sp_projs,i,subst) =
match fi with
| Anonymous ->
- (None::sp_projs,NoProjection fi::subst)
- | Name fid ->
- try
- let ccl = subst_projection fid subst ti in
- let body = match optci with
- | Some ci -> subst_projection fid subst ci
- | None ->
- (* [ccl] is defined in context [params;x:rp] *)
- (* [ccl'] is defined in context [params;x:rp;x:rp] *)
- let ccl' = liftn 1 2 ccl in
- let p = mkLambda (x, lift 1 rp, ccl') in
- let branch = it_mkLambda_or_LetIn (mkRel nfi) lifted_fields in
- let ci = Inductiveops.make_case_info env indsp LetStyle in
- mkCase (ci, p, mkRel 1, [|branch|]) in
- let proj =
- it_mkLambda_or_LetIn (mkLambda (x,rp,body)) paramdecls in
- let projtyp =
- it_mkProd_or_LetIn (mkProd (x,rp,ccl)) paramdecls in
- let kn =
+ (None::sp_projs,i,NoProjection fi::subst)
+ | Name fid -> try
+ let kn, term =
+ if optci = None && primitive then
+ (** Already defined in the kernel silently *)
+ let kn = destConstRef (Nametab.locate (Libnames.qualid_of_ident fid)) in
+ Declare.definition_message fid;
+ kn, mkProj (Projection.make kn false,mkRel 1)
+ else
+ let ccl = subst_projection fid subst ti in
+ let body = match optci with
+ | Some ci -> subst_projection fid subst ci
+ | None ->
+ (* [ccl] is defined in context [params;x:rp] *)
+ (* [ccl'] is defined in context [params;x:rp;x:rp] *)
+ let ccl' = liftn 1 2 ccl in
+ let p = mkLambda (x, lift 1 rp, ccl') in
+ let branch = it_mkLambda_or_LetIn (mkRel nfi) lifted_fields in
+ let ci = Inductiveops.make_case_info env indsp LetStyle in
+ mkCase (ci, p, mkRel 1, [|branch|])
+ in
+ let proj =
+ it_mkLambda_or_LetIn (mkLambda (x,rp,body)) paramdecls in
+ let projtyp =
+ it_mkProd_or_LetIn (mkProd (x,rp,ccl)) paramdecls in
try
- let cie = {
- const_entry_body = proj;
- const_entry_secctx = None;
- const_entry_type = Some projtyp;
- const_entry_opaque = false } in
- let k = (DefinitionEntry cie,IsDefinition kind) in
+ let entry = {
+ const_entry_body =
+ Future.from_val (Term_typing.mk_pure_proof proj);
+ const_entry_secctx = None;
+ const_entry_type = Some projtyp;
+ const_entry_polymorphic = poly;
+ const_entry_universes = ctx;
+ const_entry_opaque = false;
+ const_entry_inline_code = false;
+ const_entry_feedback = None } in
+ let k = (DefinitionEntry entry,IsDefinition kind) in
let kn = declare_constant ~internal:KernelSilent fid k in
- Flags.if_verbose message (string_of_id fid ^" is defined");
- kn
+ let constr_fip =
+ let proj_args = (*Rel 1 refers to "x"*) paramargs@[mkRel 1] in
+ applist (mkConstU (kn,u),proj_args)
+ in
+ Declare.definition_message fid;
+ kn, constr_fip
with Type_errors.TypeError (ctx,te) ->
- raise (NotDefinable (BadTypedProj (fid,ctx,te))) in
- let refi = ConstRef kn in
- let constr_fi = mkConst kn in
- Impargs.maybe_declare_manual_implicits false refi impls;
- if coe then begin
- let cl = Class.class_of_global (IndRef indsp) in
- Class.try_add_new_coercion_with_source refi Global ~source:cl
- end;
- let proj_args = (*Rel 1 refers to "x"*) paramargs@[mkRel 1] in
- let constr_fip = applist (constr_fi,proj_args) in
- (Some kn::sp_projs, Projection constr_fip::subst)
+ raise (NotDefinable (BadTypedProj (fid,ctx,te)))
+ in
+ let refi = ConstRef kn in
+ Impargs.maybe_declare_manual_implicits false refi impls;
+ if coe then begin
+ let cl = Class.class_of_global (IndRef indsp) in
+ Class.try_add_new_coercion_with_source refi ~local:false poly ~source:cl
+ end;
+ let i = if Option.is_empty optci then i+1 else i in
+ (Some kn::sp_projs, i, Projection term::subst)
with NotDefinable why ->
warning_or_error coe indsp why;
- (None::sp_projs,NoProjection fi::subst) in
- (nfi-1,(fi, optci=None)::kinds,sp_projs,subst))
- (List.length fields,[],[],[]) coers (List.rev fields) (List.rev fieldimpls)
+ (None::sp_projs,i,NoProjection fi::subst) in
+ (nfi-1,i,(fi, Option.is_empty optci)::kinds,sp_projs,subst))
+ (List.length fields,0,[],[],[]) coers (List.rev fields) (List.rev fieldimpls)
in (kinds,sp_projs)
let structure_signature ctx =
let rec deps_to_evar evm l =
match l with [] -> Evd.empty
- | [(_,_,typ)] -> Evd.add evm (Evarutil.new_untyped_evar())
- (Evd.make_evar Environ.empty_named_context_val typ)
+ | [(_,_,typ)] ->
+ let env = Environ.empty_named_context_val in
+ let (evm, _) = Evarutil.new_pure_evar env evm typ in
+ evm
| (_,_,typ)::tl ->
- let ev = Evarutil.new_untyped_evar() in
- let evm = Evd.add evm ev (Evd.make_evar Environ.empty_named_context_val typ) in
- let new_tl = Util.list_map_i
+ let env = Environ.empty_named_context_val in
+ let (evm, ev) = Evarutil.new_pure_evar env evm typ in
+ let new_tl = Util.List.map_i
(fun pos (n,c,t) -> n,c,
Termops.replace_term (mkRel pos) (mkEvar(ev,[||])) t) 1 tl in
deps_to_evar evm new_tl in
@@ -245,45 +340,43 @@ let structure_signature ctx =
open Typeclasses
-let declare_structure finite infer id idbuild paramimpls params arity fieldimpls fields
- ?(kind=StructureComponent) ?name is_coe coers sign =
+let declare_structure finite poly ctx id idbuild paramimpls params arity template
+ fieldimpls fields ?(kind=StructureComponent) ?name is_coe coers sign =
let nparams = List.length params and nfields = List.length fields in
let args = Termops.extended_rel_list nfields params in
let ind = applist (mkRel (1+nparams+nfields), args) in
let type_constructor = it_mkProd_or_LetIn ind fields in
+ let binder_name =
+ match name with
+ | None -> Id.of_string (Unicode.lowercase_first_char (Id.to_string id))
+ | Some n -> n
+ in
let mie_ind =
{ mind_entry_typename = id;
mind_entry_arity = arity;
+ mind_entry_template = not poly && template;
mind_entry_consnames = [idbuild];
mind_entry_lc = [type_constructor] }
in
- (* spiwack: raises an error if the structure is supposed to be non-recursive,
- but isn't *)
- (* there is probably a way to push this to "declare_mutual" *)
- begin match finite with
- | BiFinite ->
- if Termops.dependent (mkRel (nparams+1)) (it_mkProd_or_LetIn mkProp fields) then
- error "Records declared with the keyword Record or Structure cannot be recursive. You can, however, define recursive records using the Inductive or CoInductive command."
- | _ -> ()
- end;
let mie =
{ mind_entry_params = List.map degenerate_decl params;
- mind_entry_record = true;
- mind_entry_finite = recursivity_flag_of_kind finite;
- mind_entry_inds = [mie_ind] } in
- let kn = Command.declare_mutual_inductive_with_eliminations KernelVerbose mie [(paramimpls,[])] in
+ mind_entry_record = Some (if !primitive_flag then Some binder_name else None);
+ mind_entry_finite = finite;
+ mind_entry_inds = [mie_ind];
+ mind_entry_polymorphic = poly;
+ mind_entry_private = None;
+ mind_entry_universes = ctx } in
+ let kn = Command.declare_mutual_inductive_with_eliminations mie [(paramimpls,[])] in
let rsp = (kn,0) in (* This is ind path of idstruc *)
let cstr = (rsp,1) in
- let kinds,sp_projs = declare_projections rsp ~kind ?name coers fieldimpls fields in
+ let kinds,sp_projs = declare_projections rsp ~kind binder_name coers fieldimpls fields in
let build = ConstructRef cstr in
- if is_coe then Class.try_add_new_coercion build Global;
+ let () = if is_coe then Class.try_add_new_coercion build ~local:false poly in
Recordops.declare_structure(rsp,cstr,List.rev kinds,List.rev sp_projs);
- if infer then
- Evd.fold (fun ev evi () -> Recordops.declare_method (ConstructRef cstr) ev sign) sign ();
rsp
let implicits_of_context ctx =
- list_map_i (fun i name ->
+ List.map_i (fun i name ->
let explname =
match name with
| Name n -> Some n
@@ -291,44 +384,32 @@ let implicits_of_context ctx =
in ExplByPos (i, explname), (true, true, true))
1 (List.rev (Anonymous :: (List.map pi1 ctx)))
-let declare_instance_cst glob con pri =
- let instance = Typeops.type_of_constant (Global.env ()) con in
- let _, r = decompose_prod_assum instance in
- match class_of_constr r with
- | Some (_, (tc, _)) -> add_instance (new_instance tc pri glob (ConstRef con))
- | None -> errorlabstrm "" (Pp.strbrk "Constant does not build instances of a declared type class.")
-
-let declare_class finite def infer id idbuild paramimpls params arity fieldimpls fields
- ?(kind=StructureComponent) ?name is_coe coers priorities sign =
+let declare_class finite def poly ctx id idbuild paramimpls params arity
+ template fieldimpls fields ?(kind=StructureComponent) is_coe coers priorities sign =
let fieldimpls =
- (* Make the class and all params implicits in the projections *)
- let ctx_impls = implicits_of_context params in
- let len = succ (List.length params) in
- List.map (fun x -> ctx_impls @ Impargs.lift_implicits len x) fieldimpls
+ (* Make the class implicit in the projections, and the params if applicable. *)
+ let len = List.length params in
+ let impls = implicits_of_context params in
+ List.map (fun x -> impls @ Impargs.lift_implicits (succ len) x) fieldimpls
in
+ let binder_name = Namegen.next_ident_away (snd id) (Termops.ids_of_context (Global.env())) in
let impl, projs =
match fields with
| [(Name proj_name, _, field)] when def ->
let class_body = it_mkLambda_or_LetIn field params in
- let class_type = Option.map (fun ar -> it_mkProd_or_LetIn ar params) arity in
- let class_entry =
- { const_entry_body = class_body;
- const_entry_secctx = None;
- const_entry_type = class_type;
- const_entry_opaque = false }
- in
+ let _class_type = it_mkProd_or_LetIn arity params in
+ let class_entry =
+ Declare.definition_entry (* ?types:class_type *) ~poly ~univs:ctx class_body in
let cst = Declare.declare_constant (snd id)
(DefinitionEntry class_entry, IsDefinition Definition)
in
- let inst_type = appvectc (mkConst cst) (Termops.rel_vect 0 (List.length params)) in
- let proj_type = it_mkProd_or_LetIn (mkProd(Name (snd id), inst_type, lift 1 field)) params in
- let proj_body = it_mkLambda_or_LetIn (mkLambda (Name (snd id), inst_type, mkRel 1)) params in
- let proj_entry =
- { const_entry_body = proj_body;
- const_entry_secctx = None;
- const_entry_type = Some proj_type;
- const_entry_opaque = false }
- in
+ let cstu = (cst, if poly then Univ.UContext.instance ctx else Univ.Instance.empty) in
+ let inst_type = appvectc (mkConstU cstu) (Termops.rel_vect 0 (List.length params)) in
+ let proj_type =
+ it_mkProd_or_LetIn (mkProd(Name binder_name, inst_type, lift 1 field)) params in
+ let proj_body =
+ it_mkLambda_or_LetIn (mkLambda (Name binder_name, inst_type, mkRel 1)) params in
+ let proj_entry = Declare.definition_entry ~types:proj_type ~poly ~univs:ctx proj_body in
let proj_cst = Declare.declare_constant proj_name
(DefinitionEntry proj_entry, IsDefinition Definition)
in
@@ -336,54 +417,87 @@ let declare_class finite def infer id idbuild paramimpls params arity fieldimpls
Impargs.declare_manual_implicits false cref [paramimpls];
Impargs.declare_manual_implicits false (ConstRef proj_cst) [List.hd fieldimpls];
Classes.set_typeclass_transparency (EvalConstRef cst) false false;
- if infer then Evd.fold (fun ev evi _ -> Recordops.declare_method (ConstRef cst) ev sign) sign ();
- let sub = match List.hd coers with Some b -> Some ((if b then Backward else Forward), List.hd priorities) | None -> None in
+ let sub = match List.hd coers with
+ | Some b -> Some ((if b then Backward else Forward), List.hd priorities)
+ | None -> None
+ in
cref, [Name proj_name, sub, Some proj_cst]
| _ ->
- let idarg = Namegen.next_ident_away (snd id) (Termops.ids_of_context (Global.env())) in
- let ind = declare_structure BiFinite infer (snd id) idbuild paramimpls
- params (Option.default (Termops.new_Type ()) arity) fieldimpls fields
- ~kind:Method ~name:idarg false (List.map (fun _ -> false) fields) sign
+ let ind = declare_structure BiFinite poly ctx (snd id) idbuild paramimpls
+ params arity template fieldimpls fields
+ ~kind:Method ~name:binder_name false (List.map (fun _ -> false) fields) sign
in
let coers = List.map2 (fun coe pri ->
- Option.map (fun b -> if b then Backward, pri else Forward, pri) coe)
- coers priorities
+ Option.map (fun b ->
+ if b then Backward, pri else Forward, pri) coe)
+ coers priorities
in
- IndRef ind, (list_map3 (fun (id, _, _) b y -> (id, b, y))
+ IndRef ind, (List.map3 (fun (id, _, _) b y -> (id, b, y))
(List.rev fields) coers (Recordops.lookup_projections ind))
in
let ctx_context =
List.map (fun (na, b, t) ->
match Typeclasses.class_of_constr t with
- | Some (_, (cl, _)) -> Some (cl.cl_impl, true) (*List.exists (fun (_, n) -> n = na) supnames)*)
+ | Some (_, ((cl,_), _)) -> Some (cl.cl_impl, true)
| None -> None)
params, params
in
let k =
{ cl_impl = impl;
+ cl_strict = !typeclasses_strict;
+ cl_unique = !typeclasses_unique;
cl_context = ctx_context;
cl_props = fields;
cl_projs = projs }
in
-(* list_iter3 (fun p sub pri -> *)
-(* if sub then match p with (_, _, Some p) -> declare_instance_cst true p pri | _ -> ()) *)
-(* k.cl_projs coers priorities; *)
- add_class k; impl
+ add_class k; impl
+
+
+let add_constant_class cst =
+ let ty = Universes.unsafe_type_of_global (ConstRef cst) in
+ let ctx, arity = decompose_prod_assum ty in
+ let tc =
+ { cl_impl = ConstRef cst;
+ cl_context = (List.map (const None) ctx, ctx);
+ cl_props = [(Anonymous, None, arity)];
+ cl_projs = [];
+ cl_strict = !typeclasses_strict;
+ cl_unique = !typeclasses_unique
+ }
+ in add_class tc;
+ set_typeclass_transparency (EvalConstRef cst) false false
+
+let add_inductive_class ind =
+ let mind, oneind = Global.lookup_inductive ind in
+ let k =
+ let ctx = oneind.mind_arity_ctxt in
+ let inst = Univ.UContext.instance mind.mind_universes in
+ let ty = Inductive.type_of_inductive_knowing_parameters
+ (push_rel_context ctx (Global.env ()))
+ ((mind,oneind),inst)
+ (Array.map (fun x -> lazy x) (Termops.extended_rel_vect 0 ctx))
+ in
+ { cl_impl = IndRef ind;
+ cl_context = List.map (const None) ctx, ctx;
+ cl_props = [Anonymous, None, ty];
+ cl_projs = [];
+ cl_strict = !typeclasses_strict;
+ cl_unique = !typeclasses_unique }
+ in add_class k
-let interp_and_check_sort sort =
- Option.map (fun sort ->
- let env = Global.env() and sigma = Evd.empty in
- let s = interp_constr sigma env sort in
- if isSort (Reductionops.whd_betadeltaiota env sigma s) then s
- else user_err_loc (constr_loc sort,"", str"Sort expected.")) sort
+let declare_existing_class g =
+ match g with
+ | ConstRef x -> add_constant_class x
+ | IndRef x -> add_inductive_class x
+ | _ -> user_err_loc (Loc.dummy_loc, "declare_existing_class",
+ Pp.str"Unsupported class type, only constants and inductives are allowed")
open Vernacexpr
-open Autoinstance
(* [fs] corresponds to fields and [ps] to parameters; [coers] is a
list telling if the corresponding fields must me declared as coercions
or subinstances *)
-let definition_structure (kind,finite,infer,(is_coe,(loc,idstruc)),ps,cfs,idbuild,s) =
+let definition_structure (kind,poly,finite,(is_coe,(loc,idstruc)),ps,cfs,idbuild,s) =
let cfs,notations = List.split cfs in
let cfs,priorities = List.split cfs in
let coers,fs = List.split cfs in
@@ -392,26 +506,26 @@ let definition_structure (kind,finite,infer,(is_coe,(loc,idstruc)),ps,cfs,idbuil
| Vernacexpr.DefExpr ((_,Name id),_,_) -> id::acc
| _ -> acc in
let allnames = idstruc::(List.fold_left extract_name [] fs) in
- if not (list_distinct allnames) then error "Two objects have the same name";
- if not (kind = Class false) && List.exists ((<>) None) priorities then
+ if not (List.distinct_f Id.compare allnames)
+ then error "Two objects have the same name";
+ let isnot_class = match kind with Class false -> false | _ -> true in
+ if isnot_class && List.exists (fun opt -> not (Option.is_empty opt)) priorities then
error "Priorities only allowed for type class substructures";
(* Now, younger decl in params and fields is on top *)
- let sc = interp_and_check_sort s in
- let implpars, params, implfs, fields =
+ let ctx, arity, template, implpars, params, implfs, fields =
States.with_state_protection (fun () ->
- typecheck_params_and_fields idstruc sc ps notations fs) () in
+ typecheck_params_and_fields (kind = Class true) idstruc s ps notations fs) () in
let sign = structure_signature (fields@params) in
match kind with
| Class def ->
- let gr = declare_class finite def infer (loc,idstruc) idbuild
- implpars params sc implfs fields is_coe coers priorities sign in
- if infer then search_record declare_class_instance gr sign;
+ let gr = declare_class finite def poly ctx (loc,idstruc) idbuild
+ implpars params arity template implfs fields is_coe coers priorities sign in
gr
| _ ->
- let arity = Option.default (Termops.new_Type ()) sc in
let implfs = List.map
- (fun impls -> implpars @ Impargs.lift_implicits (succ (List.length params)) impls) implfs in
- let ind = declare_structure finite infer idstruc idbuild implpars params arity implfs
- fields is_coe (List.map (fun coe -> coe <> None) coers) sign in
- if infer then search_record declare_record_instance (ConstructRef (ind,1)) sign;
+ (fun impls -> implpars @ Impargs.lift_implicits
+ (succ (List.length params)) impls) implfs in
+ let ind = declare_structure finite poly ctx idstruc
+ idbuild implpars params arity template implfs
+ fields is_coe (List.map (fun coe -> not (Option.is_empty coe)) coers) sign in
IndRef ind