diff options
author | herbelin <herbelin@85f007b7-540e-0410-9357-904b9bb8a0f7> | 2005-02-18 22:17:50 +0000 |
---|---|---|
committer | herbelin <herbelin@85f007b7-540e-0410-9357-904b9bb8a0f7> | 2005-02-18 22:17:50 +0000 |
commit | 7b2a24d0beee17b61281a5c64fca5cf7388479d3 (patch) | |
tree | 7df42aa9ea5cf3e5ae6066c0aa73673cd67bc19d /pretyping | |
parent | 8c417a6d32e379d9642d6f2ef144f33d7df4832e (diff) |
Moving centralised discharge into dispatched discharge_function; required to delay some computation from before to after caching time + various simplifications and uniformisations
git-svn-id: svn+ssh://scm.gforge.inria.fr/svn/coq/trunk@6748 85f007b7-540e-0410-9357-904b9bb8a0f7
Diffstat (limited to 'pretyping')
-rwxr-xr-x | pretyping/classops.ml | 149 | ||||
-rw-r--r-- | pretyping/classops.mli | 19 | ||||
-rwxr-xr-x | pretyping/recordops.ml | 190 | ||||
-rwxr-xr-x | pretyping/recordops.mli | 36 |
4 files changed, 217 insertions, 177 deletions
diff --git a/pretyping/classops.ml b/pretyping/classops.ml index 66ed81d02..6d49baf52 100755 --- a/pretyping/classops.ml +++ b/pretyping/classops.ml @@ -36,14 +36,14 @@ type cl_typ = | CL_IND of inductive type cl_info_typ = { - cl_strength : strength; cl_param : int } type coe_typ = global_reference type coe_info_typ = { - coe_value : unsafe_judgment; + coe_value : constr; + coe_type : types; coe_strength : strength; coe_is_identity : bool; coe_param : int } @@ -92,11 +92,7 @@ let unfreeze (fcl,fco,fig) = (* ajout de nouveaux "objets" *) let add_new_class cl s = - try - let n,s' = Bijint.revmap cl !class_tab in - if s.cl_strength = Global & s'.cl_strength <> Global then - class_tab := Bijint.replace n cl s !class_tab - with Not_found -> + if not (Bijint.mem cl !class_tab) then class_tab := Bijint.add cl s !class_tab let add_new_coercion coe s = @@ -107,11 +103,19 @@ let add_new_path x y = let init () = class_tab:= Bijint.empty; - add_new_class CL_FUN { cl_param = 0; cl_strength = Global }; - add_new_class CL_SORT { cl_param = 0; cl_strength = Global }; + add_new_class CL_FUN { cl_param = 0 }; + add_new_class CL_SORT { cl_param = 0 }; coercion_tab:= Gmap.empty; inheritance_graph:= Gmap.empty +let _ = + Summary.declare_summary "inh_graph" + { Summary.freeze_function = freeze; + Summary.unfreeze_function = unfreeze; + Summary.init_function = init; + Summary.survive_module = false; + Summary.survive_section = false } + let _ = init() (* class_info : cl_typ -> int * cl_info_typ *) @@ -147,7 +151,7 @@ let lookup_pattern_path_between (s,t) = (fun coe -> let c, _ = Reductionops.whd_betadeltaiota_stack (Global.env()) Evd.empty - coe.coe_value.uj_val + coe.coe_value in match kind_of_term c with | Construct sp -> (sp, coe.coe_param) @@ -183,44 +187,6 @@ let subst_cl_typ subst ct = match ct with to declare any term as a coercion *) let subst_coe_typ subst t = fst (subst_global subst t) -let subst_coe_info subst info = - let jud = info.coe_value in - let val' = subst_mps subst (j_val jud) in - let type' = subst_mps subst (j_type jud) in - if val' == j_val jud && type' == j_type jud then info else - {info with coe_value = make_judge val' type'} - -(* library, summary *) - -(*val inClass : (cl_typ * cl_info_typ) -> Libobject.object = <fun> - val outClass : Libobject.object -> (cl_typ * cl_info_typ) = <fun> *) - -let cache_class (_,(x,y)) = add_new_class x y - -let subst_class (_,subst,(ct,ci as obj)) = - let ct' = subst_cl_typ subst ct in - if ct' == ct then obj else - (ct',ci) - -let (inClass,outClass) = - declare_object {(default_object "CLASS") with - load_function = (fun _ o -> cache_class o); - cache_function = cache_class; - subst_function = subst_class; - classify_function = (fun (_,x) -> Substitute x); - export_function = (function x -> Some x) } - -let declare_class (cl,stre,p) = - Lib.add_anonymous_leaf (inClass ((cl,{ cl_strength = stre; cl_param = p }))) - -let _ = - Summary.declare_summary "inh_graph" - { Summary.freeze_function = freeze; - Summary.unfreeze_function = unfreeze; - Summary.init_function = init; - Summary.survive_module = false; - Summary.survive_section = false } - (* classe d'un terme *) (* class_of : Term.constr -> int *) @@ -257,7 +223,8 @@ let pr_class x = str (string_of_class x) (* coercion_value : coe_index -> unsafe_judgment * bool *) -let coercion_value { coe_value = j; coe_is_identity = b } = (j,b) +let coercion_value { coe_value = c; coe_type = t; coe_is_identity = b } = + (make_judge c t, b) (* pretty-print functions are now in Pretty *) (* rajouter une coercion dans le graphe *) @@ -322,49 +289,81 @@ let add_coercion_in_graph (ic,source,target) = if (!ambig_paths <> []) && is_verbose () then ppnl (message_ambig !ambig_paths) -type coercion = coe_typ * coe_info_typ * cl_typ * cl_typ +type coercion = coe_typ * strength * bool * cl_typ * cl_typ * int -let cache_coercion (_,(coe,xf,cls,clt)) = +(* Calcul de l'arité d'une classe *) + +let reference_arity_length ref = + let t = Global.type_of_global ref in + List.length (fst (Reductionops.splay_arity (Global.env()) Evd.empty t)) + +let class_params = function + | CL_FUN | CL_SORT -> 0 + | CL_CONST sp -> reference_arity_length (ConstRef sp) + | CL_SECVAR sp -> reference_arity_length (VarRef sp) + | CL_IND sp -> reference_arity_length (IndRef sp) + +(* add_class : cl_typ -> strength option -> bool -> unit *) + +let add_class cl = + add_new_class cl { cl_param = class_params cl } + +let load_coercion i (_,(coe,stre,isid,cls,clt,ps)) = + add_class cls; + add_class clt; let is,_ = class_info cls in let it,_ = class_info clt in + let xf = + { coe_value = constr_of_global coe; + coe_type = Global.type_of_global coe; + coe_strength = stre; + coe_is_identity = isid; + coe_param = ps } in add_new_coercion coe xf; add_coercion_in_graph (xf,is,it) -let subst_coercion (_,subst,(coe,xf,cls,clt as obj)) = +let cache_coercion o = + load_coercion 1 o + +let subst_coercion (_,subst,(coe,stre,isid,cls,clt,ps as obj)) = let coe' = subst_coe_typ subst coe in - let xf' = subst_coe_info subst xf in let cls' = subst_cl_typ subst cls in let clt' = subst_cl_typ subst clt in - if coe' == coe && xf' == xf && cls' == cls & clt' == clt then obj else - (coe',xf',cls',clt') - - -(* val inCoercion : coercion -> Libobject.object - val outCoercion : Libobject.object -> coercion *) + if coe' == coe && cls' == cls & clt' == clt then obj else + (coe',stre,isid,cls',clt',ps) + +let discharge_cl = function + | CL_CONST kn -> CL_CONST (Lib.discharge_con kn) + | CL_IND ind -> CL_IND (Lib.discharge_inductive ind) + | cl -> cl + +let discharge_coercion (_,(coe,stre,isid,cls,clt,ps)) = + if stre = Local then None else + let n = try Array.length (Lib.section_instance coe) with Not_found -> 0 in + Some (Lib.discharge_global coe, + stre, + isid, + discharge_cl cls, + discharge_cl clt, + n + ps) let (inCoercion,outCoercion) = declare_object {(default_object "COERCION") with - load_function = (fun _ o -> cache_coercion o); - cache_function = cache_coercion; - subst_function = subst_coercion; - classify_function = (fun (_,x) -> Substitute x); - export_function = (function x -> Some x) } - -let declare_coercion coef v stre ~isid ~src:cls ~target:clt ~params:ps = - Lib.add_anonymous_leaf - (inCoercion - (coef, - { coe_value = v; - coe_strength = stre; - coe_is_identity = isid; - coe_param = ps }, - cls, clt)) + load_function = load_coercion; + cache_function = cache_coercion; + subst_function = subst_coercion; + classify_function = (fun (_,x) -> Substitute x); + discharge_function = discharge_coercion; + export_function = (function x -> Some x) } + +let declare_coercion coef stre ~isid ~src:cls ~target:clt ~params:ps = + Lib.add_anonymous_leaf (inCoercion (coef,stre,isid,cls,clt,ps)) let coercion_strength v = v.coe_strength let coercion_identity v = v.coe_is_identity (* For printing purpose *) -let get_coercion_value v = v.coe_value.uj_val +let get_coercion_value v = v.coe_value let classes () = Bijint.dom !class_tab let coercions () = Gmap.rng !coercion_tab diff --git a/pretyping/classops.mli b/pretyping/classops.mli index c1590f6a8..dd51ee970 100644 --- a/pretyping/classops.mli +++ b/pretyping/classops.mli @@ -30,7 +30,6 @@ val subst_cl_typ : substitution -> cl_typ -> cl_typ (* This is the type of infos for declared classes *) type cl_info_typ = { - cl_strength : strength; cl_param : int } (* This is the type of coercion kinds *) @@ -48,9 +47,6 @@ type coe_index (* This is the type of paths from a class to another *) type inheritance_path = coe_index list -(*s [declare_class] adds a class to the set of declared classes *) -val declare_class : cl_typ * strength * int -> unit - (*s Access to classes infos *) val class_info : cl_typ -> (cl_index * cl_info_typ) val class_exists : cl_typ -> bool @@ -70,7 +66,7 @@ val class_args_of : constr -> constr list (*s [declare_coercion] adds a coercion in the graph of coercion paths *) val declare_coercion : - coe_typ -> unsafe_judgment -> strength -> isid:bool -> + coe_typ -> strength -> isid:bool -> src:cl_typ -> target:cl_typ -> params:int -> unit (*s Access to coercions infos *) @@ -85,19 +81,6 @@ val lookup_path_to_sort_from : cl_index -> inheritance_path val lookup_pattern_path_between : cl_index * cl_index -> (constructor * int) list -(*i Pour le discharge *) -type coercion = coe_typ * coe_info_typ * cl_typ * cl_typ - -open Libobject -val inClass : (cl_typ * cl_info_typ) -> Libobject.obj -val outClass : Libobject.obj -> (cl_typ * cl_info_typ) -val inCoercion : coercion -> Libobject.obj -val outCoercion : Libobject.obj -> coercion -val coercion_strength : coe_info_typ -> strength -val coercion_identity : coe_info_typ -> bool -val coercion_params : coe_info_typ -> int -(*i*) - (*i Crade *) open Pp val install_path_printer : diff --git a/pretyping/recordops.ml b/pretyping/recordops.ml index cfccdb5e6..7f557d9b3 100755 --- a/pretyping/recordops.ml +++ b/pretyping/recordops.ml @@ -21,17 +21,19 @@ open Library open Classops open Mod_subst -(*s Une structure S est un type inductif non récursif à un seul - constructeur (de nom par défaut Build_S) *) +(*s A structure S is a non recursive inductive type with a single + constructor (the name of which defaults to Build_S) *) (* Table des structures: le nom de la structure (un [inductive]) donne le nom du constructeur, le nombre de paramètres et pour chaque - argument réels du constructeur, le noms de la projection - correspondante, si valide *) + argument réel du constructeur, le nom de la projection + correspondante, si valide, et un booléen disant si c'est une vraie + projection ou bien une fonction constante (associée à un LetIn) *) type struc_typ = { s_CONST : identifier; s_PARAM : int; + s_PROJKIND : bool list; s_PROJ : constant option list } let structure_table = ref (Indmap.empty : struc_typ Indmap.t) @@ -39,121 +41,177 @@ let projection_table = ref Cmap.empty let option_fold_right f p e = match p with Some a -> f a e | None -> e -let cache_structure (_,(ind,struc)) = +let load_structure i (_,(ind,id,kl,projs)) = + let n = (snd (Global.lookup_inductive ind)).Declarations.mind_nparams in + let struc = + { s_CONST = id; s_PARAM = n; s_PROJ = projs; s_PROJKIND = kl } in structure_table := Indmap.add ind struc !structure_table; projection_table := List.fold_right (option_fold_right (fun proj -> Cmap.add proj struc)) - struc.s_PROJ !projection_table + projs !projection_table -let subst_structure (_,subst,((kn,i),struc as obj)) = +let cache_structure o = + load_structure 1 o + +let subst_structure (_,subst,((kn,i),id,kl,projs as obj)) = let kn' = subst_kn subst kn in - let proj' = + let projs' = (* invariant: struc.s_PROJ is an evaluable reference. Thus we can take *) (* the first component of subst_con. *) list_smartmap - (option_smartmap (fun kn -> fst (subst_con subst kn))) - struc.s_PROJ + (option_smartmap (fun kn -> fst (subst_con subst kn))) + projs in - if proj' == struc.s_PROJ && kn' == kn then obj else - (kn',i),{struc with s_PROJ = proj'} + if projs' == projs && kn' == kn then obj else + ((kn',i),id,kl,projs') + +let discharge_structure (_,(ind,id,kl,projs)) = + Some (Lib.discharge_inductive ind, id, kl, + List.map (option_app Lib.discharge_con) projs) let (inStruc,outStruc) = declare_object {(default_object "STRUCTURE") with - cache_function = cache_structure; - load_function = (fun _ o -> cache_structure o); - subst_function = subst_structure; - classify_function = (fun (_,x) -> Substitute x); - export_function = (function x -> Some x) } + cache_function = cache_structure; + load_function = load_structure; + subst_function = subst_structure; + classify_function = (fun (_,x) -> Substitute x); + discharge_function = discharge_structure; + export_function = (function x -> Some x) } -let add_new_struc (s,c,n,l) = - Lib.add_anonymous_leaf (inStruc (s,{s_CONST=c;s_PARAM=n;s_PROJ=l})) +let declare_structure (s,c,_,kl,pl) = + Lib.add_anonymous_leaf (inStruc (s,c,kl,pl)) -let find_structure indsp = Indmap.find indsp !structure_table +let lookup_structure indsp = Indmap.find indsp !structure_table let find_projection_nparams = function | ConstRef cst -> (Cmap.find cst !projection_table).s_PARAM | _ -> raise Not_found -(*s Un "object" est une fonction construisant une instance d'une structure *) + +(************************************************************************) +(*s A canonical structure declares "canonical" conversion hints between *) +(* the effective components of a structure and the projections of the *) +(* structure *) (* Table des definitions "object" : pour chaque object c, c := [x1:B1]...[xk:Bk](Build_R a1...am t1...t_n) - avec ti = (ci ui1...uir) + If ti has the form (ci ui1...uir) where ci is a global reference and +if the corresponding projection Li of the structure R is defined, one +declare a "conversion" between ci and Li + + x1:B1..xk:Bk |- (Li a1..am (c x1..xk)) =_conv (ci ui1...uir) - Pour tout ci, et Li, la ième projection de la structure R (si - définie), on déclare une "coercion" +that maps the pair (Li,ci) to the following data o_DEF = c o_TABS = B1...Bk o_PARAMS = a1...am o_TCOMP = ui1...uir + *) type obj_typ = { o_DEF : constr; - o_TABS : constr list; (* dans l'ordre *) - o_TPARAMS : constr list; (* dans l'ordre *) - o_TCOMPS : constr list } (* dans l'ordre *) - -let subst_obj subst obj = - let o_DEF' = subst_mps subst obj.o_DEF in - let o_TABS' = list_smartmap (subst_mps subst) obj.o_TABS in - let o_TPARAMS' = list_smartmap (subst_mps subst) obj.o_TPARAMS in - let o_TCOMPS' = list_smartmap (subst_mps subst) obj.o_TCOMPS in - if o_DEF' == obj.o_DEF - && o_TABS' == obj.o_TABS - && o_TPARAMS' == obj.o_TPARAMS - && o_TCOMPS' == obj.o_TCOMPS - then - obj - else - { o_DEF = o_DEF' ; - o_TABS = o_TABS' ; - o_TPARAMS = o_TPARAMS' ; - o_TCOMPS = o_TCOMPS' } + o_TABS : constr list; (* ordered *) + o_TPARAMS : constr list; (* ordered *) + o_TCOMPS : constr list } (* ordered *) let object_table = (ref [] : ((global_reference * global_reference) * obj_typ) list ref) -let canonical_structures () = !object_table - -let cache_canonical_structure (_,(cst,lo)) = - List.iter (fun (o,_ as x) -> - if not (List.mem_assoc o !object_table) then - object_table := x :: (!object_table)) lo - -let subst_object subst ((r1,r2),o as obj) = - (* invariant: r1 and r2 are evaluable references. Thus subst_global *) - (* cannot instantiate them. Hence we can use just the first component *) - (* of the answer. *) - let r1',_ = subst_global subst r1 in - let r2',_ = subst_global subst r2 in - let o' = subst_obj subst o in - if r1' == r1 && r2' == r2 && o' == o then obj - else (r1',r2'),o' - -let subst_canonical_structure (_,subst,(cst,lo as obj)) = +let canonical_projections () = !object_table + +let keep_true_projections projs kinds = + map_succeed (function (p,true) -> p | _ -> failwith "") + (List.combine projs kinds) + +(* Intended to always success *) +let compute_canonical_projections (con,ind) = + let v = mkConst con in + let c = Environ.constant_value (Global.env()) con in + let lt,t = Reductionops.splay_lambda (Global.env()) Evd.empty c in + let lt = List.rev (List.map snd lt) in + let args = snd (decompose_app t) in + let { s_PARAM = p; s_PROJ = lpj; s_PROJKIND = kl } = lookup_structure ind in + let params, projs = list_chop p args in + let lpj = keep_true_projections lpj kl in + let lps = List.combine lpj projs in + let comp = + List.fold_left + (fun l (spopt,t) -> (* comp=components *) + match spopt with + | Some proji_sp -> + let c, args = decompose_app t in + (try (ConstRef proji_sp, reference_of_constr c, args) :: l + with Not_found -> l) + | _ -> l) + [] lps in + List.map (fun (refi,c,argj) -> + (refi,c),{o_DEF=v; o_TABS=lt; o_TPARAMS=params; o_TCOMPS=argj}) + comp + +let open_canonical_structure i (_,o) = + if i=1 then + let lo = compute_canonical_projections o in + List.iter (fun (o,_ as x) -> + if not (List.mem_assoc o !object_table) then + object_table := x :: (!object_table)) lo + +let cache_canonical_structure o = + open_canonical_structure 1 o + +let subst_canonical_structure (_,subst,(cst,ind as obj)) = (* invariant: cst is an evaluable reference. Thus we can take *) (* the first component of subst_con. *) let cst' = fst (subst_con subst cst) in - let lo' = list_smartmap (subst_object subst) lo in - if cst' == cst & lo' == lo then obj else (cst',lo') + let ind' = Inductiveops.subst_inductive subst ind in + if cst' == cst & ind' == ind then obj else (cst',ind') + +let discharge_canonical_structure (_,(cst,ind)) = + Some (Lib.discharge_con cst,Lib.discharge_inductive ind) let (inCanonStruc,outCanonStruct) = declare_object {(default_object "CANONICAL-STRUCTURE") with - open_function = (fun i o -> if i=1 then cache_canonical_structure o); + open_function = open_canonical_structure; cache_function = cache_canonical_structure; subst_function = subst_canonical_structure; classify_function = (fun (_,x) -> Substitute x); + discharge_function = discharge_canonical_structure; export_function = (function x -> Some x) } let add_canonical_structure x = Lib.add_anonymous_leaf (inCanonStruc x) +(*s High-level declaration of a canonical structure *) + +let error_not_structure ref = + errorlabstrm "object_declare" + (Nameops.pr_id (id_of_global ref) ++ str" is not a structure object") + +let check_and_decompose_canonical_structure ref = + let sp = match ref with ConstRef sp -> sp | _ -> error_not_structure ref in + let env = Global.env () in + let vc = match Environ.constant_opt_value env sp with + | Some vc -> vc + | None -> error_not_structure ref in + let f,args = match kind_of_term (snd (decompose_lam vc)) with + | App (f,args) -> f,args + | _ -> error_not_structure ref in + let indsp = match kind_of_term f with + | Construct (indsp,1) -> indsp + | _ -> error_not_structure ref in + let s = try lookup_structure indsp with Not_found -> error_not_structure ref in + if s.s_PARAM + List.length s.s_PROJ > Array.length args then + error_not_structure ref; + (sp,indsp) + +let declare_canonical_structure ref = + add_canonical_structure (check_and_decompose_canonical_structure ref) + let outCanonicalStructure x = fst (outCanonStruct x) -let canonical_structure_info o = List.assoc o !object_table +let lookup_canonical_conversion o = List.assoc o !object_table let freeze () = !structure_table, !projection_table, !object_table diff --git a/pretyping/recordops.mli b/pretyping/recordops.mli index 7402f74c9..d6f90e11e 100755 --- a/pretyping/recordops.mli +++ b/pretyping/recordops.mli @@ -18,36 +18,36 @@ open Libobject open Library (*i*) +(*s A structure S is a non recursive inductive type with a single + constructor (the name of which defaults to Build_S) *) + type struc_typ = { s_CONST : identifier; s_PARAM : int; + s_PROJKIND : bool list; s_PROJ : constant option list } -val add_new_struc : - inductive * identifier * int * constant option list -> unit +val declare_structure : + inductive * identifier * int * bool list * constant option list -> unit -(* [find_structure isp] returns the infos associated to inductive path +(* [lookup_structure isp] returns the infos associated to inductive path [isp] if it corresponds to a structure, otherwise fails with [Not_found] *) -val find_structure : inductive -> struc_typ +val lookup_structure : inductive -> struc_typ (* raise [Not_found] if not a projection *) val find_projection_nparams : global_reference -> int +(*s A canonical structure declares "canonical" conversion hints between *) +(* the effective components of a structure and the projections of the *) +(* structure *) + type obj_typ = { o_DEF : constr; - o_TABS : constr list; (* dans l'ordre *) - o_TPARAMS : constr list; (* dans l'ordre *) - o_TCOMPS : constr list } (* dans l'ordre *) + o_TABS : constr list; (* ordered *) + o_TPARAMS : constr list; (* ordered *) + o_TCOMPS : constr list } (* ordered *) -val canonical_structure_info : - (global_reference * global_reference) -> obj_typ -val add_canonical_structure : - constant * ((global_reference * global_reference) * obj_typ) list -> unit - -val inStruc : inductive * struc_typ -> obj -val outStruc : obj -> inductive * struc_typ - -val outCanonicalStructure : obj -> constant - -val canonical_structures : unit -> +val lookup_canonical_conversion : (global_reference * global_reference) -> obj_typ +val declare_canonical_structure : global_reference -> unit +val canonical_projections : unit -> ((global_reference * global_reference) * obj_typ) list |