aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--toplevel/class.ml471
-rw-r--r--toplevel/class.mli25
-rw-r--r--toplevel/record.ml170
-rw-r--r--toplevel/record.mli12
4 files changed, 678 insertions, 0 deletions
diff --git a/toplevel/class.ml b/toplevel/class.ml
new file mode 100644
index 000000000..5c762636f
--- /dev/null
+++ b/toplevel/class.ml
@@ -0,0 +1,471 @@
+
+open Util
+open Pp
+open Names
+open Generic
+open Term
+open Inductive
+open Constant
+open Environ
+open Lib
+open Classops
+open Declare
+
+(* manipulations concernant les strength *)
+
+(* gt dans le sens de "longueur du sp" (donc le moins persistant) *)
+
+(* strength * strength -> bool *)
+
+let stre_gt = function
+ (NeverDischarge,NeverDischarge) -> false
+ | (NeverDischarge,x) -> false
+ | (x,NeverDischarge) -> true
+ | (DischargeAt sp1,DischargeAt sp2) -> sp_gt (sp1,sp2)
+
+let stre_max (stre1,stre2) =
+ if stre_gt (stre1,stre2) then stre1 else stre2
+
+let stre_max4 stre1 stre2 stre3 stre4 =
+ stre_max ((stre_max (stre1,stre2)),(stre_max (stre3,stre4)))
+
+let id_of_varid = function
+ | (VAR id) -> id
+ | _ -> anomaly "class__id_of_varid"
+
+let stre_of_VAR c = variable_strength (destVar c)
+
+(* lf liste des variable dont depend la coercion f
+ lc liste des variable dont depend la classe source *)
+
+let rec stre_unif_cond = function
+ ([],[]) -> NeverDischarge
+ | (v::l,[]) -> stre_of_VAR v
+ | ([],v::l) -> stre_of_VAR v
+ | (v1::l1,v2::l2) ->
+ if v1=v2 then stre_unif_cond (l1,l2)
+ else
+ let stre1 = (stre_of_VAR v1)
+ and stre2 = (stre_of_VAR v2)
+ in stre_max (stre1,stre2)
+
+let stre_of_coe = function
+ NAM_SP sp ->
+ (match global_operator sp (basename sp) with
+ Const sp, _ -> constant_strength sp
+ | _ -> NeverDischarge)
+ | NAM_Var id -> variable_strength id
+ | _ -> NeverDischarge
+
+(* try_add_class : Names.identifier ->
+ Term.constr -> (cl_typ * int) option -> bool -> int * Libobject.strength *)
+
+let try_add_class id v clpopt streopt check_exist =
+ 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 -> errorlabstrm "try_add_class"
+ [< 'sTR "Type of "; 'sTR (string_of_id id);
+ 'sTR " does not end with a sort" >] in
+ let cl,p =
+ match clpopt with
+ None -> let (cl,_)=constructor_at_head v in (cl,p1)
+ | Some (cl,p2) -> (fully_applied id p2 p1;cl,p1) in
+ if check_exist & class_exists cl then
+ errorlabstrm "try_add_new_class"
+ [< 'sTR (string_of_id id) ; 'sTR " is already a class" >];
+ let stre' = stre_of_cl cl in
+ let stre = (match streopt with
+ (Some stre) -> stre_max (stre,stre')
+ | None -> stre') in
+ add_new_class (cl,(string_of_id id),stre,p);
+ stre
+
+
+(* try_add_new_class : Names.identifier -> unit *)
+
+let try_add_new_class id stre =
+ let v = global_reference CCI id in
+ let _ = try_add_class id v None (Some stre) true in ()
+
+
+(* check_class : Names.identifier ->
+ Term.constr -> cl_typ -> int -> int * Libobject.strength *)
+
+let check_class id v cl p =
+ try
+ let _,clinfo = class_info cl in
+ if p = clinfo.cL_PARAM
+ then clinfo.cL_STRE
+ else errorlabstrm "fully_applied"
+ [< 'sTR"Wrong number of parameters for ";'sTR(string_of_id id) >]
+ with Not_found -> try_add_class id v (Some (cl,p)) None false
+
+
+(* decomposition de constr vers coe_typ *)
+
+let coe_constructor_at_head t =
+ let rec aux t' =
+ match kind_of_term t' with
+ IsConst (sp,l) -> (Array.to_list l),NAM_SP sp
+ | IsMutInd (sp,_,l) -> (Array.to_list l),NAM_SP sp
+ | IsVar id -> [],NAM_Var id
+ | IsCast (c,_) -> aux c
+ | IsMutConstruct (sp,i,j,l) -> (Array.to_list l),NAM_Construct ((sp,i),j)
+ | IsAppL(f,args) -> aux f
+ | _ -> raise Not_found
+ in aux (collapse_appl t)
+
+let constructor_at_head1 t =
+ let rec aux t' =
+ match kind_of_term t' with
+ IsConst (sp,l) -> t',[],(Array.to_list l),CL_SP sp,0
+ | IsMutInd (sp,i,l) -> t',[],(Array.to_list l),CL_IND (sp,i),0
+ | IsVar id -> t',[],[],CL_Var id,0
+ | IsCast (c,_) -> aux c
+ | IsAppL(f,args) -> let t',_,l,c,_ = aux f in t',args,l,c,List.length args
+ | IsProd (_,_,_) -> t',[],[],CL_FUN,0
+ | IsSort _ -> t',[],[],CL_SORT,0
+ | _ -> raise Not_found
+ in aux (collapse_appl t)
+
+
+(* condition d'heritage uniforme *)
+
+let uniform_cond nargs lt =
+ let rec aux = function
+ (0,[]) -> true
+ | (n,t::l) -> (strip_outer_cast t = Rel n) & (aux ((n-1),l))
+ | _ -> false
+ in aux (nargs,lt)
+
+let id_of_cl = function
+ CL_FUN -> (id_of_string "FUNCLASS")
+ | CL_SORT -> (id_of_string "SORTCLASS")
+ | CL_SP sp -> (basename sp)
+ | CL_IND (sp,i) ->
+ (mind_nth_type_packet (Global.lookup_mind sp) i).mind_typename
+ | CL_Var id -> id
+
+let string_of_cl = function
+ CL_FUN -> "FUNCLASS"
+ | CL_SORT -> "SORTCLASS"
+ | CL_SP sp -> string_of_id (basename sp)
+ | CL_IND (sp,i) ->
+ string_of_id
+ (mind_nth_type_packet (Global.lookup_mind sp) i).mind_typename
+ | CL_Var id -> string_of_id id
+
+(*
+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
+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
+*)
+
+type choice = Ident of identifier | Section_path of section_path
+
+let get_source lp source =
+ let aux test =
+ let rec aux1 n = function
+ [] -> raise Not_found
+ | t1::lt ->
+ try (let v1,lv1,l,cl1,p1 = constructor_at_head1 t1 in
+ if test cl1
+ then cl1,p1,v1,lv1,n,l
+ else aux1 (n+1) lt)
+ with _ -> aux1 (n + 1) lt
+ in aux1 1 lp
+ in match source with
+ None ->
+ let (v1,lv1,l,cl1,p1) as x =
+ (match lp with
+ [] -> raise Not_found
+ | t1::_ ->
+ try constructor_at_head1 t1
+ with _ -> raise Not_found)
+ in (id_of_cl cl1),(cl1,p1,v1,lv1,1,l)
+ | Some (Ident id) -> id, aux (function cl -> id_of_cl cl = id)
+ | Some (Section_path sp) ->
+ basename sp,
+ aux (function
+ CL_SP sp1 -> sp=sp1
+ | CL_IND (sp1,i) -> sp=sp1
+ | _ -> false)
+
+let get_target t ind =
+ if (ind > 1)
+ then CL_FUN,0,t
+ else let v2,_,_,cl2,p2 = constructor_at_head1 t in
+ cl2,p2,v2
+
+
+let prods_of t =
+ let rec aux acc = function
+ DOP2(Prod,c1,DLAM(_,c2)) -> aux (c1::acc) c2
+ | (DOP2(Cast,c,_)) -> aux acc c
+ | t -> t::acc
+ in aux [] t
+
+(* coercion identite' *)
+
+let lams_of t =
+ let rec aux acc = function
+ DOP2(Lambda,c1,DLAM(x,c2)) -> aux ((x,c1)::acc) c2
+ | (DOP2(Cast,c,_)) -> aux acc c
+ | t -> acc,t
+ in aux [] t
+
+let build_id_coercion idf_opt ids =
+ let env = Global.env () in
+ let vs = global env ids in
+ let c = match (strip_outer_cast vs) with
+ (DOPN(Const sp,l) as c') when Environ.evaluable_constant env c' ->
+ (try Instantiate.constant_value env c'
+ with _ -> errorlabstrm "build_id_coercion"
+ [< 'sTR(string_of_id ids);
+ 'sTR" must be a transparent constant" >])
+ | _ -> errorlabstrm "build_id_coercion"
+ [< 'sTR(string_of_id ids); 'sTR" must be a transparent constant" >] in
+ let lams,t = lams_of c in
+ let lams = List.rev lams in
+ let llams = List.length lams in
+ let val_f =
+ List.fold_right
+ (fun (x,t) u ->
+ DOP2(Lambda,t,DLAM(x,u)))
+ lams
+ (DOP2(Lambda,(applistc vs (rel_list 0 llams)),
+ DLAM(Name (id_of_string "x"),Rel 1))) in
+ let typ_f =
+ List.fold_right
+ (fun (x,t) c -> DOP2(Prod,t,DLAM(x,c)))
+ lams
+ (DOP2(Prod,(applistc vs (rel_list 0 llams)),
+ DLAM(Anonymous,lift 1 t))) in
+ let constr_f = DOP2(Cast,val_f,typ_f) in
+ (* juste pour verification *)
+ let _ = try Typing.type_of env Evd.empty constr_f
+ with _ ->
+ error "cannot be defined as coercion - may be a bad number of arguments" in
+ let idf =
+ (match idf_opt with
+ Some(idf) -> idf
+ | None ->
+ id_of_string ("Id_"^(string_of_id ids)^"_"^
+ (string_of_cl (fst (constructor_at_head t))))) in
+ let constr_entry = {const_entry_body = constr_f; const_entry_type = None } in
+ let _ = declare_constant idf (constr_entry,NeverDischarge,false)
+ in idf
+
+let coercion_syntax_entry id n =
+ let args = (String.concat " " (list_tabulate (fun _ -> "$_") n)) ^ " $c" in
+ let str = "level 10: " ^ (string_of_id id) ^
+ " [ <<(" ^ (string_of_id id) ^ " " ^ args ^ ")>> ]" ^
+ " -> [ (APPLIST $c):E ]"
+ in
+ try
+ let se = Pcoq.parse_string Pcoq.Prim.syntax_entry_eoi str in
+ Metasyntax.add_syntax_obj "constr" [se]
+ with Stdpp.Exc_located _ -> anomaly ("ill-formed syntax entry: "^str)
+
+let fun_coercion_syntax_entry id n =
+ let args =
+ if n<0 then anomaly "fun_coercion_syntax_entry"
+ else
+ String.concat " " (list_tabulate (fun _ -> "$_") n) ^ " $c ($LIST $l)" in
+ let str = "level 10: " ^ ((string_of_id id)^"1") ^
+ " [ (APPLIST " ^ (string_of_id id) ^ " " ^ args ^ ") ] " ^
+ "-> [ (APPLIST $c ($LIST $l)):E ]"
+ in
+ try
+ let se = Pcoq.parse_string Pcoq.Prim.syntax_entry_eoi str in
+ Metasyntax.add_syntax_obj "constr" [se]
+ with Stdpp.Exc_located _ -> anomaly ("ill-formed syntax entry: "^str)
+
+
+
+let coercion_syntax idf ps clt =
+ match clt with
+ CL_FUN ->
+ (fun_coercion_syntax_entry idf ps;
+ coercion_syntax_entry idf ps)
+ | _ -> coercion_syntax_entry idf ps
+
+
+let add_new_coercion_in_graph1 (coef,v,stre,isid,cls,clt) idf ps =
+ let _ = add_anonymous_leaf
+ (inCoercion
+ ((coef,
+ {cOE_VALUE=v;cOE_STRE=stre;cOE_ISID=isid;cOE_PARAM=ps}),
+ cls,clt)) in
+ coercion_syntax idf ps clt
+
+(*
+nom de la fonction coercion
+strength de f
+nom de la classe source (optionnel)
+sp de la classe source (dans le cas des structures)
+nom de la classe target (optionnel)
+booleen "coercion identite'?"
+
+lorque source est None alors target est None aussi.
+*)
+
+let try_add_new_coercion_core idf stre source target isid =
+ let env = Global.env () in
+ let v = global env idf in
+ let t = Retyping.get_type_of env Evd.empty v in
+ let k = Retyping.get_type_of env Evd.empty t in
+ let vj = {uj_val=v; uj_type=t; uj_kind = k} in
+ let f_vardep,coef = coe_constructor_at_head v in
+ if coercion_exists coef then
+ errorlabstrm "try_add_coercion"
+ [< 'sTR(string_of_id idf) ; 'sTR" is already a coercion" >];
+ let lp = prods_of t in
+ let llp = List.length lp in
+ if llp <= 1 then
+ errorlabstrm "try_add_coercion"
+ [< 'sTR"Does not correspond to a coercion" >];
+
+ let ids,(cls,ps,vs,lvs,ind,s_vardep) =
+ try get_source (List.tl lp) source
+ with Not_found -> errorlabstrm "try_add_coercion"
+ [<'sTR"We do not find the source class " >] in
+
+ if (cls = CL_FUN) then
+ errorlabstrm "try_add_coercion"
+ [< 'sTR"FUNCLASS cannot be a source class" >];
+ if (cls = CL_SORT) then
+ errorlabstrm "try_add_coercion"
+ [< 'sTR"SORTCLASS cannot be a source class" >];
+ if not (uniform_cond (llp-1-ind) lvs) then
+ errorlabstrm "try_add_coercion"
+ [<'sTR(string_of_id idf);
+ 'sTR" does not respect the inheritance uniform condition" >];
+
+ let clt,pt,vt =
+ try get_target (List.hd lp) ind
+ with Not_found -> errorlabstrm "try_add_coercion"
+ [<'sTR"We cannot find the target class" >] in
+ let idt =
+ (match target with
+ Some idt ->
+ if idt = id_of_cl clt then idt
+ else errorlabstrm "try_add_coercion"
+ [<'sTR"The target class does not correspond to ";
+ 'sTR(string_of_id idt) >]
+ | None -> (id_of_cl clt)) in
+ let stres = check_class ids vs cls ps in
+ let stret = check_class idt vt clt pt in
+ let stref = stre_of_coe coef in
+ let streunif = stre_unif_cond (s_vardep,f_vardep) in
+ let stre' = stre_max4 stres stret stref streunif in
+ (* if (stre=NeverDischarge) & (stre'<>NeverDischarge)
+ then errorlabstrm "try_add_coercion"
+ [<'sTR(string_of_id idf);
+ 'sTR" must be declared as a local coercion (its strength is ";
+ 'sTR(string_of_strength stre');'sTR")" >] *)
+ let stre = stre_max (stre,stre') in
+ add_new_coercion_in_graph1 (coef,vj,stre,isid,cls,clt) idf ps
+
+
+let try_add_new_coercion id stre =
+ try_add_new_coercion_core id stre None None false
+
+let try_add_new_coercion_subclass id stre =
+ let idf = build_id_coercion None id in
+ try_add_new_coercion_core idf stre (Some (Ident id)) None true
+
+let try_add_new_coercion_with_target id stre source target isid =
+ if isid then
+ let idf = build_id_coercion (Some id) source in
+ try_add_new_coercion_core idf stre (Some (Ident source)) (Some target) true
+ else
+ try_add_new_coercion_core id stre (Some (Ident source)) (Some target) false
+
+let try_add_new_coercion_record id stre source_sp =
+ try_add_new_coercion_core id stre (Some (Section_path source_sp)) None false
+
+(* fonctions pour le discharge: plutot sale *)
+
+let defined_in_sec sp sec_sp =
+ let ((p1,id1,k1)) = repr_path sp in
+ let ((p2,id2,k2)) = repr_path sec_sp in
+ p1 = (string_of_id id2)::p2
+
+let process_class sec_sp ((cl,{cL_STR=s;cL_STRE=stre;cL_PARAM=p}) as x ) =
+ let env = Global.env () in
+ match cl with
+ CL_Var id -> x
+ | CL_SP sp ->
+ if defined_in_sec sp sec_sp
+ then
+ let ((_,spid,spk)) = repr_path sp in
+ let newsp = Lib.make_path spid CCI in
+ let v = global_reference CCI spid in
+ let t = Retyping.get_type_of env Evd.empty v in
+ let p = arity_sort t in
+ (CL_SP newsp,{cL_STR=s;cL_STRE=stre;cL_PARAM=p})
+ else x
+ | CL_IND (sp,i) ->
+ if defined_in_sec sp sec_sp
+ then
+ let ((_,spid,spk)) = repr_path sp in
+ let newsp = Lib.make_path spid CCI in
+ let v = global_reference CCI spid in
+ let t = Retyping.get_type_of env Evd.empty v in
+ let p = arity_sort t in
+ (CL_IND (newsp,i),{cL_STR=s;cL_STRE=stre;cL_PARAM=p})
+ else x
+ | _ -> anomaly "process_class"
+
+let process_cl sec_sp cl =
+ match cl with
+ CL_Var id -> CL_Var id
+ | CL_SP sp ->
+ if defined_in_sec sp sec_sp then
+ let ((_,spid,spk)) = repr_path sp in
+ let newsp = Lib.make_path spid CCI in
+ CL_SP newsp
+ else cl
+ | CL_IND (sp,i) ->
+ if defined_in_sec sp sec_sp then
+ let ((_,spid,spk)) = repr_path sp in
+ let newsp = Lib.make_path spid CCI in
+ CL_IND (newsp,i)
+ else cl
+ | _ -> cl
+
+let process_coercion sec_sp (((coe,coeinfo),s,t) as x) =
+ let s1= process_cl sec_sp s in
+ let t1 = process_cl sec_sp t in
+ let p = (snd (class_info s1)).cL_PARAM in
+ match coe with
+ NAM_Var id -> ((coe,coeinfo),s1,t1),id,p
+ | NAM_SP sp ->
+ if defined_in_sec sp sec_sp then
+ let ((_,spid,spk)) = repr_path sp in
+ let newsp = Lib.make_path spid CCI in
+ let v = global_reference CCI spid in
+ ((NAM_SP newsp,coeinfo),s1,t1),spid,p
+ else ((coe,coeinfo),s1,t1),basename sp,p
+ | NAM_Construct ((sp,i),j) ->
+ if defined_in_sec sp sec_sp then
+ let ((_,spid,spk)) = repr_path sp in
+ let newsp = Lib.make_path spid CCI in
+ let id = Global.id_of_global (MutConstruct((newsp,i),j)) in
+ let v = global_reference CCI id in
+ (((NAM_Construct ((newsp,i),j)),coeinfo),s1,t1),id,p
+ else
+ ((coe,coeinfo),s1,t1),
+ Global.id_of_global (MutConstruct((sp,i),j)),
+ p
+
+(* Id: class.ml4,v 1.2 1997/06/17 17:44:10 dderaugl Exp $ *)
diff --git a/toplevel/class.mli b/toplevel/class.mli
new file mode 100644
index 000000000..094b2ecc2
--- /dev/null
+++ b/toplevel/class.mli
@@ -0,0 +1,25 @@
+
+(* $Id$ *)
+
+open Names
+open Term
+open Classops
+open Declare
+
+val try_add_new_coercion : identifier -> strength -> unit
+val try_add_new_coercion_subclass : identifier -> strength -> unit
+val try_add_new_coercion_record: identifier -> strength -> section_path -> unit
+val try_add_new_coercion_with_target : identifier -> strength ->
+ identifier -> identifier -> bool -> unit
+
+val try_add_new_class : identifier -> strength -> unit
+val process_class :
+ section_path -> (cl_typ * cl_info_typ) -> (cl_typ * cl_info_typ)
+val process_coercion :
+ section_path -> (coe_typ * coe_info_typ) * cl_typ * cl_typ ->
+ ((coe_typ * coe_info_typ) * cl_typ * cl_typ) * identifier * int
+
+val defined_in_sec : section_path -> section_path -> bool
+val coercion_syntax : identifier -> int -> cl_typ -> unit
+val fun_coercion_syntax_entry : identifier -> int -> unit
+val coercion_syntax_entry : identifier -> int -> unit
diff --git a/toplevel/record.ml b/toplevel/record.ml
new file mode 100644
index 000000000..cc44bc22b
--- /dev/null
+++ b/toplevel/record.ml
@@ -0,0 +1,170 @@
+
+(* $:Id$ *)
+
+open Util;;
+open Names;;
+open Term;;
+(*
+open Generic;;
+open Mach;;
+open Command;;
+open More_util;;
+open Pp;;
+
+open Constrtypes;;
+open Termenv;;
+open Trad;;
+open Ast;;
+open CoqAst;;
+
+open Machops;;
+open Classops;;
+open Recordops;;
+*)
+
+(********** definition d'un record (structure) **************)
+
+let make_constructor fields appc =
+ let rec aux fields =
+ match fields with
+ [] -> appc
+ | (id,ty)::l -> ope("PROD",[ty; slam(Some (string_of_id id), aux l)])
+ in aux fields;;
+
+(* free_vars existe de'ja` dans ast.ml *)
+
+let rec drop = function
+ [] -> []
+ | (None::t) -> drop t
+ | ((Some id)::t) -> id::(drop t)
+;;
+
+let fold curriedf l base =
+ List.fold_right (fun a -> fun b -> curriedf(a,b)) l base
+;;
+
+let free_vars t =
+ let rec aux = function
+ (Nvar(_,s),accum) -> add_set (id_of_string s) accum
+| (Node(_,_,tl),accum) -> fold aux tl accum
+| (Slam(_,None,body),accum) ->
+ (aux(body,[]))@accum
+| (Slam(_,Some id,body),accum) ->
+ (subtract (aux(body,[])) [(id_of_string id)])@accum
+| (_,accum) -> accum
+ in aux(t,[])
+;;
+
+let free_in_asts id l =
+ let rec aux =
+ function [] -> true
+ | a::l -> (not (List.mem id (free_vars a))) & (aux l) in
+ aux l;;
+
+let all_vars t =
+ let rec aux = function
+ (Nvar(_,id),accum) -> add_set (id_of_string id) accum
+| (Node(_,_,tl),accum) -> fold aux tl accum
+| (Slam(_,None,body),accum) -> aux (body,accum)
+| (Slam(_,Some id,body),accum) ->
+ aux (body,(union accum [(id_of_string id)]))
+| (_,accum) -> accum
+ in aux(t,[])
+;;
+
+let print_id_list l =
+ [< 'sTR "[" ; prlist (fun id -> [< 'sTR (string_of_id id) >]) l; 'sTR "]" >]
+;;
+
+let typecheck_params_and_field ps fs =
+ let sign0 = initial_sign() in
+ let sign1,newps =
+ List.fold_left
+ (fun (sign,newps) (id,t) ->
+ let tj = type_of_com sign t in
+ (add_sign (id,tj) sign,(id,tj.body)::newps))
+ (sign0,[]) ps in
+ let sign2,newfs =
+ List.fold_left
+ (fun (sign,newfs) (id,t) ->
+ let tj = type_of_com sign t in
+ (add_sign (id,tj) sign,(id,tj.body)::newfs)) (sign1,[]) fs
+ in List.rev(newps),List.rev(newfs)
+;;
+
+
+let mk_LambdaCit = List.fold_right (fun (x,a) b -> mkNamedLambda x a b);;
+
+
+let definition_structure (coe_constr,struc,ps,cfs,const,s) =
+
+ let (sign,fsign) = initial_assumptions() in
+ let fs = List.map snd cfs in
+ let coers = List.map fst cfs in
+ let idps = List.map fst ps in
+ let typs = List.map snd ps in
+ let idfs = List.map fst fs in
+ let tyfs = List.map snd fs in
+ let _ = if not (free_in_asts struc tyfs)
+ then message "Error: A record cannot be recursive" in
+ let newps,newfs = typecheck_params_and_field ps fs in
+ let app_constructor = ope("APPLIST",
+ (ope("XTRA",[str "!";(nvar (string_of_id struc))]))::
+ List.map (fun id -> nvar(string_of_id id)) idps) in
+ let type_constructor = make_constructor fs app_constructor in
+ let _ = build_mutual ps [(struc,s,[(const,type_constructor)])] true in
+
+ let x = next_ident_away (id_of_string "x")
+ (List.fold_left (fun l ty -> union (all_vars ty) l)
+ (union idps (fst sign)) tyfs) in
+ let r = Machops.global (gLOB sign) struc in
+ let (rsp,_,_) = destMutInd r in
+ let rid = basename rsp in
+ let lp = length idps in
+ let rp1 = applist (r,(rel_list 0 lp)) in
+ let rp2 = applist (r,(rel_list 1 lp)) in
+ let warning_or_error coe st = if coe then (errorlabstrm "structure" st)
+ else pPNL [< 'sTR"Warning: "; st >] in
+
+ let (sp_projs,_,_,_,_) =
+ List.fold_left
+ (fun (sp_projs,ids_ok,ids_not_ok,sigma,coes) (fi,ti) ->
+ let fv_ti = global_vars ti in
+ let bad_projs = (intersect ids_not_ok fv_ti) in
+ if bad_projs <> []
+ then begin (warning_or_error (hd coes)
+ [< 'sTR(string_of_id fi);
+ 'sTR" cannot be defined. The projections ";
+ print_id_list bad_projs; 'sTR " were not defined" >]);
+ (None::sp_projs,ids_ok,fi::ids_not_ok,sigma,(tl coes))
+ end
+ else
+
+ let p = mkNamedLambda x rp2 (replace_vars sigma ti) in
+ let branch = mk_LambdaCit newfs (VAR fi) in
+ let proj = mk_LambdaCit newps
+ (mkNamedLambda x rp1 (mkMutCaseA (ci_of_mind r) p (Rel 1) [|branch|])) in
+ let ok = try (Declare.machine_constant (sign,fsign)
+ ((fi,false,NeverDischarge),proj); true)
+ with UserError(s,pps) ->
+ ((warning_or_error (hd coes)
+ [<'sTR (string_of_id fi);
+ 'sTR" cannot be defined. "; pps >]);false) in
+ if not ok
+ then (None::sp_projs,ids_ok,fi::ids_not_ok,sigma,(tl coes))
+ else begin
+ if List.hd coes then
+ Class.try_add_new_coercion_record fi NeverDischarge rsp;
+ let constr_fi = Machops.global (gLOB sign) fi in
+ let constr_fip =
+ applist (constr_fi,(List.map (fun id -> VAR id) idps)@[VAR x])
+ in (Some(path_of_const constr_fi)::sp_projs,fi::ids_ok,ids_not_ok,
+ (fi,{sinfo=Closed;sit=constr_fip})::sigma,(tl coes))
+ end)
+ ([],[],[],[],coers) newfs
+ in (if coe_constr="COERCION"
+ then Class.try_add_new_coercion const NeverDischarge);
+ add_new_struc (rsp,const,lp,rev sp_projs)
+;;
+
+(* $Id$ *)
diff --git a/toplevel/record.mli b/toplevel/record.mli
new file mode 100644
index 000000000..4e0ba6036d
--- /dev/null
+++ b/toplevel/record.mli
@@ -0,0 +1,12 @@
+
+(* $Id$ *)
+
+open Names
+open Term
+
+val definition_structure :
+ string * identifier * (identifier * CoqAst.t) list *
+ (bool * (identifier * CoqAst.t)) list * identifier *
+ CoqAst.t -> unit;;
+
+(* $Id$ *)