diff options
author | Samuel Mimram <smimram@debian.org> | 2008-07-25 15:12:53 +0200 |
---|---|---|
committer | Samuel Mimram <smimram@debian.org> | 2008-07-25 15:12:53 +0200 |
commit | a0cfa4f118023d35b767a999d5a2ac4b082857b4 (patch) | |
tree | dabcac548e299fee1da464c93b3dba98484f45b1 /toplevel/classes.ml | |
parent | 2281410e38ef99d025ea77194585a9bc019fdaa9 (diff) |
Imported Upstream version 8.2~beta3+dfsgupstream/8.2.beta3+dfsg
Diffstat (limited to 'toplevel/classes.ml')
-rw-r--r-- | toplevel/classes.ml | 737 |
1 files changed, 737 insertions, 0 deletions
diff --git a/toplevel/classes.ml b/toplevel/classes.ml new file mode 100644 index 00000000..8ed99cbd --- /dev/null +++ b/toplevel/classes.ml @@ -0,0 +1,737 @@ +(* -*- compile-command: "make -C .. bin/coqtop.byte" -*- *) +(************************************************************************) +(* v * The Coq Proof Assistant / The Coq Development Team *) +(* <O___,, * CNRS-Ecole Polytechnique-INRIA Futurs-Universite Paris Sud *) +(* \VV/ **************************************************************) +(* // * This file is distributed under the terms of the *) +(* * GNU Lesser General Public License Version 2.1 *) +(************************************************************************) + +(*i $Id: classes.ml 11161 2008-06-21 14:32:47Z msozeau $ i*) + +(*i*) +open Names +open Decl_kinds +open Term +open Termops +open Sign +open Entries +open Evd +open Environ +open Nametab +open Mod_subst +open Util +open Typeclasses_errors +open Typeclasses +open Libnames +open Constrintern +open Rawterm +open Topconstr +(*i*) + +open Decl_kinds +open Entries + +let hint_db = "typeclass_instances" + +let qualid_of_con c = + Qualid (dummy_loc, shortest_qualid_of_global Idset.empty (ConstRef c)) + +let _ = + Typeclasses.register_add_instance_hint + (fun inst pri -> + Flags.silently (fun () -> + Auto.add_hints false [hint_db] + (Vernacexpr.HintsResolve + [pri, CAppExpl (dummy_loc, (None, qualid_of_con inst), [])])) ()) + +let declare_instance_cst glob con = + 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 None glob con) + | None -> error "Constant does not build instances of a declared type class" + +let declare_instance glob idl = + let con = + try (match global (Ident idl) with + | ConstRef x -> x + | _ -> raise Not_found) + with _ -> error "Instance definition not found" + in declare_instance_cst glob con + +let mismatched_params env n m = mismatched_ctx_inst env Parameters n m +(* let mismatched_defs env n m = mismatched_ctx_inst env Definitions n m *) +let mismatched_props env n m = mismatched_ctx_inst env Properties n m + +type binder_list = (identifier located * bool * constr_expr) list + +let interp_binders_evars isevars env avoid l = + List.fold_left + (fun (env, ids, params) ((loc, i), t) -> + let n = Name i in + let t' = interp_binder_evars isevars env n t in + let d = (i,None,t') in + (push_named d env, i :: ids, d::params)) + (env, avoid, []) l + +let interp_typeclass_context_evars isevars env avoid l = + List.fold_left + (fun (env, ids, params) (iid, bk, l) -> + let t' = interp_binder_evars isevars env (snd iid) l in + let i = match snd iid with + | Anonymous -> Nameops.next_name_away (Termops.named_hd env t' Anonymous) ids + | Name id -> id + in + let d = (i,None,t') in + (push_named d env, i :: ids, d::params)) + (env, avoid, []) l + +let interp_constrs_evars isevars env avoid l = + List.fold_left + (fun (env, ids, params) t -> + let t' = interp_binder_evars isevars env Anonymous t in + let id = Nameops.next_name_away (Termops.named_hd env t' Anonymous) ids in + let d = (id,None,t') in + (push_named d env, id :: ids, d::params)) + (env, avoid, []) l + +let raw_assum_of_binders k = + List.map (fun ((loc,i),t) -> LocalRawAssum ([(loc, Name i)], k, t)) + +let raw_assum_of_constrs k = + List.map2 (fun t (n,_,_) -> LocalRawAssum ([(dummy_loc, Name n)], k, t)) + +let raw_assum_of_anonymous_constrs k = + List.map (fun t -> LocalRawAssum ([(dummy_loc, Anonymous)], k, t)) + +let decl_expr_of_binders = + List.map (fun ((loc,i),t) -> false, Vernacexpr.AssumExpr ((loc, Name i), t)) + +let rec unfold n f acc = + match n with + | 0 -> f 0 acc + | n -> unfold (n - 1) f (f n acc) + +(* Declare everything in the parameters as implicit, and the class instance as well *) +open Topconstr + +let declare_implicit_proj c proj imps sub = + let len = List.length c.cl_context in + let (ctx, _) = decompose_prod_n (len + 1) (Typeops.type_of_constant (Global.env()) (snd proj)) in + let expls = + let rec aux i expls = function + [] -> expls + | (Name n, _) :: tl -> + let impl = ExplByPos (i, Some n), (true, true) in + aux (succ i) (impl :: List.remove_assoc (ExplByName n) expls) tl + | (Anonymous,_) :: _ -> assert(false) + in + aux 1 [] (List.rev ctx) + in + let expls = expls @ List.map (function (ExplByPos (i, n), f) -> (ExplByPos (succ len + i, n)), f | _ -> assert(false)) imps in + if sub then + declare_instance_cst true (snd proj); + Impargs.declare_manual_implicits false (ConstRef (snd proj)) true expls + +let declare_implicits impls subs cl = + Util.list_iter3 (fun p imps sub -> declare_implicit_proj cl p imps sub) + cl.cl_projs impls subs; + let len = List.length cl.cl_context in + let indimps = + list_fold_left_i + (fun i acc (is, (na, b, t)) -> + if len - i <= cl.cl_params then acc + else + match is with + None | Some (_, false) -> (ExplByPos (i, Some na), (false, true)) :: acc + | _ -> acc) + 1 [] (List.rev cl.cl_context) + in + Impargs.declare_manual_implicits false cl.cl_impl false indimps + +let rel_of_named_context subst l = + List.fold_right + (fun (id, _, t) (ctx, acc) -> (Name id, None, subst_vars acc t) :: ctx, id :: acc) + l ([], subst) + +let ids_of_rel_context subst l = + List.fold_right + (fun (id, _, t) acc -> Nameops.out_name id :: acc) + l subst + +let degenerate_decl (na,b,t) = + let id = match na with + | Name id -> id + | Anonymous -> anomaly "Unnamed record variable" in + match b with + | None -> (id, Entries.LocalAssum t) + | Some b -> (id, Entries.LocalDef b) + + +let declare_structure env id idbuild params arity fields = + let nparams = List.length params and nfields = List.length fields in + let args = 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 mie_ind = + { mind_entry_typename = id; + mind_entry_arity = arity; + mind_entry_consnames = [idbuild]; + mind_entry_lc = [type_constructor] } in + let mie = + { mind_entry_params = List.map degenerate_decl params; + mind_entry_record = true; + mind_entry_finite = true; + mind_entry_inds = [mie_ind] } in + let kn = Command.declare_mutual_with_eliminations true mie [] in + let rsp = (kn,0) in (* This is ind path of idstruc *) + let id = Nameops.next_ident_away id (ids_of_context (Global.env())) in + let kinds,sp_projs = Record.declare_projections rsp ~kind:Method ~name:id (List.map (fun _ -> false) fields) fields in + let _build = ConstructRef (rsp,1) in + Recordops.declare_structure(rsp,idbuild,List.rev kinds,List.rev sp_projs); + rsp + +let interp_type_evars evdref env ?(impls=([],[])) typ = + let typ' = intern_gen true ~impls (Evd.evars_of !evdref) env typ in + let imps = Implicit_quantifiers.implicits_of_rawterm typ' in + imps, Pretyping.Default.understand_tcc_evars evdref env Pretyping.IsType typ' + +let mk_interning_data env na impls typ = + let impl = Impargs.compute_implicits_with_manual env typ (Impargs.is_implicit_args()) impls + in (na, ([], impl, Notation.compute_arguments_scope typ)) + +let interp_fields_evars isevars env avoid l = + List.fold_left + (fun (env, uimpls, ids, params, impls) ((loc, i), _, t) -> + let impl, t' = interp_type_evars isevars env ~impls t in + let data = mk_interning_data env i impl t' in + let d = (i,None,t') in + (push_named d env, impl :: uimpls, Idset.add i ids, d::params, ([], data :: snd impls))) + (env, [], avoid, [], ([], [])) l + +let interp_fields_rel_evars isevars env avoid l = + List.fold_left + (fun (env, uimpls, ids, params, impls) ((loc, i), _, t) -> + let impl, t' = interp_type_evars isevars env ~impls t in + let data = mk_interning_data env i impl t' in + let d = (Name i,None,t') in + (push_rel d env, impl :: uimpls, Idset.add i ids, d::params, ([], data :: snd impls))) + (env, [], avoid, [], ([], [])) l + +let name_typeclass_binder avoid = function + | LocalRawAssum ([loc, Anonymous], bk, c) -> + let name = + let id = + match c with + CApp (_, (_, CRef (Ident (loc,id))), _) -> id + | _ -> id_of_string "assum" + in Implicit_quantifiers.make_fresh avoid (Global.env ()) id + in LocalRawAssum ([loc, Name name], bk, c), Idset.add name avoid + | x -> x, avoid + +let name_typeclass_binders avoid l = + let l', avoid = + List.fold_left + (fun (binders, avoid) b -> let b', avoid = name_typeclass_binder avoid b in + b' :: binders, avoid) + ([], avoid) l + in List.rev l', avoid + +let decompose_named_assum = + let rec prodec_rec subst l c = + match kind_of_term c with + | Prod (Name na,t,c) -> + let decl = (na,None,substl subst t) in + let subst' = mkVar na :: subst in + prodec_rec subst' (add_named_decl decl l) (substl subst' c) + | LetIn (Name na, b, t, c) -> + let decl = (na,Some (substl subst b),substl subst t) in + let subst' = mkVar na :: subst in + prodec_rec subst' (add_named_decl decl l) (substl subst' c) + | Cast (c,_,_) -> prodec_rec subst l c + | _ -> l,c + in prodec_rec [] [] + +let push_named_context = + List.fold_right push_named + +let named_of_rel_context (subst, ids, env as init) ctx = + Sign.fold_rel_context + (fun (na,c,t) (subst, avoid, env) -> + let id = Nameops.next_name_away na avoid in + let d = (id,Option.map (substl subst) c,substl subst t) in + (mkVar id :: subst, id::avoid, d::env)) + ctx ~init + +let new_class id par ar sup props = + let env0 = Global.env() in + let isevars = ref (Evd.create_evar_defs Evd.empty) in + let bound = Implicit_quantifiers.ids_of_list (Termops.ids_of_context env0) in + let bound, ids = Implicit_quantifiers.free_vars_of_binders ~bound [] (sup @ par) in + let bound = Idset.union bound (Implicit_quantifiers.ids_of_list ids) in + let sup, bound = name_typeclass_binders bound sup in + let supnames = + List.fold_left (fun acc b -> + match b with + LocalRawAssum (nl, _, _) -> nl @ acc + | LocalRawDef _ -> assert(false)) + [] sup + in + + (* Interpret the arity *) + let arity_imps, fullarity = + let ar = + match ar with + Some ar -> ar | None -> (dummy_loc, Rawterm.RType None) + in + let arity = CSort (fst ar, snd ar) in + let term = prod_constr_expr (prod_constr_expr arity par) sup in + interp_type_evars isevars env0 term + in + let ctx_params, arity = decompose_prod_assum fullarity in + let env_params = push_rel_context ctx_params env0 in + + (* Interpret the definitions and propositions *) + let env_props, prop_impls, bound, ctx_props, _ = + interp_fields_rel_evars isevars env_params bound props + in + let subs = List.map (fun ((loc, id), b, _) -> b) props in + (* Instantiate evars and check all are resolved *) + let isevars,_ = Evarconv.consider_remaining_unif_problems env_props !isevars in + let isevars = Typeclasses.resolve_typeclasses env_props isevars in + let sigma = Evd.evars_of isevars in + let ctx_params = Evarutil.nf_rel_context_evar sigma ctx_params in + let ctx_props = Evarutil.nf_rel_context_evar sigma ctx_props in + let arity = Reductionops.nf_evar sigma arity in + let ce t = Evarutil.check_evars env0 Evd.empty isevars t in + let impl, projs = + let params = ctx_params and fields = ctx_props in + List.iter (fun (_,c,t) -> ce t; match c with Some c -> ce c | None -> ()) (params @ fields); + match fields with + [(Name proj_name, _, field)] -> + let class_body = it_mkLambda_or_LetIn field params in + let class_type = + match ar with + Some _ -> Some (it_mkProd_or_LetIn arity params) + | None -> None + in + let class_entry = + { const_entry_body = class_body; + const_entry_type = class_type; + const_entry_opaque = false; + const_entry_boxed = false } + in + let cst = Declare.declare_constant (snd id) + (DefinitionEntry class_entry, IsDefinition Definition) + in + let inst_type = appvectc (mkConst cst) (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_type = Some proj_type; + const_entry_opaque = false; + const_entry_boxed = false } + in + let proj_cst = Declare.declare_constant proj_name + (DefinitionEntry proj_entry, IsDefinition Definition) + in + ConstRef cst, [proj_name, proj_cst] + | _ -> + let idb = id_of_string ("Build_" ^ (string_of_id (snd id))) in + let kn = declare_structure env0 (snd id) idb params arity fields in + IndRef kn, (List.map2 (fun (id, _, _) y -> Nameops.out_name id, Option.get y) + fields (Recordops.lookup_projections kn)) + in + let ids = List.map pi1 (named_context env0) in + let (subst, ids, named_ctx_params) = named_of_rel_context ([], ids, []) ctx_params in + let (_, _, named_ctx_props) = named_of_rel_context (subst, ids, []) ctx_props in + let ctx_context = + List.map (fun ((na, b, t) as d) -> + match Typeclasses.class_of_constr t with + | Some cl -> (Some (cl.cl_impl, List.exists (fun (_, n) -> n = Name na) supnames), d) + | None -> (None, d)) + named_ctx_params + in + let k = + { cl_impl = impl; + cl_params = List.length par; + cl_context = ctx_context; + cl_props = named_ctx_props; + cl_projs = projs } + in + declare_implicits (List.rev prop_impls) subs k; + add_class k + +type binder_def_list = (identifier located * identifier located list * constr_expr) list + +let binders_of_lidents l = + List.map (fun (loc, id) -> LocalRawAssum ([loc, Name id], Default Rawterm.Implicit, CHole (loc, None))) l + +let subst_ids_in_named_context subst l = + let x, _ = + List.fold_right + (fun (id, _, t) (ctx, k) -> (id, None, substn_vars k subst t) :: ctx, succ k) + l ([], 1) + in x + +let subst_one_named inst ids t = + substnl inst 0 (substn_vars 1 ids t) + +let subst_named inst subst ctx = + let ids = List.map (fun (id, _, _) -> id) subst in + let ctx' = subst_ids_in_named_context ids ctx in + let ctx', _ = + List.fold_right + (fun (id, _, t) (ctx, k) -> (id, None, substnl inst k t) :: ctx, succ k) + ctx' ([], 0) + in ctx' +(* +let infer_super_instances env params params_ctx super = + let super = subst_named params params_ctx super in + List.fold_right + (fun (na, _, t) (sups, ids, supctx) -> + let t = subst_one_named sups ids t in + let inst = + try resolve_one_typeclass env t + with Not_found -> + let cl, args = destClass t in + no_instance (push_named_context supctx env) (dummy_loc, cl.cl_name) (Array.to_list args) + in + let d = (na, Some inst, t) in + inst :: sups, na :: ids, d :: supctx) + super ([], [], [])*) + +(* let evars_of_context ctx id n env = *) +(* List.fold_right (fun (na, _, t) (n, env, nc) -> *) +(* let b = Evarutil.e_new_evar isevars env ~src:(dummy_loc, ImplicitArg (Ident id, (n * Some na))) t in *) +(* let d = (na, Some b, t) in *) +(* (succ n, push_named d env, d :: nc)) *) +(* ctx (n, env, []) *) + +let type_ctx_instance isevars env ctx inst subst = + List.fold_left2 + (fun (subst, instctx) (na, _, t) ce -> + let t' = replace_vars subst t in + let c = interp_casted_constr_evars isevars env ce t' in + let d = na, Some c, t' in + (na, c) :: subst, d :: instctx) + (subst, []) (List.rev ctx) inst + +let substitution_of_constrs ctx cstrs = + List.fold_right2 (fun c (na, _, _) acc -> (na, c) :: acc) cstrs ctx [] + +let destClassApp cl = + match cl with + | CApp (loc, (None,CRef (Ident f)), l) -> f, List.map fst l + | _ -> raise Not_found + +let refine_ref = ref (fun _ -> assert(false)) + +let id_of_class cl = + match cl.cl_impl with + | ConstRef kn -> let _,_,l = repr_con kn in id_of_label l + | IndRef (kn,i) -> + let mip = (Environ.lookup_mind kn (Global.env ())).Declarations.mind_packets in + mip.(0).Declarations.mind_typename + | _ -> assert false + +open Pp + +let ($$) g f = fun x -> g (f x) + +let default_on_free_vars = + Flags.if_verbose + (fun fvs -> + match fvs with + [] -> () + | l -> msgnl (str"Implicitly generalizing " ++ + prlist_with_sep (fun () -> str", ") Nameops.pr_id l ++ str".")) + +let fail_on_free_vars = function + [] -> () + | [fv] -> + errorlabstrm "Classes" + (str"Unbound variable " ++ Nameops.pr_id fv ++ str".") + | fvs -> errorlabstrm "Classes" + (str"Unbound variables " ++ + prlist_with_sep (fun () -> str", ") Nameops.pr_id fvs ++ str".") + +let instance_hook k pri global imps ?hook cst = + let inst = Typeclasses.new_instance k pri global cst in + Impargs.maybe_declare_manual_implicits false (ConstRef cst) false imps; + Typeclasses.add_instance inst; + (match hook with Some h -> h cst | None -> ()) + +let declare_instance_constant k pri global imps ?hook id term termtype = + let cdecl = + let kind = IsDefinition Instance in + let entry = + { const_entry_body = term; + const_entry_type = Some termtype; + const_entry_opaque = false; + const_entry_boxed = false } + in DefinitionEntry entry, kind + in + let kn = Declare.declare_constant id cdecl in + Flags.if_verbose Command.definition_message id; + instance_hook k pri global imps ?hook kn; + id + +let new_instance ?(global=false) ctx (instid, bk, cl) props ?(on_free_vars=default_on_free_vars) + ?(tac:Proof_type.tactic option) ?(hook:(Names.constant -> unit) option) pri = + let env = Global.env() in + let isevars = ref (Evd.create_evar_defs Evd.empty) in + let bound = Implicit_quantifiers.ids_of_list (Termops.ids_of_context env) in + let bound, fvs = Implicit_quantifiers.free_vars_of_binders ~bound [] ctx in + let tclass = + match bk with + | Implicit -> + let loc, id, par = Implicit_quantifiers.destClassAppExpl cl in + let k = class_info (Nametab.global id) in + let applen = List.fold_left (fun acc (x, y) -> if y = None then succ acc else acc) 0 par in + let needlen = List.fold_left (fun acc (x, y) -> if x = None then succ acc else acc) 0 k.cl_context in + if needlen <> applen then + mismatched_params env (List.map fst par) (List.map snd k.cl_context); + let pars, _ = Implicit_quantifiers.combine_params Idset.empty (* need no avoid *) + (fun avoid (clname, (id, _, t)) -> + match clname with + Some (cl, b) -> + let t = + if b then + let _k = class_info cl in + CHole (Util.dummy_loc, Some (Evd.ImplicitArg (k.cl_impl, (1, None)))) + else CHole (Util.dummy_loc, None) + in t, avoid + | None -> failwith ("new instance: under-applied typeclass")) + par (List.rev k.cl_context) + in Topconstr.CAppExpl (loc, (None, id), pars) + + | Explicit -> cl + in + let ctx_bound = Idset.union bound (Implicit_quantifiers.ids_of_list fvs) in + let gen_ids = Implicit_quantifiers.free_vars_of_constr_expr ~bound:ctx_bound tclass [] in + on_free_vars (List.rev fvs @ List.rev gen_ids); + let gen_idset = Implicit_quantifiers.ids_of_list gen_ids in + let bound = Idset.union gen_idset ctx_bound in + let gen_ctx = Implicit_quantifiers.binder_list_of_ids gen_ids in + let ctx, avoid = name_typeclass_binders bound ctx in + let ctx = List.append ctx (List.rev gen_ctx) in + let k, ctx', imps, subst = + let c = Command.generalize_constr_expr tclass ctx in + let imps, c' = interp_type_evars isevars env c in + let ctx, c = decompose_named_assum c' in + let cl, args = Typeclasses.dest_class_app c in + cl, ctx, imps, substitution_of_constrs (List.map snd cl.cl_context) (List.rev (Array.to_list args)) + in + let id = + match snd instid with + Name id -> + let sp = Lib.make_path id in + if Nametab.exists_cci sp then + errorlabstrm "new_instance" (Nameops.pr_id id ++ Pp.str " already exists"); + id + | Anonymous -> + let i = Nameops.add_suffix (id_of_class k) "_instance_0" in + Termops.next_global_ident_away false i (Termops.ids_of_context env) + in + let env' = push_named_context ctx' env in + isevars := Evarutil.nf_evar_defs !isevars; + isevars := resolve_typeclasses env !isevars; + let sigma = Evd.evars_of !isevars in + let substctx = Typeclasses.nf_substitution sigma subst in + if Lib.is_modtype () then + begin + let _, ty_constr = instance_constructor k (List.rev_map snd substctx) in + let termtype = + let t = it_mkNamedProd_or_LetIn ty_constr ctx' in + Evarutil.nf_isevar !isevars t + in + Evarutil.check_evars env Evd.empty !isevars termtype; + let cst = Declare.declare_internal_constant id + (Entries.ParameterEntry (termtype,false), Decl_kinds.IsAssumption Decl_kinds.Logical) + in instance_hook k None false imps ?hook cst; id + end + else + begin + let subst, _propsctx = + let props = + List.map (fun (x, l, d) -> + x, Topconstr.abstract_constr_expr d (binders_of_lidents l)) + props + in + if List.length props > List.length k.cl_props then + mismatched_props env' (List.map snd props) k.cl_props; + let props, rest = + List.fold_left + (fun (props, rest) (id,_,_) -> + try + let ((loc, mid), c) = List.find (fun ((_,id'), c) -> id' = id) rest in + let rest' = List.filter (fun ((_,id'), c) -> id' <> id) rest in + Constrintern.add_glob loc (ConstRef (List.assoc mid k.cl_projs)); + c :: props, rest' + with Not_found -> (CHole (Util.dummy_loc, None) :: props), rest) + ([], props) k.cl_props + in + if rest <> [] then + unbound_method env' k.cl_impl (fst (List.hd rest)) + else + type_ctx_instance isevars env' k.cl_props props substctx + in + let app, ty_constr = instance_constructor k (List.rev_map snd subst) in + let termtype = + let t = it_mkNamedProd_or_LetIn ty_constr ctx' in + Evarutil.nf_isevar !isevars t + in + let term = Termops.it_mkNamedLambda_or_LetIn app ctx' in + isevars := Evarutil.nf_evar_defs !isevars; + let term = Evarutil.nf_isevar !isevars term in + let evm = Evd.evars_of (undefined_evars !isevars) in + Evarutil.check_evars env Evd.empty !isevars termtype; + if evm = Evd.empty then + declare_instance_constant k pri global imps ?hook id term termtype + else begin + isevars := Typeclasses.resolve_typeclasses ~onlyargs:true ~fail:true env !isevars; + let kind = Decl_kinds.Global, Decl_kinds.DefinitionBody Decl_kinds.Instance in + Flags.silently (fun () -> + Command.start_proof id kind termtype + (fun _ -> function ConstRef cst -> instance_hook k pri global imps ?hook cst + | _ -> assert false); + if props <> [] then + Pfedit.by (* (Refiner.tclTHEN (Refiner.tclEVARS (Evd.evars_of !isevars)) *) + (!refine_ref (evm, term)); + (match tac with Some tac -> Pfedit.by tac | None -> ())) (); + Flags.if_verbose (msg $$ Printer.pr_open_subgoals) (); + id + end + end + +let goal_kind = Decl_kinds.Global, Decl_kinds.DefinitionBody Decl_kinds.Definition + +let solve_by_tac env evd evar evi t = + let goal = {it = evi; sigma = (Evd.evars_of evd) } in + let (res, valid) = t goal in + if res.it = [] then + let prooftree = valid [] in + let proofterm, obls = Refiner.extract_open_proof res.sigma prooftree in + if obls = [] then + let evd' = evars_reset_evd res.sigma evd in + let evd' = evar_define evar proofterm evd' in + evd', true + else evd, false + else evd, false + +let context ?(hook=fun _ -> ()) l = + let env = Global.env() in + let isevars = ref (Evd.create_evar_defs Evd.empty) in + let avoid = Termops.ids_of_context env in + let ctx, l = Implicit_quantifiers.resolve_class_binders (vars_of_env env) l in + let env', avoid, ctx = interp_binders_evars isevars env avoid ctx in + let env', avoid, l = interp_typeclass_context_evars isevars env' avoid l in + isevars := Evarutil.nf_evar_defs !isevars; + let sigma = Evd.evars_of !isevars in + let fullctx = Evarutil.nf_named_context_evar sigma (l @ ctx) in + List.iter (function (id,_,t) -> + if Lib.is_modtype () then + let cst = Declare.declare_internal_constant id + (ParameterEntry (t,false), IsAssumption Logical) + in + match class_of_constr t with + | Some tc -> + add_instance (Typeclasses.new_instance tc None false cst); + hook (ConstRef cst) + | None -> () + else + (Command.declare_one_assumption false (Local (* global *), Definitional) t + [] true (* implicit *) true (* always kept *) false (* inline *) (dummy_loc, id); + match class_of_constr t with + None -> () + | Some tc -> hook (VarRef id))) + (List.rev fullctx) + +open Libobject + +let module_qualid = qualid_of_dirpath (dirpath_of_string "Coq.Classes.Init") +let tactic_qualid = make_qualid (dirpath_of_string "Coq.Classes.Init") (id_of_string "typeclass_instantiation") + +let tactic_expr = Tacexpr.TacArg (Tacexpr.Reference (Qualid (dummy_loc, tactic_qualid))) +let tactic = lazy (Tacinterp.interp tactic_expr) + +let _ = + Typeclasses.solve_instanciation_problem := + (fun env evd ev evi -> + Library.require_library [(dummy_loc, module_qualid)] None; (* may be inefficient *) + solve_by_tac env evd ev evi (Lazy.force tactic)) + +(* let prod = lazy_fun Coqlib.build_prod *) + +(* let build_conjunction evm = *) +(* List.fold_left *) +(* (fun (acc, evs) (ev, evi) -> *) +(* if class_of_constr evi.evar_concl <> None then *) +(* mkApp ((Lazy.force prod).Coqlib.typ, [|evi.evar_concl; acc |]), evs *) +(* else acc, Evd.add evs ev evi) *) +(* (Coqlib.build_coq_True (), Evd.empty) evm *) + +(* let destruct_conjunction evm_list evm evm' term = *) +(* let _, evm = *) +(* List.fold_right *) +(* (fun (ev, evi) (term, evs) -> *) +(* if class_of_constr evi.evar_concl <> None then *) +(* match kind_of_term term with *) +(* | App (x, [| _ ; _ ; proof ; term |]) -> *) +(* let evs' = Evd.define evs ev proof in *) +(* (term, evs') *) +(* | _ -> assert(false) *) +(* else *) +(* match (Evd.find evm' ev).evar_body with *) +(* Evar_empty -> raise Not_found *) +(* | Evar_defined c -> *) +(* let evs' = Evd.define evs ev c in *) +(* (term, evs')) *) +(* evm_list (term, evm) *) +(* in evm *) + +(* let solve_by_tac env evd evar evi t = *) +(* let goal = {it = evi; sigma = (Evd.evars_of evd) } in *) +(* let (res, valid) = t goal in *) +(* if res.it = [] then *) +(* let prooftree = valid [] in *) +(* let proofterm, obls = Refiner.extract_open_proof res.sigma prooftree in *) +(* if obls = [] then *) +(* let evd' = evars_reset_evd res.sigma evd in *) +(* let evd' = evar_define evar proofterm evd' in *) +(* evd', true *) +(* else evd, false *) +(* else evd, false *) + +(* let resolve_all_typeclasses env evd = *) +(* let evm = Evd.evars_of evd in *) +(* let evm_list = Evd.to_list evm in *) +(* let goal, typesevm = build_conjunction evm_list in *) +(* let evars = ref (Evd.create_evar_defs typesevm) in *) +(* let term = resolve_one_typeclass_evd env evars goal in *) +(* let evm' = destruct_conjunction evm_list evm (Evd.evars_of !evars) term in *) +(* Evd.create_evar_defs evm' *) + +(* let _ = *) +(* Typeclasses.solve_instanciations_problem := *) +(* (fun env evd -> *) +(* Library.require_library [(dummy_loc, module_qualid)] None; (\* may be inefficient *\) *) +(* resolve_all_typeclasses env evd) *) + +let solve_evars_by_tac env evd t = + let ev = make_evar empty_named_context_val mkProp in + let goal = {it = ev; sigma = (Evd.evars_of evd) } in + let (res, valid) = t goal in + let evd' = evars_reset_evd res.sigma evd in + evd' +(* Library.require_library [(dummy_loc, module_qualid)] None (a\* may be inefficient *\); *) + +(* let _ = *) +(* Typeclasses.solve_instanciations_problem := *) +(* (fun env evd -> *) +(* Eauto.resolve_all_evars false (true, 15) env *) +(* (fun ev evi -> is_implicit_arg (snd (evar_source ev evd)) *) +(* && class_of_constr evi.evar_concl <> None) evd) *) |