aboutsummaryrefslogtreecommitdiff
path: root/pretyping
diff options
context:
space:
mode:
Diffstat (limited to 'pretyping')
-rw-r--r--pretyping/typeclasses.ml80
-rw-r--r--pretyping/typeclasses.mli19
2 files changed, 85 insertions, 14 deletions
diff --git a/pretyping/typeclasses.ml b/pretyping/typeclasses.ml
index 89e0fc93d7..128d3a6a71 100644
--- a/pretyping/typeclasses.ml
+++ b/pretyping/typeclasses.ml
@@ -41,6 +41,11 @@ let classes_transparent_state_ref = ref (fun () -> assert false)
let register_classes_transparent_state = (:=) classes_transparent_state_ref
let classes_transparent_state () = !classes_transparent_state_ref ()
+let solve_instanciation_problem = ref (fun _ _ _ -> assert false)
+
+let resolve_one_typeclass env evm t =
+ !solve_instanciation_problem env evm t
+
type rels = constr list
(* This module defines type-classes *)
@@ -55,8 +60,9 @@ type typeclass = {
cl_props : rel_context;
(* The method implementaions as projections. *)
- cl_projs : (name * bool * constant option) list;
+ cl_projs : (name * int option option * constant option) list;
}
+
module Gmap = Fmap.Make(RefOrdered)
type typeclasses = typeclass Gmap.t
@@ -68,7 +74,7 @@ type instance = {
-1 for discard, 0 for none, mutable to avoid redeclarations
when multiple rebuild_object happen. *)
is_global: int;
- is_impl: global_reference;
+ is_impl: global_reference;
}
type instances = (instance Gmap.t) Gmap.t
@@ -224,6 +230,45 @@ let class_input : typeclass -> obj =
let add_class cl =
Lib.add_anonymous_leaf (class_input cl)
+(** Build the subinstances hints. *)
+
+let check_instance env sigma c =
+ try
+ let (evd, c) = resolve_one_typeclass env sigma
+ (Retyping.get_type_of env sigma c) in
+ Evd.is_empty (Evd.undefined_evars evd)
+ with _ -> false
+
+let build_subclasses ~check env sigma glob pri =
+ let rec aux pri c =
+ let ty = Retyping.get_type_of env sigma c in
+ match class_of_constr ty with
+ | None -> []
+ | Some (rels, (tc, args)) ->
+ let instapp = Reductionops.whd_beta sigma (appvectc c (Termops.extended_rel_vect 0 rels)) in
+ let projargs = Array.of_list (args @ [instapp]) in
+ let projs = list_map_filter
+ (fun (n, b, proj) ->
+ match b with
+ | None -> None
+ | Some pri' ->
+ let proj = Option.get proj in
+ let body = it_mkLambda_or_LetIn (mkApp (mkConst proj, projargs)) rels in
+ if check && check_instance env sigma body then None
+ else
+ let pri =
+ match pri, pri' with
+ | Some p, Some p' -> Some (p + p')
+ | Some p, None -> Some (p + 1)
+ | _, _ -> None
+ in
+ Some (ConstRef proj, pri, body)) tc.cl_projs
+ in
+ let declare_proj hints (cref, pri, body) =
+ let rest = aux pri body in
+ hints @ (pri, body) :: rest
+ in List.fold_left declare_proj [] projs
+ in aux pri (constr_of_global glob)
(*
* instances persistent object
@@ -268,9 +313,14 @@ let discharge_instance (_, (action, inst)) =
let is_local i = i.is_global = -1
+let add_instance check inst =
+ add_instance_hint (constr_of_global inst.is_impl) (is_local inst) inst.is_pri;
+ List.iter (fun (pri, c) -> add_instance_hint c (is_local inst) pri)
+ (build_subclasses ~check:(check && not (isVarRef inst.is_impl))
+ (Global.env ()) Evd.empty inst.is_impl inst.is_pri)
+
let rebuild_instance (action, inst) =
- if action = AddInstance then
- add_instance_hint inst.is_impl (is_local inst) inst.is_pri;
+ if action = AddInstance then add_instance true inst;
(action, inst)
let classify_instance (action, inst) =
@@ -280,7 +330,7 @@ let classify_instance (action, inst) =
let load_instance (_, (action, inst) as ai) =
cache_instance ai;
if action = AddInstance then
- add_instance_hint inst.is_impl (is_local inst) inst.is_pri
+ add_instance_hint (constr_of_global inst.is_impl) (is_local inst) inst.is_pri
let instance_input : instance_action * instance -> obj =
declare_object
@@ -295,12 +345,25 @@ let instance_input : instance_action * instance -> obj =
let add_instance i =
Lib.add_anonymous_leaf (instance_input (AddInstance, i));
- add_instance_hint i.is_impl (is_local i) i.is_pri
+ add_instance true i
let remove_instance i =
Lib.add_anonymous_leaf (instance_input (RemoveInstance, i));
remove_instance_hint i.is_impl
+let declare_instance pri local glob =
+ let c = constr_of_global glob in
+ let ty = Retyping.get_type_of (Global.env ()) Evd.empty c in
+ match class_of_constr ty with
+ | Some (rels, (tc, args) as _cl) ->
+ add_instance (new_instance tc pri (not local) glob)
+(* let path, hints = build_subclasses (not local) (Global.env ()) Evd.empty glob in *)
+(* let entries = List.map (fun (path, pri, c) -> (pri, local, path, c)) hints in *)
+(* Auto.add_hints local [typeclasses_db] (Auto.HintsResolveEntry entries); *)
+(* Auto.add_hints local [typeclasses_db] *)
+(* (Auto.HintsCutEntry (PathSeq (PathStar (PathAtom PathAny), path))) *)
+ | None -> ()
+
open Declarations
let add_constant_class cst =
@@ -381,6 +444,7 @@ let is_implicit_arg k =
| InternalHole -> true
| _ -> false
+
(* To embed a boolean for resolvability status.
This is essentially a hack to mark which evars correspond to
goals and do not need to be resolved when we have nested [resolve_all_evars]
@@ -416,11 +480,7 @@ let has_typeclasses evd =
evd false
let solve_instanciations_problem = ref (fun _ _ _ _ _ -> assert false)
-let solve_instanciation_problem = ref (fun _ _ _ -> assert false)
let resolve_typeclasses ?(onlyargs=false) ?(split=true) ?(fail=true) env evd =
if not (has_typeclasses evd) then evd
else !solve_instanciations_problem env evd onlyargs split fail
-
-let resolve_one_typeclass env evm t =
- !solve_instanciation_problem env evm t
diff --git a/pretyping/typeclasses.mli b/pretyping/typeclasses.mli
index e4db68fbcd..a00d23a9b2 100644
--- a/pretyping/typeclasses.mli
+++ b/pretyping/typeclasses.mli
@@ -34,8 +34,9 @@ type typeclass = {
(** The methods implementations of the typeclass as projections.
Some may be undefinable due to sorting restrictions or simply undefined if
- no name is provided. The boolean indicates subclasses. *)
- cl_projs : (name * bool * constant option) list;
+ no name is provided. The [int option option] indicates subclasses whose hint has
+ the given priority. *)
+ cl_projs : (name * int option option * constant option) list;
}
type instance
@@ -93,10 +94,20 @@ val set_typeclass_transparency : evaluable_global_reference -> bool -> bool -> u
val register_classes_transparent_state : (unit -> transparent_state) -> unit
val classes_transparent_state : unit -> transparent_state
-val register_add_instance_hint : (global_reference -> bool (* local? *) -> int option -> unit) -> unit
+val register_add_instance_hint : (constr -> bool (* local? *) -> int option -> unit) -> unit
val register_remove_instance_hint : (global_reference -> unit) -> unit
-val add_instance_hint : global_reference -> bool -> int option -> unit
+val add_instance_hint : constr -> bool -> int option -> unit
val remove_instance_hint : global_reference -> unit
val solve_instanciations_problem : (env -> evar_map -> bool -> bool -> bool -> evar_map) ref
val solve_instanciation_problem : (env -> evar_map -> types -> open_constr) ref
+
+val declare_instance : int option -> bool -> global_reference -> unit
+
+
+(** Build the subinstances hints for a given typeclass object.
+ check tells if we should check for existence of the
+ subinstances and add only the missing ones. *)
+
+val build_subclasses : check:bool -> env -> evar_map -> global_reference -> int option (* priority *) ->
+ (int option * constr) list