aboutsummaryrefslogtreecommitdiff
path: root/pretyping
diff options
context:
space:
mode:
Diffstat (limited to 'pretyping')
-rw-r--r--pretyping/cases.ml4
-rw-r--r--pretyping/detyping.ml30
-rw-r--r--pretyping/detyping.mli2
-rw-r--r--pretyping/indrec.ml8
-rw-r--r--pretyping/pattern.ml6
-rw-r--r--pretyping/pretyping.ml34
-rw-r--r--pretyping/rawterm.ml28
-rw-r--r--pretyping/rawterm.mli8
-rw-r--r--pretyping/typeclasses.ml311
-rw-r--r--pretyping/typeclasses.mli70
-rw-r--r--pretyping/typeclasses_errors.ml42
-rw-r--r--pretyping/typeclasses_errors.mli40
12 files changed, 534 insertions, 49 deletions
diff --git a/pretyping/cases.ml b/pretyping/cases.ml
index 058f3d210d..e71083c509 100644
--- a/pretyping/cases.ml
+++ b/pretyping/cases.ml
@@ -1408,9 +1408,9 @@ let set_arity_signature dep n arsign tomatchl pred x =
let rec decomp_lam_force n avoid l p =
if n = 0 then (List.rev l,p,avoid) else
match p with
- | RLambda (_,(Name id as na),_,c) ->
+ | RLambda (_,(Name id as na),_,_,c) ->
decomp_lam_force (n-1) (id::avoid) (na::l) c
- | RLambda (_,(Anonymous as na),_,c) -> decomp_lam_force (n-1) avoid (na::l) c
+ | RLambda (_,(Anonymous as na),_,_,c) -> decomp_lam_force (n-1) avoid (na::l) c
| _ ->
let x = next_ident_away (id_of_string "x") avoid in
decomp_lam_force (n-1) (x::avoid) (Name x :: l)
diff --git a/pretyping/detyping.ml b/pretyping/detyping.ml
index 2cfa7076ae..a9e550bf7c 100644
--- a/pretyping/detyping.ml
+++ b/pretyping/detyping.ml
@@ -268,7 +268,7 @@ let is_nondep_branch c n =
let extract_nondep_branches test c b n =
let rec strip n r = if n=0 then r else
match r with
- | RLambda (_,_,_,t) -> strip (n-1) t
+ | RLambda (_,_,_,_,t) -> strip (n-1) t
| RLetIn (_,_,_,t) -> strip (n-1) t
| _ -> assert false in
if test c n then Some (strip n b) else None
@@ -276,7 +276,7 @@ let extract_nondep_branches test c b n =
let it_destRLambda_or_LetIn_names n c =
let rec aux n nal c =
if n=0 then (List.rev nal,c) else match c with
- | RLambda (_,na,_,c) -> aux (n-1) (na::nal) c
+ | RLambda (_,na,_,_,c) -> aux (n-1) (na::nal) c
| RLetIn (_,na,_,c) -> aux (n-1) (na::nal) c
| _ ->
(* eta-expansion *)
@@ -308,7 +308,7 @@ let detype_case computable detype detype_eqns testdep avoid data p c bl =
| Some p ->
let nl,typ = it_destRLambda_or_LetIn_names k p in
let n,typ = match typ with
- | RLambda (_,x,t,c) -> x, c
+ | RLambda (_,x,_,t,c) -> x, c
| _ -> Anonymous, typ in
let aliastyp =
if List.for_all ((=) Anonymous) nl then None
@@ -444,14 +444,14 @@ and share_names isgoal n l avoid env c t =
let t = detype isgoal avoid env t in
let id = next_name_away na avoid in
let avoid = id::avoid and env = add_name (Name id) env in
- share_names isgoal (n-1) ((Name id,None,t)::l) avoid env c c'
+ share_names isgoal (n-1) ((Name id,Explicit,None,t)::l) avoid env c c'
(* May occur for fix built interactively *)
| LetIn (na,b,t',c), _ when n > 0 ->
let t' = detype isgoal avoid env t' in
let b = detype isgoal avoid env b in
let id = next_name_away na avoid in
let avoid = id::avoid and env = add_name (Name id) env in
- share_names isgoal n ((Name id,Some b,t')::l) avoid env c t
+ share_names isgoal n ((Name id,Explicit,Some b,t')::l) avoid env c t
(* Only if built with the f/n notation or w/o let-expansion in types *)
| _, LetIn (_,b,_,t) when n > 0 ->
share_names isgoal n l avoid env c (subst1 b t)
@@ -461,7 +461,7 @@ and share_names isgoal n l avoid env c t =
let id = next_name_away na' avoid in
let avoid = id::avoid and env = add_name (Name id) env in
let appc = mkApp (lift 1 c,[|mkRel 1|]) in
- share_names isgoal (n-1) ((Name id,None,t')::l) avoid env appc c'
+ share_names isgoal (n-1) ((Name id,Explicit,None,t')::l) avoid env appc c'
(* If built with the f/n notation: we renounce to share names *)
| _ ->
if n>0 then warning "Detyping.detype: cannot factorize fix enough";
@@ -524,8 +524,8 @@ and detype_binder isgoal bk avoid env na ty c =
concrete_name (avoid_flag isgoal) avoid env na c in
let r = detype isgoal avoid' (add_name na' env) c in
match bk with
- | BProd -> RProd (dl, na',detype isgoal avoid env ty, r)
- | BLambda -> RLambda (dl, na',detype isgoal avoid env ty, r)
+ | BProd -> RProd (dl, na',Explicit,detype isgoal avoid env ty, r)
+ | BLambda -> RLambda (dl, na',Explicit,detype isgoal avoid env ty, r)
| BLetIn -> RLetIn (dl, na',detype isgoal avoid env ty, r)
let rec detype_rel_context where avoid env sign =
@@ -541,7 +541,7 @@ let rec detype_rel_context where avoid env sign =
else concrete_name None avoid env na c in
let b = Option.map (detype false avoid env) b in
let t = detype false avoid env t in
- (na',b,t) :: aux avoid' (add_name na' env) rest
+ (na',Explicit,b,t) :: aux avoid' (add_name na' env) rest
in aux avoid env (List.rev sign)
(**********************************************************************)
@@ -573,15 +573,15 @@ let rec subst_rawconstr subst raw =
if r' == r && rl' == rl then raw else
RApp(loc,r',rl')
- | RLambda (loc,n,r1,r2) ->
+ | RLambda (loc,n,bk,r1,r2) ->
let r1' = subst_rawconstr subst r1 and r2' = subst_rawconstr subst r2 in
if r1' == r1 && r2' == r2 then raw else
- RLambda (loc,n,r1',r2')
+ RLambda (loc,n,bk,r1',r2')
- | RProd (loc,n,r1,r2) ->
+ | RProd (loc,n,bk,r1,r2) ->
let r1' = subst_rawconstr subst r1 and r2' = subst_rawconstr subst r2 in
if r1' == r1 && r2' == r2 then raw else
- RProd (loc,n,r1',r2')
+ RProd (loc,n,bk,r1',r2')
| RLetIn (loc,n,r1,r2) ->
let r1' = subst_rawconstr subst r1 and r2' = subst_rawconstr subst r2 in
@@ -629,10 +629,10 @@ let rec subst_rawconstr subst raw =
let ra1' = array_smartmap (subst_rawconstr subst) ra1
and ra2' = array_smartmap (subst_rawconstr subst) ra2 in
let bl' = array_smartmap
- (list_smartmap (fun (na,obd,ty as dcl) ->
+ (list_smartmap (fun (na,k,obd,ty as dcl) ->
let ty' = subst_rawconstr subst ty in
let obd' = Option.smartmap (subst_rawconstr subst) obd in
- if ty'==ty & obd'==obd then dcl else (na,obd',ty')))
+ if ty'==ty & obd'==obd then dcl else (na,k,obd',ty')))
bl in
if ra1' == ra1 && ra2' == ra2 && bl'==bl then raw else
RRec (loc,fix,ida,bl',ra1',ra2')
diff --git a/pretyping/detyping.mli b/pretyping/detyping.mli
index 588bc8c849..72379dfcfa 100644
--- a/pretyping/detyping.mli
+++ b/pretyping/detyping.mli
@@ -41,7 +41,7 @@ val detype_case :
val detype_sort : sorts -> rawsort
val detype_rel_context : constr option -> identifier list -> names_context ->
- rel_context -> (name * rawconstr option * rawconstr) list
+ rel_context -> rawdecl list
(* look for the index of a named var or a nondep var as it is renamed *)
val lookup_name_as_renamed : env -> constr -> identifier -> int option
diff --git a/pretyping/indrec.ml b/pretyping/indrec.ml
index b894a9aae9..37d60e470c 100644
--- a/pretyping/indrec.ml
+++ b/pretyping/indrec.ml
@@ -520,11 +520,11 @@ let build_mutual_indrec env sigma = function
(List.map
(function (mind',mibi',mipi',dep',s') ->
let (sp',_) = mind' in
- if sp=sp' then
+ if sp=sp' then
let (mibi',mipi') = lookup_mind_specif env mind' in
- (mind',mibi',mipi',dep',s')
- else
- raise (RecursionSchemeError (NotMutualInScheme (mind,mind'))))
+ (mind',mibi',mipi',dep',s')
+ else
+ raise (RecursionSchemeError (NotMutualInScheme (mind,mind'))))
lrecspec)
in
let _ = check_arities listdepkind in
diff --git a/pretyping/pattern.ml b/pretyping/pattern.ml
index 63dfbb2d9f..845f9fae1f 100644
--- a/pretyping/pattern.ml
+++ b/pretyping/pattern.ml
@@ -220,10 +220,10 @@ let rec pat_of_raw metas vars = function
| RApp (_,c,cl) ->
PApp (pat_of_raw metas vars c,
Array.of_list (List.map (pat_of_raw metas vars) cl))
- | RLambda (_,na,c1,c2) ->
+ | RLambda (_,na,bk,c1,c2) ->
PLambda (na, pat_of_raw metas vars c1,
pat_of_raw metas (na::vars) c2)
- | RProd (_,na,c1,c2) ->
+ | RProd (_,na,bk,c1,c2) ->
PProd (na, pat_of_raw metas vars c1,
pat_of_raw metas (na::vars) c2)
| RLetIn (_,na,c1,c2) ->
@@ -241,7 +241,7 @@ let rec pat_of_raw metas vars = function
PIf (pat_of_raw metas vars c,
pat_of_raw metas vars b1,pat_of_raw metas vars b2)
| RLetTuple (loc,nal,(_,None),b,c) ->
- let mkRLambda c na = RLambda (loc,na,RHole (loc,Evd.InternalHole),c) in
+ let mkRLambda c na = RLambda (loc,na,Explicit,RHole (loc,Evd.InternalHole),c) in
let c = List.fold_left mkRLambda c nal in
PCase ((LetStyle,[|1|],None,None),PMeta None,pat_of_raw metas vars b,
[|pat_of_raw metas vars c|])
diff --git a/pretyping/pretyping.ml b/pretyping/pretyping.ml
index 9ecd7e2514..3689ae174a 100644
--- a/pretyping/pretyping.ml
+++ b/pretyping/pretyping.ml
@@ -321,11 +321,11 @@ module Pretyping_F (Coercion : Coercion.S) = struct
| RRec (loc,fixkind,names,bl,lar,vdef) ->
let rec type_bl env ctxt = function
[] -> ctxt
- | (na,None,ty)::bl ->
+ | (na,bk,None,ty)::bl ->
let ty' = pretype_type empty_valcon env evdref lvar ty in
let dcl = (na,None,ty'.utj_val) in
type_bl (push_rel dcl env) (add_rel_decl dcl ctxt) bl
- | (na,Some bd,ty)::bl ->
+ | (na,bk,Some bd,ty)::bl ->
let ty' = pretype_type empty_valcon env evdref lvar ty in
let bd' = pretype (mk_tycon ty'.utj_val) env evdref lvar ty in
let dcl = (na,Some bd'.uj_val,ty'.utj_val) in
@@ -420,7 +420,7 @@ module Pretyping_F (Coercion : Coercion.S) = struct
| _ -> resj in
inh_conv_coerce_to_tycon loc env evdref resj tycon
- | RLambda(loc,name,c1,c2) ->
+ | RLambda(loc,name,bk,c1,c2) ->
let (name',dom,rng) = evd_comb1 (split_tycon loc env) evdref tycon in
let dom_valcon = valcon_of_tycon dom in
let j = pretype_type dom_valcon env evdref lvar c1 in
@@ -428,7 +428,7 @@ module Pretyping_F (Coercion : Coercion.S) = struct
let j' = pretype rng (push_rel var env) evdref lvar c2 in
judge_of_abstraction env (orelse_name name name') j j'
- | RProd(loc,name,c1,c2) ->
+ | RProd(loc,name,bk,c1,c2) ->
let j = pretype_type empty_valcon env evdref lvar c1 in
let var = (name,j.utj_val) in
let env' = push_rel_assum var env in
@@ -652,7 +652,13 @@ module Pretyping_F (Coercion : Coercion.S) = struct
(pretype tycon env evdref lvar c).uj_val
| IsType ->
(pretype_type empty_valcon env evdref lvar c).utj_val in
- nf_evar (evars_of !evdref) c'
+ let evd,_ = consider_remaining_unif_problems env !evdref in
+ let evd = nf_evar_defs evd in
+ let c' = nf_evar (evars_of evd) c' in
+ let evd = Typeclasses.resolve_typeclasses env (evars_of evd) evd in
+ let c' = nf_evar (evars_of evd) c' in
+ evdref := evd;
+ c'
(* TODO: comment faire remonter l'information si le typage a resolu des
variables du sigma original. il faudrait que la fonction de typage
@@ -680,10 +686,15 @@ module Pretyping_F (Coercion : Coercion.S) = struct
let ise_pretype_gen fail_evar sigma env lvar kind c =
let evdref = ref (Evd.create_evar_defs sigma) in
let c = pretype_gen evdref env lvar kind c in
+(* let evd,_ = consider_remaining_unif_problems env !evdref in *)
+(* let evd = nf_evar_defs evd in *)
+(* let c = nf_evar (evars_of evd) c in *)
+(* let evd = undefined_evars evd in *)
+(* let evd = Typeclasses.resolve_typeclasses env sigma evd in *)
+(* let c = nf_evar (evars_of evd) c in *)
let evd,_ = consider_remaining_unif_problems env !evdref in
- let c = nf_evar (evars_of evd) c in
- if fail_evar then check_evars env sigma evd c;
- evd, c
+ if fail_evar then check_evars env (Evd.evars_of evd) evd c;
+ evd, c
(** Entry points of the high-level type synthesis algorithm *)
@@ -701,6 +712,13 @@ module Pretyping_F (Coercion : Coercion.S) = struct
let understand_tcc_evars evdref env kind c =
pretype_gen evdref env ([],[]) kind c
+(* let c = pretype_gen evdref env ([],[]) kind c in *)
+(* evdref := nf_evar_defs !evdref; *)
+(* let c = nf_evar (evars_of !evdref) c in *)
+(* let evd = undefined_evars !evdref in *)
+(* let evd = Typeclasses.resolve_typeclasses env (evars_of evd) !evdref in *)
+(* evdref := evd; *)
+(* nf_evar (evars_of evd) c *)
let understand_tcc sigma env ?expected_type:exptyp c =
let evd, t = ise_pretype_gen false sigma env ([],[]) (OfType exptyp) c in
diff --git a/pretyping/rawterm.ml b/pretyping/rawterm.ml
index d2a3473632..bf5cc22723 100644
--- a/pretyping/rawterm.ml
+++ b/pretyping/rawterm.ml
@@ -36,6 +36,8 @@ type rawsort = RProp of Term.contents | RType of Univ.universe option
type binder_kind = BProd | BLambda | BLetIn
+type binding_kind = Explicit | Implicit
+
type quantified_hypothesis = AnonHyp of int | NamedHyp of identifier
type 'a explicit_bindings = (loc * quantified_hypothesis * 'a) list
@@ -57,8 +59,8 @@ type rawconstr =
| REvar of loc * existential_key * rawconstr list option
| RPatVar of loc * (bool * patvar) (* Used for patterns only *)
| RApp of loc * rawconstr * rawconstr list
- | RLambda of loc * name * rawconstr * rawconstr
- | RProd of loc * name * rawconstr * rawconstr
+ | RLambda of loc * name * binding_kind * rawconstr * rawconstr
+ | RProd of loc * name * binding_kind * rawconstr * rawconstr
| RLetIn of loc * name * rawconstr * rawconstr
| RCases of loc * rawconstr option * tomatch_tuple * cases_clauses
| RLetTuple of loc * name list * (name * rawconstr option) *
@@ -71,7 +73,7 @@ type rawconstr =
| RCast of loc * rawconstr * rawconstr cast_type
| RDynamic of loc * Dyn.t
-and rawdecl = name * rawconstr option * rawconstr
+and rawdecl = name * binding_kind * rawconstr option * rawconstr
and fix_recursion_order = RStructRec | RWfRec of rawconstr | RMeasureRec of rawconstr
@@ -101,13 +103,13 @@ let cases_predicate_names tml =
- boolean in POldCase means it is recursive
i*)
-let map_rawdecl f (na,obd,ty) = (na,Option.map f obd,f ty)
+let map_rawdecl f (na,k,obd,ty) = (na,k,Option.map f obd,f ty)
let map_rawconstr f = function
| RVar (loc,id) -> RVar (loc,id)
| RApp (loc,g,args) -> RApp (loc,f g, List.map f args)
- | RLambda (loc,na,ty,c) -> RLambda (loc,na,f ty,f c)
- | RProd (loc,na,ty,c) -> RProd (loc,na,f ty,f c)
+ | RLambda (loc,na,bk,ty,c) -> RLambda (loc,na,bk,f ty,f c)
+ | RProd (loc,na,bk,ty,c) -> RProd (loc,na,bk,f ty,f c)
| RLetIn (loc,na,b,c) -> RLetIn (loc,na,f b,f c)
| RCases (loc,rtntypopt,tml,pl) ->
RCases (loc,Option.map f rtntypopt,
@@ -166,8 +168,8 @@ let occur_rawconstr id =
let rec occur = function
| RVar (loc,id') -> id = id'
| RApp (loc,f,args) -> (occur f) or (List.exists occur args)
- | RLambda (loc,na,ty,c) -> (occur ty) or ((na <> Name id) & (occur c))
- | RProd (loc,na,ty,c) -> (occur ty) or ((na <> Name id) & (occur c))
+ | RLambda (loc,na,bk,ty,c) -> (occur ty) or ((na <> Name id) & (occur c))
+ | RProd (loc,na,bk,ty,c) -> (occur ty) or ((na <> Name id) & (occur c))
| RLetIn (loc,na,b,c) -> (occur b) or ((na <> Name id) & (occur c))
| RCases (loc,rtntypopt,tml,pl) ->
(occur_option rtntypopt)
@@ -182,7 +184,7 @@ let occur_rawconstr id =
not (array_for_all4 (fun fid bl ty bd ->
let rec occur_fix = function
[] -> not (occur ty) && (fid=id or not(occur bd))
- | (na,bbd,bty)::bl ->
+ | (na,k,bbd,bty)::bl ->
not (occur bty) &&
(match bbd with
Some bd -> not (occur bd)
@@ -211,7 +213,7 @@ let free_rawvars =
let rec vars bounded vs = function
| RVar (loc,id') -> if Idset.mem id' bounded then vs else Idset.add id' vs
| RApp (loc,f,args) -> List.fold_left (vars bounded) vs (f::args)
- | RLambda (loc,na,ty,c) | RProd (loc,na,ty,c) | RLetIn (loc,na,ty,c) ->
+ | RLambda (loc,na,_,ty,c) | RProd (loc,na,_,ty,c) | RLetIn (loc,na,ty,c) ->
let vs' = vars bounded vs ty in
let bounded' = add_name_to_ids bounded na in
vars bounded' vs' c
@@ -234,7 +236,7 @@ let free_rawvars =
let vars_fix i vs fid =
let vs1,bounded1 =
List.fold_left
- (fun (vs,bounded) (na,bbd,bty) ->
+ (fun (vs,bounded) (na,k,bbd,bty) ->
let vs' = vars_option bounded vs bbd in
let vs'' = vars bounded vs' bty in
let bounded' = add_name_to_ids bounded na in
@@ -272,8 +274,8 @@ let loc_of_rawconstr = function
| REvar (loc,_,_) -> loc
| RPatVar (loc,_) -> loc
| RApp (loc,_,_) -> loc
- | RLambda (loc,_,_,_) -> loc
- | RProd (loc,_,_,_) -> loc
+ | RLambda (loc,_,_,_,_) -> loc
+ | RProd (loc,_,_,_,_) -> loc
| RLetIn (loc,_,_,_) -> loc
| RCases (loc,_,_,_) -> loc
| RLetTuple (loc,_,_,_,_) -> loc
diff --git a/pretyping/rawterm.mli b/pretyping/rawterm.mli
index c43c290e86..2a5dab6e40 100644
--- a/pretyping/rawterm.mli
+++ b/pretyping/rawterm.mli
@@ -40,6 +40,8 @@ type rawsort = RProp of Term.contents | RType of Univ.universe option
type binder_kind = BProd | BLambda | BLetIn
+type binding_kind = Explicit | Implicit
+
type quantified_hypothesis = AnonHyp of int | NamedHyp of identifier
type 'a explicit_bindings = (loc * quantified_hypothesis * 'a) list
@@ -61,8 +63,8 @@ type rawconstr =
| REvar of loc * existential_key * rawconstr list option
| RPatVar of loc * (bool * patvar) (* Used for patterns only *)
| RApp of loc * rawconstr * rawconstr list
- | RLambda of loc * name * rawconstr * rawconstr
- | RProd of loc * name * rawconstr * rawconstr
+ | RLambda of loc * name * binding_kind * rawconstr * rawconstr
+ | RProd of loc * name * binding_kind * rawconstr * rawconstr
| RLetIn of loc * name * rawconstr * rawconstr
| RCases of loc * rawconstr option * tomatch_tuple * cases_clauses
| RLetTuple of loc * name list * (name * rawconstr option) *
@@ -75,7 +77,7 @@ type rawconstr =
| RCast of loc * rawconstr * rawconstr cast_type
| RDynamic of loc * Dyn.t
-and rawdecl = name * rawconstr option * rawconstr
+and rawdecl = name * binding_kind * rawconstr option * rawconstr
and fix_recursion_order = RStructRec | RWfRec of rawconstr | RMeasureRec of rawconstr
diff --git a/pretyping/typeclasses.ml b/pretyping/typeclasses.ml
new file mode 100644
index 0000000000..b0e7cb1470
--- /dev/null
+++ b/pretyping/typeclasses.ml
@@ -0,0 +1,311 @@
+(************************************************************************)
+(* 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 6748 2005-02-18 22:17:50Z herbelin $ i*)
+
+(*i*)
+open Names
+open Decl_kinds
+open Term
+open Sign
+open Evd
+open Environ
+open Nametab
+open Mod_subst
+open Util
+open Typeclasses_errors
+(*i*)
+
+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 rels = constr list
+
+(* This module defines type-classes *)
+type typeclass = {
+ cl_name : identifier; (* Name of the class *)
+ cl_context : named_context; (* Context in which superclasses and params are typed (usually types) *)
+ cl_super : named_context; (* Superclasses applied to some of the params *)
+ cl_params : named_context; (* Context of the parameters (usually types) *)
+(* cl_defs : named_context; (\* Context of the definitions (usually functions), which may be shared *\) *)
+ cl_props : named_context; (* Context of the properties on defs, in Prop, will not be shared *)
+ cl_impl : inductive; (* The class implementation: a record parameterized by params and defs *)
+}
+
+type typeclasses = (identifier, typeclass) Gmap.t
+
+type instance = {
+ is_class: typeclass;
+ is_name: identifier; (* Name of the instance *)
+(* is_params: named_context; (\* Context of the parameters, instanciated *\) *)
+(* is_super: named_context; (\* The corresponding superclasses *\) *)
+(* is_defs: named_context; (\* Context of the definitions, instanciated *\) *)
+ is_impl: constant;
+(* is_add_hint : unit -> unit; (\* Hook to add an hint for the instance *\) *)
+}
+
+type instances = (identifier, instance list) Gmap.t
+
+let classes : typeclasses ref = ref Gmap.empty
+
+let methods : (identifier, identifier) Gmap.t ref = ref Gmap.empty
+
+let instances : instances ref = ref Gmap.empty
+
+let freeze () = !classes, !methods, !instances
+
+let unfreeze (cl,m,is) =
+ classes:=cl;
+ methods:=m;
+ instances:=is
+
+let init () =
+ classes:= Gmap.empty;
+ methods:= Gmap.empty;
+ instances:= Gmap.empty
+
+let _ =
+ Summary.declare_summary "classes_and_instances"
+ { Summary.freeze_function = freeze;
+ Summary.unfreeze_function = unfreeze;
+ Summary.init_function = init;
+ Summary.survive_module = true;
+ Summary.survive_section = true }
+
+let gmap_merge old ne =
+ Gmap.fold (fun k v acc -> Gmap.add k v acc) ne old
+
+let gmap_list_merge old ne =
+ let ne =
+ Gmap.fold (fun k v acc ->
+ let oldv = try Gmap.find k old with Not_found -> [] in
+ let v' =
+ List.fold_left (fun acc x ->
+ if not (List.exists (fun y -> y.is_name = x.is_name) v) then x :: acc else acc)
+ v oldv
+ in Gmap.add k v' acc)
+ ne Gmap.empty
+ in
+ Gmap.fold (fun k v acc ->
+ let newv = try Gmap.find k ne with Not_found -> [] in
+ let v' =
+ List.fold_left (fun acc x ->
+ if not (List.exists (fun y -> y.is_name = x.is_name) acc) then x :: acc else acc)
+ newv v
+ in Gmap.add k v' acc)
+ old ne
+
+let cache (_, (cl, m, inst)) =
+ classes := gmap_merge !classes cl;
+ methods := gmap_merge !methods m;
+ instances := gmap_list_merge !instances inst
+
+open Libobject
+
+let subst (_,subst,(cl,m,inst)) =
+ let do_subst_con c = fst (Mod_subst.subst_con subst c)
+ and do_subst c = Mod_subst.subst_mps subst c
+ and do_subst_ind (kn,i) = (Mod_subst.subst_kn subst kn,i)
+ in
+ let do_subst_named ctx =
+ List.map (fun (na, b, t) ->
+ (na, Option.smartmap do_subst b, do_subst t))
+ ctx
+ in
+ let subst_class cl =
+ let cl' = { cl with cl_impl = do_subst_ind cl.cl_impl;
+ cl_context = do_subst_named cl.cl_context;
+ cl_super = do_subst_named cl.cl_super;
+ cl_params = do_subst_named cl.cl_params;
+ cl_props = do_subst_named cl.cl_props; }
+ in if cl' = cl then cl else cl'
+ in
+ let subst_inst classes insts =
+ List.map (fun is ->
+ { is with is_class = Gmap.find is.is_class.cl_name classes;
+ is_impl = do_subst_con is.is_impl }) insts
+ in
+ let classes = Gmap.map subst_class cl in
+ let instances = Gmap.map (subst_inst classes) inst in
+ (classes, m, instances)
+
+let discharge (_,(cl,m,inst)) =
+ let subst_class cl =
+ { cl with cl_impl = Lib.discharge_inductive cl.cl_impl }
+ in
+ let subst_inst classes insts =
+ List.map (fun is -> { is with is_impl = Lib.discharge_con is.is_impl;
+ is_class = Gmap.find is.is_class.cl_name classes; }) insts
+ in
+ let classes = Gmap.map subst_class cl in
+ let instances = Gmap.map (subst_inst classes) inst in
+ Some (classes, m, instances)
+
+let (input,output) =
+ declare_object
+ { (default_object "type classes state") with
+ cache_function = cache;
+ load_function = (fun _ -> cache);
+ open_function = (fun _ -> cache);
+ classify_function = (fun (_,x) -> Substitute x);
+ discharge_function = discharge;
+ subst_function = subst;
+ export_function = (fun x -> Some x) }
+
+let update () =
+ Lib.add_anonymous_leaf (input (!classes, !methods, !instances))
+
+let class_methods cl =
+ List.map (function (x, _, _) -> x) cl.cl_props
+
+let add_class c =
+ classes := Gmap.add c.cl_name c !classes;
+ methods := List.fold_left (fun acc x -> Gmap.add x c.cl_name acc) !methods (class_methods c);
+ update ()
+
+let class_info c =
+ Gmap.find c !classes
+
+let class_of_inductive ind =
+ let res = Gmap.fold
+ (fun k v acc -> match acc with None -> if v.cl_impl = ind then Some v else acc | _ -> acc)
+ !classes None
+ in match res with
+ None -> raise Not_found
+ | Some cl -> cl
+
+let typeclasses () = Gmap.fold (fun _ l c -> l :: c) !classes []
+
+let gmapl_add x y m =
+ try
+ let l = Gmap.find x m in
+ Gmap.add x (y::Util.list_except y l) m
+ with Not_found ->
+ Gmap.add x [y] m
+
+let instances_of c =
+ try Gmap.find c.cl_name !instances with Not_found -> []
+
+let add_instance i =
+ instances := gmapl_add i.is_class.cl_name i !instances;
+ update ()
+
+open Libnames
+
+let id_of_reference r =
+ let (_, id) = repr_qualid (snd (qualid_of_reference r)) in id
+
+let instances r =
+ let id = id_of_reference r in
+ try let cl = class_info id in instances_of cl
+ with Not_found -> unbound_class (Global.env()) (loc_of_reference r, id)
+
+let solve_instanciation_problem = ref (fun _ _ _ _ -> assert false)
+
+let resolve_typeclass env ev evi (evd, defined as acc) =
+ if evi.evar_body = Evar_empty then
+ try
+ !solve_instanciation_problem env evd ev evi
+ with Exit -> acc
+ else acc
+
+let resolve_one_typeclass env types =
+ try
+ let evi = Evd.make_evar (Environ.named_context_val env) types in
+ let ev = 1 in
+ let evm = Evd.add Evd.empty ev evi in
+ let evd = Evd.create_evar_defs evm in
+ let evd', b = !solve_instanciation_problem env evd ev evi in
+ if b then
+ let evm' = Evd.evars_of evd' in
+ match Evd.evar_body (Evd.find evm' ev) with
+ Evar_empty -> raise Not_found
+ | Evar_defined c -> c
+ else raise Not_found
+ with Exit -> raise Not_found
+
+let resolve_one_typeclass_evd env evd types =
+ try
+ let ev = Evarutil.e_new_evar evd env types in
+ let (ev,_) = destEvar ev in
+ let evd', b =
+ !solve_instanciation_problem env !evd ev (Evd.find (Evd.evars_of !evd) ev)
+ in
+ evd := evd';
+ if b then
+ let evm' = Evd.evars_of evd' in
+ match Evd.evar_body (Evd.find evm' ev) with
+ Evar_empty -> raise Not_found
+ | Evar_defined c -> c
+ else raise Not_found
+ with Exit -> raise Not_found
+
+let method_typeclass ref =
+ match ref with
+ | ConstRef c ->
+ let (_, _, l) = Names.repr_con c in
+ class_info (Gmap.find (Names.id_of_label l) !methods)
+ | _ -> raise Not_found
+
+let is_class ind =
+ Gmap.fold (fun k v acc -> acc || v.cl_impl = ind) !classes false
+
+let is_implicit_arg k =
+ match k with
+ ImplicitArg (ref, (n, id)) -> true
+ | InternalHole -> true
+ | _ -> false
+
+let resolve_typeclasses ?(check=true) env sigma evd =
+ let evm = Evd.evars_of evd in
+ let tc_evars =
+ let f ev evi acc =
+ let (l, k) = Evd.evar_source ev evd in
+ if not check || is_implicit_arg k then
+ match kind_of_term evi.evar_concl with
+ | App(ki, args) when isInd ki ->
+ if is_class (destInd ki) then Evd.add acc ev evi
+ else acc
+ | _ -> acc
+ else acc
+ in Evd.fold f evm Evd.empty
+ in
+ let rec sat evars =
+ let (evars', progress) =
+ Evd.fold
+ (fun ev evi acc ->
+ if Evd.mem tc_evars ev then resolve_typeclass env ev evi acc else acc)
+ (Evd.evars_of evars) (evars, false)
+ in
+ if not progress then evars'
+ else
+ sat (Evarutil.nf_evar_defs evars')
+ in sat evd
+
+let class_of_constr c =
+ match kind_of_term c with
+ App (c, _) ->
+ (match kind_of_term c with
+ Ind ind -> (try Some (class_of_inductive ind) with Not_found -> None)
+ | _ -> None)
+ | _ -> None
+
+
+type substitution = (identifier * constr) list
+
+let substitution_of_named_context isevars env id n subst l =
+ List.fold_right
+ (fun (na, _, t) subst ->
+ let t' = replace_vars subst t in
+ let b = Evarutil.e_new_evar isevars env ~src:(dummy_loc, ImplicitArg (VarRef id, (n, Some na))) t' in
+ (na, b) :: subst)
+ l subst
+
+let nf_substitution sigma subst =
+ List.map (function (na, c) -> na, Reductionops.nf_evar sigma c) subst
diff --git a/pretyping/typeclasses.mli b/pretyping/typeclasses.mli
new file mode 100644
index 0000000000..fbe48e06a2
--- /dev/null
+++ b/pretyping/typeclasses.mli
@@ -0,0 +1,70 @@
+(************************************************************************)
+(* 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.mli 6748 2005-02-18 22:17:50Z herbelin $ i*)
+
+(*i*)
+open Names
+open Decl_kinds
+open Term
+open Sign
+open Evd
+open Environ
+open Nametab
+open Mod_subst
+open Topconstr
+open Util
+(*i*)
+
+(* This module defines type-classes *)
+type typeclass = {
+ cl_name : identifier; (* Name of the class *)
+ cl_context : named_context; (* Context in which superclasses and params are typed (usually types) *)
+ cl_super : named_context; (* Superclasses applied to some of the params *)
+ cl_params : named_context; (* Context of the real parameters (types and operations) *)
+(* cl_defs : rel_context; (\* Context of the definitions (usually functions), which may be shared *\) *)
+ cl_props : named_context; (* Context of the properties on defs, in Prop, will not be shared *)
+ cl_impl : inductive; (* The class implementation: a record parameterized by params and defs *)
+}
+
+type instance = {
+ is_class: typeclass;
+ is_name: identifier; (* Name of the instance *)
+(* is_params: named_context; (\* Context of the parameters, instanciated *\) *)
+(* is_super: named_context; (\* The corresponding superclasses *\) *)
+ is_impl: constant;
+(* is_add_hint : unit -> unit; (\* Hook to add an hint for the instance *\) *)
+}
+
+val instances : Libnames.reference -> instance list
+val typeclasses : unit -> typeclass list
+val add_class : typeclass -> unit
+val add_instance : instance -> unit
+
+val class_info : identifier -> typeclass (* raises Not_found *)
+val class_of_inductive : inductive -> typeclass (* raises Not_found *)
+
+val resolve_one_typeclass : env -> types -> types (* Raises Not_found *)
+val resolve_one_typeclass_evd : env -> evar_defs ref -> types -> types (* Raises Not_found *)
+
+val is_class : inductive -> bool
+
+val class_of_constr : constr -> typeclass option
+
+val resolve_typeclass : env -> evar -> evar_info -> evar_defs * bool -> evar_defs * bool
+val resolve_typeclasses : ?check:bool -> env -> evar_map -> evar_defs -> evar_defs
+
+val solve_instanciation_problem : (env -> evar_defs -> existential_key -> evar_info -> evar_defs * bool) ref
+
+type substitution = (identifier * constr) list
+
+val substitution_of_named_context :
+ evar_defs ref -> env -> identifier -> int ->
+ substitution -> named_context -> substitution
+
+val nf_substitution : evar_map -> substitution -> substitution
diff --git a/pretyping/typeclasses_errors.ml b/pretyping/typeclasses_errors.ml
new file mode 100644
index 0000000000..980f327cb5
--- /dev/null
+++ b/pretyping/typeclasses_errors.ml
@@ -0,0 +1,42 @@
+(************************************************************************)
+(* 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 6748 2005-02-18 22:17:50Z herbelin $ i*)
+
+(*i*)
+open Names
+open Decl_kinds
+open Term
+open Sign
+open Evd
+open Environ
+open Nametab
+open Mod_subst
+open Topconstr
+open Util
+(*i*)
+
+type contexts = Parameters | Properties
+
+type typeclass_error =
+ | UnboundClass of identifier located
+ | UnboundMethod of identifier * identifier located (* Class name, method *)
+ | NoInstance of identifier located * constr list
+ | MismatchedContextInstance of contexts * constr_expr list * named_context (* found, expected *)
+
+exception TypeClassError of env * typeclass_error
+
+let typeclass_error env err = raise (TypeClassError (env, err))
+
+let unbound_class env id = typeclass_error env (UnboundClass id)
+
+let unbound_method env cid id = typeclass_error env (UnboundMethod (cid, id))
+
+let no_instance env id args = typeclass_error env (NoInstance (id, args))
+
+let mismatched_ctx_inst env c n m = typeclass_error env (MismatchedContextInstance (c, n, m))
diff --git a/pretyping/typeclasses_errors.mli b/pretyping/typeclasses_errors.mli
new file mode 100644
index 0000000000..fbc2f25449
--- /dev/null
+++ b/pretyping/typeclasses_errors.mli
@@ -0,0 +1,40 @@
+(************************************************************************)
+(* 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.mli 6748 2005-02-18 22:17:50Z herbelin $ i*)
+
+(*i*)
+open Names
+open Decl_kinds
+open Term
+open Sign
+open Evd
+open Environ
+open Nametab
+open Mod_subst
+open Topconstr
+open Util
+(*i*)
+
+type contexts = Parameters | Properties
+
+type typeclass_error =
+ | UnboundClass of identifier located
+ | UnboundMethod of identifier * identifier located (* Class name, method *)
+ | NoInstance of identifier located * constr list
+ | MismatchedContextInstance of contexts * constr_expr list * named_context (* found, expected *)
+
+exception TypeClassError of env * typeclass_error
+
+val unbound_class : env -> identifier located -> 'a
+
+val unbound_method : env -> identifier -> identifier located -> 'a
+
+val no_instance : env -> identifier located -> constr list -> 'a
+
+val mismatched_ctx_inst : env -> contexts -> constr_expr list -> named_context -> 'a