aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar herbelin <herbelin@85f007b7-540e-0410-9357-904b9bb8a0f7>2001-11-09 17:46:17 +0000
committerGravatar herbelin <herbelin@85f007b7-540e-0410-9357-904b9bb8a0f7>2001-11-09 17:46:17 +0000
commit3cd1a988f93566579740294c7fafbfc81b174675 (patch)
tree1f1a4e6865a1c271c668aaab2c04768be34d2519
parent03941e1ee40758d3e206d3e4463696bf22005d8c (diff)
Nettoyage coercions et classes
git-svn-id: svn+ssh://scm.gforge.inria.fr/svn/coq/trunk@2179 85f007b7-540e-0410-9357-904b9bb8a0f7
-rwxr-xr-xpretyping/classops.ml57
-rw-r--r--pretyping/classops.mli6
-rw-r--r--toplevel/class.ml203
3 files changed, 139 insertions, 127 deletions
diff --git a/pretyping/classops.ml b/pretyping/classops.ml
index 9df00372c..4628f66e1 100755
--- a/pretyping/classops.ml
+++ b/pretyping/classops.ml
@@ -23,6 +23,9 @@ open Rawterm
(* usage qque peu general: utilise aussi dans record *)
+(* A class is a type constructor, its type is an arity whose number of
+ arguments is cl_param (0 for CL_SORT and CL_FUN) *)
+
type cl_typ =
| CL_SORT
| CL_FUN
@@ -32,7 +35,8 @@ type cl_typ =
type cl_info_typ = {
cl_strength : strength;
- cl_param : int }
+ cl_param : int
+}
type coe_typ = global_reference
@@ -187,37 +191,33 @@ let _ =
(* classe d'un terme *)
-(* constructor_at_head : constr -> cl_typ * int *)
-
-let constructor_at_head t =
- let rec aux t' = match kind_of_term t' with
- | Var id -> CL_SECVAR id,0
- | Const sp -> CL_CONST sp,0
- | Ind ind_sp -> CL_IND ind_sp,0
- | Prod (_,_,c) -> CL_FUN,0
- | LetIn (_,_,_,c) -> aux c
- | Sort _ -> CL_SORT,0
- | Cast (c,_) -> aux (collapse_appl c)
- | App (f,args) -> let c,_ = aux f in c, Array.length args
+(* find_class_type : constr -> cl_typ * int *)
+
+let find_class_type t =
+ let t', args = decompose_app (Reductionops.whd_betaiotazeta t) in
+ match kind_of_term t' with
+ | Var id -> CL_SECVAR id, args
+ | Const sp -> CL_CONST sp, args
+ | Ind ind_sp -> CL_IND ind_sp, args
+ | Prod (_,_,_) -> CL_FUN, []
+ | Sort _ -> CL_SORT, []
| _ -> raise Not_found
- in
- aux (collapse_appl t)
(* class_of : Term.constr -> int *)
let class_of env sigma t =
- let t,n,n1,i =
- (try
- let (cl,n) = constructor_at_head t in
- let (i,{cl_param=n1}) = class_info cl in
- t,n,n1,i
- with _ ->
- let t = Tacred.hnf_constr env sigma t in
- let (cl,n) = constructor_at_head t in
- let (i,{cl_param=n1}) = class_info cl in
- t,n,n1,i)
+ let (t, n1, i, args) =
+ try
+ let (cl,args) = find_class_type t in
+ let (i, { cl_param = n1 } ) = class_info cl in
+ (t, n1, i, args)
+ with Not_found ->
+ let t = Tacred.hnf_constr env sigma t in
+ let (cl, args) = find_class_type t in
+ let (i, { cl_param = n1 } ) = class_info cl in
+ (t, n1, i, args)
in
- if n = n1 then t,i else raise Not_found
+ if List.length args = n1 then t, i else raise Not_found
let class_args_of c = snd (decompose_app c)
@@ -256,6 +256,9 @@ let message_ambig l =
(* add_coercion_in_graph : coe_index * cl_index * cl_index -> unit
coercion,source,target *)
+let different_class_params i j =
+ (snd (class_info_from_index i)).cl_param > 0
+
let add_coercion_in_graph (ic,source,target) =
let old_inheritance_graph = !inheritance_graph in
let ambig_paths =
@@ -263,7 +266,7 @@ let add_coercion_in_graph (ic,source,target) =
let try_add_new_path (p,i,j) =
try
if i=j then begin
- if (snd (class_info_from_index i)).cl_param > 0 then begin
+ if different_class_params i j then begin
let _ = lookup_path_between (i,j) in
ambig_paths := ((i,j),p)::!ambig_paths
end
diff --git a/pretyping/classops.mli b/pretyping/classops.mli
index b8817ae0e..9f8d0cf85 100644
--- a/pretyping/classops.mli
+++ b/pretyping/classops.mli
@@ -55,9 +55,9 @@ val class_info : cl_typ -> (cl_index * cl_info_typ)
val class_exists : cl_typ -> bool
val class_info_from_index : cl_index -> cl_typ * cl_info_typ
-(* [constructor_at_head c] returns the head reference of c and its
- number of arguments *)
-val constructor_at_head : constr -> cl_typ * int
+(* [find_class_type c] returns the head reference of c and its
+ arguments *)
+val find_class_type : constr -> cl_typ * constr list
(* raises [Not_found] if not convertible to a class *)
val class_of : env -> evar_map -> constr -> constr * cl_index
diff --git a/toplevel/class.ml b/toplevel/class.ml
index d2524b067..a3a7ffdf0 100644
--- a/toplevel/class.ml
+++ b/toplevel/class.ml
@@ -74,8 +74,11 @@ let stre_of_global = function
| VarRef id -> variable_strength id
| IndRef _ | ConstructRef _ -> NeverDischarge
-(* verfications pour l'ajout d'une classe *)
+(* Errors *)
+(******
+<<<<<<< class.ml
+=======
let rec arity_sort a = match kind_of_term a with
| Sort (Prop _ | Type _) -> 0
| Prod (_,_,c) -> (arity_sort c) +1
@@ -111,98 +114,94 @@ let try_add_new_class ref stre =
[< 'sTR "Type of "; Printer.pr_global ref;
'sTR " does not end with a sort" >]
in
- let cl = fst (constructor_at_head v) in
+ let cl = fst (find_class_type v) in
let _ = try_add_class (cl,p1) (Some stre) true in ()
(* Coercions *)
+******)
type coercion_error_kind =
| AlreadyExists
- | NotACoercion
- | NoSource of string
+ | NotAFunction
+ | NoSource
+ | NoSourceFunClass
+ | NoSourceSortClass
| NotUniform
| NoTarget
| WrongTarget of cl_typ * cl_typ
- | NotAClass of cl_typ
+ | NotAClass of global_reference
| NotEnoughClassArgs of cl_typ
exception CoercionError of coercion_error_kind
let explain_coercion_error g = function
| AlreadyExists ->
- errorlabstrm "try_add_coercion"
- [< Printer.pr_global g; 'sTR" is already a coercion" >]
- | NotACoercion ->
- errorlabstrm "try_add_coercion"
- [< Printer.pr_global g; 'sTR" does not correspond to a coercion" >]
- | NoSource s ->
- errorlabstrm "try_add_coercion"
- [< Printer.pr_global g; 'sTR ": "; 'sTR s >]
+ [< Printer.pr_global g; 'sTR" is already a coercion" >]
+ | NotAFunction ->
+ [< Printer.pr_global g; 'sTR" is not a function" >]
+ | NoSource ->
+ [< Printer.pr_global g; 'sTR ": cannot find the source class" >]
+ | NoSourceFunClass ->
+ [< Printer.pr_global g; 'sTR ": FUNCLASS cannot be a source class" >]
+ | NoSourceSortClass ->
+ [< Printer.pr_global g; 'sTR ": SORTCLASS cannot be a source class" >]
| NotUniform ->
- errorlabstrm "try_add_coercion"
[< Printer.pr_global g;
'sTR" does not respect the inheritance uniform condition" >];
| NoTarget ->
- errorlabstrm "try_add_coercion"
- [<'sTR"We cannot find the target class" >]
+ [<'sTR"Cannot find the target class" >]
| WrongTarget (clt,cl) ->
- errorlabstrm "try_add_coercion"
- [<'sTR"Found target class "; 'sTR(string_of_class cl);
- 'sTR " while "; 'sTR(string_of_class clt);
- 'sTR " is expected" >]
- | NotAClass cl ->
- errorlabstrm "check_class"
- [< 'sTR "Type of "; 'sTR (string_of_class cl);
- 'sTR " does not end with a sort" >]
+ [<'sTR"Found target class "; 'sTR(string_of_class cl);
+ 'sTR " while "; 'sTR(string_of_class clt);
+ 'sTR " is expected" >]
+ | NotAClass ref ->
+ [< 'sTR "Type of "; Printer.pr_global ref;
+ 'sTR " does not end with a sort" >]
| NotEnoughClassArgs cl ->
- errorlabstrm "fully_applied"
- [< 'sTR"Wrong number of parameters for ";'sTR(string_of_class cl) >]
-
-let check_fully_applied cl p p1 =
- if p <> p1 then raise (CoercionError (NotEnoughClassArgs cl))
-
-(* check_class : Names.identifier ->
- Term.constr -> cl_typ -> int -> int * Libobject.strength *)
-
-let check_class v cl p =
- try
- let _,clinfo = class_info cl in
- check_fully_applied cl p clinfo.cl_param
- with Not_found ->
- let env = Global.env () in
- let t = Retyping.get_type_of env Evd.empty v in
- let p1 =
- try
- arity_sort t
- with Not_found -> raise (CoercionError (NotAClass cl))
+ [< 'sTR"Wrong number of parameters for ";'sTR(string_of_class cl) >]
+
+(* Verifications pour l'ajout d'une classe *)
+
+let rec arity_sort a = match kind_of_term a with
+ | Sort (Prop _ | Type _) -> 0
+ | Prod (_,_,c) -> (arity_sort c) +1
+ | LetIn (_,_,_,c) -> arity_sort c (* Utile ?? *)
+ | Cast (c,_) -> arity_sort c
+ | _ -> raise Not_found
+
+let check_reference_arity ref =
+ try arity_sort (Global.type_of_global ref)
+ with Not_found -> raise (CoercionError (NotAClass ref))
+
+let check_arity = function
+ | CL_FUN | CL_SORT -> 0
+ | CL_CONST sp -> check_reference_arity (ConstRef sp)
+ | CL_SECVAR sp -> check_reference_arity (VarRef sp)
+ | CL_IND sp -> check_reference_arity (IndRef sp)
+
+(* try_add_class : cl_typ -> strength option -> bool -> unit *)
+
+let try_add_class cl streopt fail_if_exists =
+ if not (class_exists cl) then
+ let p = check_arity cl in
+ let stre' = strength_of_cl cl in
+ let stre = match streopt with
+ | Some stre -> stre_max (stre,stre')
+ | None -> stre'
in
- check_fully_applied cl p p1;
- try_add_class (cl,p1) None false
+ declare_class (cl,stre,p)
+ else
+ if fail_if_exists then errorlabstrm "try_add_new_class"
+ [< 'sTR (string_of_class cl) ; 'sTR " is already a class" >]
+
+
+(* Coercions *)
(* check that the computed target is the provided one *)
let check_target clt = function
| Some cl when cl <> clt -> raise (CoercionError (WrongTarget(clt,cl)))
| _ -> ()
-(* decomposition de constr vers coe_typ *)
-
-let constructor_at_head1 t =
- let rec aux t' =
- match kind_of_term t' with
- | Const sp -> t',[],CL_CONST sp,0
- | Ind ind_sp -> t',[],CL_IND ind_sp,0
- | Var id -> t',[],CL_SECVAR id,0
- | Cast (c,_) -> aux c
- | App(f,args) ->
- let t',_,l,_ = aux f in t',Array.to_list args,l,Array.length args
- | Prod (_,_,_) -> t',[],CL_FUN,0
- | LetIn (_,_,_,c) -> aux c
- | Sort _ -> t',[],CL_SORT,0
- | _ -> raise Not_found
- in
- aux (collapse_appl t)
-
-
(* condition d'heritage uniforme *)
let uniform_cond nargs lt =
@@ -236,46 +235,44 @@ lp est la liste (inverse'e) des arguments de la coercion
ids est le nom de la classe source
sps_opt est le sp de la classe source dans le cas des structures
retourne:
-la classe souce
+la classe source
nbre d'arguments de la classe
le constr de la class
-l'indice de la classe source dans la liste lp
la liste des variables dont depend la classe source
+l'indice de la classe source dans la liste lp
*)
let get_source lp source =
match source with
| None ->
- let (v1,lv1,cl1,p1) =
- match lp with
+ let (cl1,lv1) =
+ match lp with
| [] -> raise Not_found
- | t1::_ ->
- try constructor_at_head1 t1
- with _ -> raise Not_found
+ | t1::_ -> find_class_type t1
in
- (cl1,p1,v1,lv1,1)
+ (cl1,lv1,1)
| Some cl ->
let rec aux n = function
| [] -> raise Not_found
| t1::lt ->
try
- let v1,lv1,cl1,p1 = constructor_at_head1 t1 in
- if cl1 = cl then cl1,p1,v1,lv1,n
- else aux (n+1) lt
- with _ -> aux (n + 1) lt
+ let cl1,lv1 = find_class_type t1 in
+ if cl = cl1 then cl1,lv1,n
+ else raise Not_found
+ with Not_found -> aux (n+1) lt
in aux 1 lp
let get_target t ind =
if (ind > 1) then
- CL_FUN,0,t
+ CL_FUN
else
- let v2,_,cl2,p2 = constructor_at_head1 t in cl2,p2,v2
+ fst (find_class_type t)
let prods_of t =
let rec aux acc d = match kind_of_term d with
| Prod (_,c1,c2) -> aux (c1::acc) c2
| Cast (c,_) -> aux acc c
- | _ -> d::acc
+ | _ -> (d,acc)
in
aux [] t
@@ -331,7 +328,7 @@ let build_id_coercion idf_opt source =
| Some idf -> idf
| None ->
id_of_string ("Id_"^(string_of_class source)^"_"^
- (string_of_class (fst (constructor_at_head t))))
+ (string_of_class (fst (find_class_type t))))
in
let constr_entry = (* Cast is necessary to express [val_f] is identity *)
ConstantEntry
@@ -357,36 +354,35 @@ let add_new_coercion_core coef stre source target isid =
let v = constr_of_reference coef in
let vj = Retyping.get_judgment_of env Evd.empty v in
if coercion_exists coef then raise (CoercionError AlreadyExists);
- let lp = prods_of (vj.uj_type) in
+ let tg,lp = prods_of (vj.uj_type) in
let llp = List.length lp in
- if llp <= 1 then raise (CoercionError NotACoercion);
- let (cls,ps,vs,lvs,ind) =
+ if llp = 0 then raise (CoercionError NotAFunction);
+ let (cls,lvs,ind) =
try
- get_source (List.tl lp) source
+ get_source lp source
with Not_found ->
- raise (CoercionError (NoSource "Cannot find the source class "))
+ raise (CoercionError NoSource)
in
- if (cls = CL_FUN) then
- raise (CoercionError (NoSource "FUNCLASS cannot be a source class"));
- if (cls = CL_SORT) then
- raise (CoercionError (NoSource "SORTCLASS cannot be a source class"));
- if not (uniform_cond (llp-1-ind) lvs) then
+ if (cls = CL_FUN) then raise (CoercionError NoSourceFunClass);
+ if (cls = CL_SORT) then raise (CoercionError NoSourceSortClass);
+ if not (uniform_cond (llp-ind) lvs) then
raise (CoercionError NotUniform);
- let clt,pt,vt =
+ let clt =
try
- get_target (List.hd lp) ind
+ get_target tg ind
with Not_found ->
raise (CoercionError NoTarget)
in
check_target clt target;
- check_class vs cls ps;
- check_class vt clt pt;
+ try_add_class cls None false;
+ try_add_class clt None false;
let stre' = get_strength stre coef cls clt in
- declare_coercion coef vj stre' isid cls clt ps
+ declare_coercion coef vj stre' isid cls clt (List.length lvs)
let try_add_new_coercion_core ref b c d e =
try add_new_coercion_core ref b c d e
- with CoercionError e -> explain_coercion_error ref e
+ with CoercionError e ->
+ errorlabstrm "try_add_new_coercion_core" (explain_coercion_error ref e)
let try_add_new_coercion ref stre =
try_add_new_coercion_core ref stre None None false
@@ -405,6 +401,19 @@ let try_add_new_identity_coercion id stre source target =
let try_add_new_coercion_with_source ref stre source =
try_add_new_coercion_core ref stre (Some source) None false
+(* try_add_new_class : global_reference -> strength -> unit *)
+
+let class_of_global = function
+ | VarRef sp -> CL_SECVAR sp
+ | ConstRef sp -> CL_CONST sp
+ | IndRef sp -> CL_IND sp
+ | ConstructRef _ as ref -> raise (CoercionError (NotAClass ref))
+
+let try_add_new_class ref stre =
+ try try_add_class (class_of_global ref) (Some stre) true
+ with CoercionError e ->
+ errorlabstrm "try_add_new_class" (explain_coercion_error ref e)
+
(* fonctions pour le discharge: encore un peu sale mais ça s'améliore *)
type coercion_entry =