aboutsummaryrefslogtreecommitdiff
path: root/library
diff options
context:
space:
mode:
Diffstat (limited to 'library')
-rw-r--r--library/universes.ml192
-rw-r--r--library/universes.mli142
2 files changed, 289 insertions, 45 deletions
diff --git a/library/universes.ml b/library/universes.ml
index 765d34f98f..11ab849c52 100644
--- a/library/universes.ml
+++ b/library/universes.ml
@@ -15,6 +15,198 @@ open Environ
open Locus
open Univ
+type universe_constraint_type = ULe | UEq | ULub
+
+type universe_constraint = universe * universe_constraint_type * universe
+
+module Constraints = struct
+ module S = Set.Make(
+ struct
+ type t = universe_constraint
+
+ let compare_type c c' =
+ match c, c' with
+ | ULe, ULe -> 0
+ | ULe, _ -> -1
+ | _, ULe -> 1
+ | UEq, UEq -> 0
+ | UEq, _ -> -1
+ | ULub, ULub -> 0
+ | ULub, _ -> 1
+
+ let compare (u,c,v) (u',c',v') =
+ let i = compare_type c c' in
+ if Int.equal i 0 then
+ let i' = Universe.compare u u' in
+ if Int.equal i' 0 then Universe.compare v v'
+ else
+ if c != ULe && Universe.compare u v' = 0 && Universe.compare v u' = 0 then 0
+ else i'
+ else i
+ end)
+
+ include S
+
+ let add (l,d,r as cst) s =
+ if Universe.equal l r then s
+ else add cst s
+
+ let tr_dir = function
+ | ULe -> Le
+ | UEq -> Eq
+ | ULub -> Eq
+
+ let op_str = function ULe -> " <= " | UEq -> " = " | ULub -> " /\\ "
+
+ let pr c =
+ fold (fun (u1,op,u2) pp_std ->
+ pp_std ++ Universe.pr u1 ++ str (op_str op) ++
+ Universe.pr u2 ++ fnl ()) c (str "")
+
+ let equal x y =
+ x == y || equal x y
+
+end
+
+type universe_constraints = Constraints.t
+type 'a universe_constrained = 'a * universe_constraints
+
+type 'a universe_constraint_function = 'a -> 'a -> universe_constraints -> universe_constraints
+
+let enforce_eq_instances_univs strict x y c =
+ let d = if strict then ULub else UEq in
+ let ax = Instance.to_array x and ay = Instance.to_array y in
+ if Array.length ax != Array.length ay then
+ Errors.anomaly (Pp.str "Invalid argument: enforce_eq_instances_univs called with" ++
+ Pp.str " instances of different lengths");
+ CArray.fold_right2
+ (fun x y -> Constraints.add (Universe.make x, d, Universe.make y))
+ ax ay c
+
+let subst_univs_universe_constraint fn (u,d,v) =
+ let u' = subst_univs_universe fn u and v' = subst_univs_universe fn v in
+ if Universe.equal u' v' then None
+ else Some (u',d,v')
+
+let subst_univs_universe_constraints subst csts =
+ Constraints.fold
+ (fun c -> Option.fold_right Constraints.add (subst_univs_universe_constraint subst c))
+ csts Constraints.empty
+
+
+let to_constraints g s =
+ let tr (x,d,y) acc =
+ let add l d l' acc = Constraint.add (l,Constraints.tr_dir d,l') acc in
+ match Universe.level x, d, Universe.level y with
+ | Some l, (ULe | UEq | ULub), Some l' -> add l d l' acc
+ | _, ULe, Some l' -> enforce_leq x y acc
+ | _, ULub, _ -> acc
+ | _, d, _ ->
+ let f = if d == ULe then check_leq else check_eq in
+ if f g x y then acc else
+ raise (Invalid_argument
+ "to_constraints: non-trivial algebraic constraint between universes")
+ in Constraints.fold tr s Constraint.empty
+
+let eq_constr_univs_infer univs m n =
+ if m == n then true, Constraints.empty
+ else
+ let cstrs = ref Constraints.empty in
+ let eq_universes strict = Univ.Instance.check_eq univs in
+ let eq_sorts s1 s2 =
+ if Sorts.equal s1 s2 then true
+ else
+ let u1 = Sorts.univ_of_sort s1 and u2 = Sorts.univ_of_sort s2 in
+ if Univ.check_eq univs u1 u2 then true
+ else
+ (cstrs := Constraints.add (u1, UEq, u2) !cstrs;
+ true)
+ in
+ let rec eq_constr' m n =
+ m == n || Constr.compare_head_gen eq_universes eq_sorts eq_constr' m n
+ in
+ let res = Constr.compare_head_gen eq_universes eq_sorts eq_constr' m n in
+ res, !cstrs
+
+let leq_constr_univs_infer univs m n =
+ if m == n then true, Constraints.empty
+ else
+ let cstrs = ref Constraints.empty in
+ let eq_universes strict l l' = Univ.Instance.check_eq univs l l' in
+ let eq_sorts s1 s2 =
+ if Sorts.equal s1 s2 then true
+ else
+ let u1 = Sorts.univ_of_sort s1 and u2 = Sorts.univ_of_sort s2 in
+ if Univ.check_eq univs u1 u2 then true
+ else (cstrs := Constraints.add (u1, UEq, u2) !cstrs;
+ true)
+ in
+ let leq_sorts s1 s2 =
+ if Sorts.equal s1 s2 then true
+ else
+ let u1 = Sorts.univ_of_sort s1 and u2 = Sorts.univ_of_sort s2 in
+ if Univ.check_leq univs u1 u2 then true
+ else
+ (cstrs := Constraints.add (u1, ULe, u2) !cstrs;
+ true)
+ in
+ let rec eq_constr' m n =
+ m == n || Constr.compare_head_gen eq_universes eq_sorts eq_constr' m n
+ in
+ let rec compare_leq m n =
+ Constr.compare_head_gen_leq eq_universes eq_sorts leq_sorts
+ eq_constr' leq_constr' m n
+ and leq_constr' m n = m == n || compare_leq m n in
+ let res = compare_leq m n in
+ res, !cstrs
+
+let eq_constr_universes m n =
+ if m == n then true, Constraints.empty
+ else
+ let cstrs = ref Constraints.empty in
+ let eq_universes strict l l' =
+ cstrs := enforce_eq_instances_univs strict l l' !cstrs; true in
+ let eq_sorts s1 s2 =
+ if Sorts.equal s1 s2 then true
+ else
+ (cstrs := Constraints.add
+ (Sorts.univ_of_sort s1, UEq, Sorts.univ_of_sort s2) !cstrs;
+ true)
+ in
+ let rec eq_constr' m n =
+ m == n || Constr.compare_head_gen eq_universes eq_sorts eq_constr' m n
+ in
+ let res = Constr.compare_head_gen eq_universes eq_sorts eq_constr' m n in
+ res, !cstrs
+
+let leq_constr_universes m n =
+ if m == n then true, Constraints.empty
+ else
+ let cstrs = ref Constraints.empty in
+ let eq_universes strict l l' =
+ cstrs := enforce_eq_instances_univs strict l l' !cstrs; true in
+ let eq_sorts s1 s2 =
+ if Sorts.equal s1 s2 then true
+ else (cstrs := Constraints.add
+ (Sorts.univ_of_sort s1,UEq,Sorts.univ_of_sort s2) !cstrs;
+ true)
+ in
+ let leq_sorts s1 s2 =
+ if Sorts.equal s1 s2 then true
+ else
+ (cstrs := Constraints.add
+ (Sorts.univ_of_sort s1,ULe,Sorts.univ_of_sort s2) !cstrs;
+ true)
+ in
+ let rec eq_constr' m n =
+ m == n || Constr.compare_head_gen eq_universes eq_sorts eq_constr' m n
+ in
+ let rec compare_leq m n =
+ Constr.compare_head_gen_leq eq_universes eq_sorts leq_sorts eq_constr' leq_constr' m n
+ and leq_constr' m n = m == n || compare_leq m n in
+ let res = compare_leq m n in
+ res, !cstrs
+
(* Generator of levels *)
let new_univ_level, set_remote_new_univ_level =
RemoteCounter.new_counter ~name:"Universes" 0 ~incr:((+) 1)
diff --git a/library/universes.mli b/library/universes.mli
index e5d3ded586..4cc92543b2 100644
--- a/library/universes.mli
+++ b/library/universes.mli
@@ -16,12 +16,64 @@ open Locus
open Univ
(** Universes *)
-val new_univ_level : Names.dir_path -> universe_level
+
+(** The global universe counter *)
val set_remote_new_univ_level : universe_level RemoteCounter.installer
+
+(** Side-effecting functions creating new universe levels. *)
+
+val new_univ_level : Names.dir_path -> universe_level
val new_univ : Names.dir_path -> universe
val new_Type : Names.dir_path -> types
val new_Type_sort : Names.dir_path -> sorts
+val new_global_univ : unit -> universe in_universe_context_set
+val new_sort_in_family : sorts_family -> sorts
+
+(** {6 Constraints for type inference}
+
+ When doing conversion of universes, not only do we have =/<= constraints but
+ also Lub constraints which correspond to unification of two levels which might
+ not be necessary if unfolding is performed.
+*)
+
+type universe_constraint_type = ULe | UEq | ULub
+
+type universe_constraint = universe * universe_constraint_type * universe
+module Constraints : sig
+ include Set.S with type elt = universe_constraint
+
+ val pr : t -> Pp.std_ppcmds
+end
+
+type universe_constraints = Constraints.t
+type 'a universe_constrained = 'a * universe_constraints
+type 'a universe_constraint_function = 'a -> 'a -> universe_constraints -> universe_constraints
+
+val subst_univs_universe_constraints : universe_subst_fn ->
+ universe_constraints -> universe_constraints
+
+val enforce_eq_instances_univs : bool -> universe_instance universe_constraint_function
+
+val to_constraints : universes -> universe_constraints -> constraints
+
+(** [eq_constr_univs_infer u a b] is [true, c] if [a] equals [b] modulo alpha, casts,
+ application grouping, the universe constraints in [u] and additional constraints [c]. *)
+val eq_constr_univs_infer : Univ.universes -> constr -> constr -> bool universe_constrained
+
+(** [leq_constr_univs u a b] is [true, c] if [a] is convertible to [b]
+ modulo alpha, casts, application grouping, the universe constraints
+ in [u] and additional constraints [c]. *)
+val leq_constr_univs_infer : Univ.universes -> constr -> constr -> bool universe_constrained
+
+(** [eq_constr_universes a b] [true, c] if [a] equals [b] modulo alpha, casts,
+ application grouping and the universe constraints in [c]. *)
+val eq_constr_universes : constr -> constr -> bool universe_constrained
+
+(** [leq_constr_universes a b] [true, c] if [a] is convertible to [b] modulo
+ alpha, casts, application grouping and the universe constraints in [c]. *)
+val leq_constr_universes : constr -> constr -> bool universe_constrained
+
(** Build a fresh instance for a given context, its associated substitution and
the instantiated constraints. *)
@@ -31,9 +83,6 @@ val fresh_instance_from_context : universe_context ->
val fresh_instance_from : universe_context -> universe_instance option ->
(universe_instance * universe_level_subst) in_universe_context_set
-val new_global_univ : unit -> universe in_universe_context_set
-val new_sort_in_family : sorts_family -> sorts
-
val fresh_sort_in_family : env -> sorts_family ->
sorts in_universe_context_set
val fresh_constant_instance : env -> constant ->
@@ -49,6 +98,11 @@ val fresh_global_instance : ?names:Univ.Instance.t -> env -> Globnames.global_re
val fresh_global_or_constr_instance : env -> Globnames.global_reference_or_constr ->
constr in_universe_context_set
+(** Get fresh variables for the universe context.
+ Useful to make tactics that manipulate constrs in universe contexts polymorphic. *)
+val fresh_universe_context_set_instance : universe_context_set ->
+ universe_level_subst * universe_context_set
+
(** Raises [Not_found] if not a global reference. *)
val global_of_constr : constr -> Globnames.global_reference puniverses
@@ -78,39 +132,6 @@ val make_opt_subst : universe_opt_subst -> universe_subst_fn
val subst_opt_univs_constr : universe_opt_subst -> constr -> constr
-val choose_canonical : universe_set -> (Level.t -> bool) (* flexibles *) -> universe_set -> universe_set ->
- universe_level * (universe_set * universe_set * universe_set)
-
-val instantiate_with_lbound :
- Univ.LMap.key ->
- Univ.universe ->
- bool ->
- bool ->
- Univ.LSet.t * Univ.universe option Univ.LMap.t *
- Univ.LSet.t *
- (bool * bool * Univ.universe) Univ.LMap.t * Univ.constraints ->
- (Univ.LSet.t * Univ.universe option Univ.LMap.t *
- Univ.LSet.t *
- (bool * bool * Univ.universe) Univ.LMap.t * Univ.constraints) *
- (bool * bool * Univ.universe)
-
-val compute_lbound : (constraint_type * Univ.universe) list -> universe option
-
-type constraints_map = (Univ.constraint_type * Univ.LMap.key) list Univ.LMap.t
-
-val pr_constraints_map : constraints_map -> Pp.std_ppcmds
-
-val minimize_univ_variables :
- Univ.LSet.t ->
- Univ.universe option Univ.LMap.t ->
- Univ.LSet.t ->
- constraints_map -> constraints_map ->
- Univ.constraints ->
- Univ.LSet.t * Univ.universe option Univ.LMap.t *
- Univ.LSet.t *
- (bool * bool * Univ.universe) Univ.LMap.t * Univ.constraints
-
-
val normalize_context_set : universe_context_set ->
universe_opt_subst (* The defined and undefined variables *) ->
universe_set (* univ variables that can be substituted by algebraics *) ->
@@ -141,7 +162,6 @@ val normalize_universe_subst : universe_subst ref ->
the constraints should be properly added to an evd.
See Evd.fresh_global, Evarutil.new_global, and pf_constr_of_global for
the proper way to get a fresh copy of a global reference. *)
-
val constr_of_global : Globnames.global_reference -> constr
(** ** DEPRECATED ** synonym of [constr_of_global] *)
@@ -171,13 +191,6 @@ val nf_evars_and_universes_local : (existential -> constr option) -> universe_le
val nf_evars_and_universes_opt_subst : (existential -> constr option) ->
universe_opt_subst -> constr -> constr
-(** Get fresh variables for the universe context.
- Useful to make tactics that manipulate constrs in universe contexts polymorphic. *)
-val fresh_universe_context_set_instance : universe_context_set ->
- universe_level_subst * universe_context_set
-
-val pr_universe_opt_subst : universe_opt_subst -> Pp.std_ppcmds
-
(** Shrink a universe context to a restricted set of variables *)
val universes_of_constr : constr -> universe_set
@@ -189,3 +202,42 @@ val simplify_universe_context : universe_context_set ->
val refresh_constraints : universes -> universe_context_set -> universe_context_set * universes
val remove_trivial_constraints : universe_context_set -> universe_context_set
+
+(** Pretty-printing *)
+
+val pr_universe_opt_subst : universe_opt_subst -> Pp.std_ppcmds
+
+(* For tracing *)
+
+type constraints_map = (Univ.constraint_type * Univ.LMap.key) list Univ.LMap.t
+
+val pr_constraints_map : constraints_map -> Pp.std_ppcmds
+
+val choose_canonical : universe_set -> (Level.t -> bool) (* flexibles *) -> universe_set -> universe_set ->
+ universe_level * (universe_set * universe_set * universe_set)
+
+val compute_lbound : (constraint_type * Univ.universe) list -> universe option
+
+val instantiate_with_lbound :
+ Univ.LMap.key ->
+ Univ.universe ->
+ bool ->
+ bool ->
+ Univ.LSet.t * Univ.universe option Univ.LMap.t *
+ Univ.LSet.t *
+ (bool * bool * Univ.universe) Univ.LMap.t * Univ.constraints ->
+ (Univ.LSet.t * Univ.universe option Univ.LMap.t *
+ Univ.LSet.t *
+ (bool * bool * Univ.universe) Univ.LMap.t * Univ.constraints) *
+ (bool * bool * Univ.universe)
+
+val minimize_univ_variables :
+ Univ.LSet.t ->
+ Univ.universe option Univ.LMap.t ->
+ Univ.LSet.t ->
+ constraints_map -> constraints_map ->
+ Univ.constraints ->
+ Univ.LSet.t * Univ.universe option Univ.LMap.t *
+ Univ.LSet.t *
+ (bool * bool * Univ.universe) Univ.LMap.t * Univ.constraints
+