aboutsummaryrefslogtreecommitdiffhomepage
path: root/library/lib.ml
diff options
context:
space:
mode:
authorGravatar coq <coq@85f007b7-540e-0410-9357-904b9bb8a0f7>2002-08-02 17:17:42 +0000
committerGravatar coq <coq@85f007b7-540e-0410-9357-904b9bb8a0f7>2002-08-02 17:17:42 +0000
commit12965209478bd99dfbe57f07d5b525e51b903f22 (patch)
tree36a7f5e4802cd321caf02fed0be8349100be09fb /library/lib.ml
parent8b26fd6ba739d4f49fae99ed764b086022e44b50 (diff)
Modules dans COQ\!\!\!\!
git-svn-id: svn+ssh://scm.gforge.inria.fr/svn/coq/trunk@2957 85f007b7-540e-0410-9357-904b9bb8a0f7
Diffstat (limited to 'library/lib.ml')
-rw-r--r--library/lib.ml447
1 files changed, 344 insertions, 103 deletions
diff --git a/library/lib.ml b/library/lib.ml
index 8eaba772e..286133305 100644
--- a/library/lib.ml
+++ b/library/lib.ml
@@ -11,23 +11,102 @@
open Pp
open Util
open Names
+open Libnames
open Nameops
open Libobject
open Summary
+
type node =
| Leaf of obj
- | Module of dir_path
- | OpenedSection of dir_path * Summary.frozen
+ | CompilingModule of object_prefix
+ | OpenedModule of object_prefix * Summary.frozen
+ | OpenedModtype of object_prefix * Summary.frozen
+ | OpenedSection of object_prefix * Summary.frozen
(* bool is to tell if the section must be opened automatically *)
| ClosedSection of bool * dir_path * library_segment
| FrozenState of Summary.frozen
-and library_entry = section_path * node
+and library_entry = object_name * node
and library_segment = library_entry list
+type lib_objects = (identifier * obj) list
+
+let rec iter_leaves f i seg =
+ match seg with
+ | [] -> ()
+ | (oname ,Leaf obj)::segtl ->
+ f i (oname,obj);
+ iter_leaves f i segtl
+ | _ -> anomaly "We should have leaves only here"
+
+
+let open_segment = iter_leaves open_object
+
+let load_segment = iter_leaves load_object
+
+let change_kns mp seg =
+ let subst_one = function
+ | ((sp,kn),(Leaf obj as lobj)) ->
+ let kn' = make_kn mp empty_dirpath (label kn) in
+ ((sp,kn'),lobj)
+ | _ -> anomaly "We should have leaves only here"
+ in
+ List.map subst_one seg
+
+let subst_segment (dirpath,(mp,dir)) subst seg =
+ let subst_one = function
+ | ((sp,kn),Leaf obj) ->
+ let sp' = make_path dirpath (basename sp) in
+ let kn' = make_kn mp dir (label kn) in
+ let oname' = sp',kn' in
+ let obj' = subst_object (oname',subst,obj) in
+ (oname', Leaf obj')
+ | _ -> anomaly "We should have leaves only here"
+ in
+ List.map subst_one seg
+
+
+let iter_objects f i prefix =
+ List.iter (fun (id,obj) -> f i (make_oname prefix id, obj))
+
+let load_objects = iter_objects load_object
+let open_objects = iter_objects open_object
+
+let subst_objects prefix subst seg =
+ let subst_one = fun (id,obj as node) ->
+ let obj' = subst_object (make_oname prefix id, subst, obj) in
+ if obj' == obj then node else
+ (id, obj')
+ in
+ list_smartmap subst_one seg
+
+let classify_objects seg =
+ let rec clean ((substl,keepl,anticipl) as acc) = function
+ | (_,CompilingModule _) :: _ | [] -> acc
+ | ((sp,kn as oname),Leaf o) as node :: stk ->
+ let id = id_of_label (label kn) in
+ (match classify_object (oname,o) with
+ | Dispose -> clean acc stk
+ | Keep o' ->
+ clean (substl, (id,o')::keepl, anticipl) stk
+ | Substitute o' ->
+ clean ((id,o')::substl, keepl, anticipl) stk
+ | Anticipate o' ->
+ clean (substl, keepl, o'::anticipl) stk)
+ | (oname,ClosedSection _ as item) :: stk -> clean acc stk
+ | (_,OpenedSection _) :: _ -> error "there are still opened sections"
+ | (_,OpenedModule _) :: _ -> error "there are still opened modules"
+ | (_,OpenedModtype _) :: _ -> error "there are still opened module types"
+ | (_,FrozenState _) :: stk -> clean acc stk
+ in
+ clean ([],[],[]) (List.rev seg)
+
+
+let segment_of_objects prefix =
+ List.map (fun (id,obj) -> (make_oname prefix id, Leaf obj))
(* We keep trace of operations in the stack [lib_stk].
[path_prefix] is the current path of sections, where sections are stored in
@@ -36,31 +115,44 @@ and library_segment = library_entry list
sections, but on the contrary there are many constructions of section
paths based on the library path. *)
+let initial_prefix = default_module,(initial_path,empty_dirpath)
+
let lib_stk = ref ([] : library_segment)
-let module_name = ref None
-let path_prefix = ref (default_module : dir_path)
+let comp_name = ref None
+let path_prefix = ref initial_prefix
-let module_sp () =
- match !module_name with Some m -> m | None -> default_module
+let module_dp () =
+ match !comp_name with Some m -> m | None -> default_module
let recalc_path_prefix () =
let rec recalc = function
| (sp, OpenedSection (dir,_)) :: _ -> dir
+ | (sp, OpenedModule (dir,_)) :: _ -> dir
+ | (sp, OpenedModtype (dir,_)) :: _ -> dir
+ | (sp, CompilingModule dir) :: _ -> dir
| _::l -> recalc l
- | [] -> module_sp ()
+ | [] -> initial_prefix
in
path_prefix := recalc !lib_stk
-let pop_path_prefix () = path_prefix := fst (split_dirpath !path_prefix)
+let pop_path_prefix () =
+ let dir,(mp,sec) = !path_prefix in
+ path_prefix := fst (split_dirpath dir), (mp, fst (split_dirpath sec))
+
+let make_path id = Libnames.make_path (fst !path_prefix) id
-let make_path id = Names.make_path !path_prefix id
+let make_kn id =
+ let mp,dir = snd !path_prefix in
+ Names.make_kn mp dir (label_of_id id)
+
+let make_oname id = make_path id, make_kn id
let sections_depth () =
- List.length (repr_dirpath !path_prefix)
- - List.length (repr_dirpath (module_sp ()))
+ List.length (repr_dirpath (snd (snd !path_prefix)))
-let cwd () = !path_prefix
+let cwd () = fst !path_prefix
+let current_prefix () = snd !path_prefix
let find_entry_p p =
let rec find = function
@@ -70,12 +162,17 @@ let find_entry_p p =
find !lib_stk
let split_lib sp =
- let rec findrec after = function
- | ((sp',obj) as hd)::before ->
- if sp = sp' then (after,hd,before) else findrec (hd::after) before
+ let rec collect after equal = function
+ | ((sp',_) as hd)::before ->
+ if sp = sp' then collect after (hd::equal) before else after,equal,hd::before
+ | [] -> after,equal,[]
+ in
+ let rec findeq after = function
+ | ((sp',_) as hd)::before ->
+ if sp = sp' then collect after [hd] before else findeq (hd::after) before
| [] -> error "no such entry"
in
- findrec [] !lib_stk
+ findeq [] !lib_stk
(* Adding operations. *)
@@ -87,119 +184,267 @@ let anonymous_id =
fun () -> incr n; id_of_string ("_" ^ (string_of_int !n))
let add_anonymous_entry node =
- let sp = make_path (anonymous_id()) in
- add_entry sp node;
- sp
+ let id = anonymous_id () in
+ let name = make_oname id in
+ add_entry name node;
+ name
let add_absolutely_named_leaf sp obj =
cache_object (sp,obj);
add_entry sp (Leaf obj)
let add_leaf id obj =
- let sp = make_path id in
- cache_object (sp,obj);
- add_entry sp (Leaf obj);
- sp
+ let oname = make_oname id in
+ cache_object (oname,obj);
+ add_entry oname (Leaf obj);
+ oname
+
+let add_leaves id objs =
+ let oname = make_oname id in
+ let add_obj obj =
+ add_entry oname (Leaf obj);
+ load_object 1 (oname,obj)
+ in
+ List.iter add_obj objs;
+ oname
let add_anonymous_leaf obj =
- let sp = make_path (anonymous_id()) in
- cache_object (sp,obj);
- add_entry sp (Leaf obj)
+ let id = anonymous_id () in
+ let oname = make_oname id in
+ cache_object (oname,obj);
+ add_entry oname (Leaf obj)
let add_frozen_state () =
let _ = add_anonymous_entry (FrozenState (freeze_summaries())) in ()
+(* Modules. *)
+
+let is_something_opened = function
+ (_,OpenedSection _) -> true
+ | (_,OpenedModule _) -> true
+ | (_,OpenedModtype _) -> true
+ | _ -> false
+
+let classify_segment seg =
+ let rec clean ((substl,keepl,anticipl) as acc) = function
+ | (_,CompilingModule _) :: _ | [] -> acc
+ | (oname,Leaf o) as node :: stk ->
+ (match classify_object (oname,o) with
+ | Dispose -> clean acc stk
+ | Keep o' ->
+ clean (substl, (oname,Leaf o')::keepl, anticipl) stk
+ | Substitute o' ->
+ clean ((oname,Leaf o')::substl, keepl, anticipl) stk
+ | Anticipate o' ->
+ clean (substl, keepl, (oname,Leaf o')::anticipl) stk)
+ | (oname,ClosedSection _ as item) :: stk -> clean acc stk
+ | (_,OpenedSection _) :: _ -> error "there are still opened sections"
+ | (_,OpenedModule _) :: _ -> error "there are still opened modules"
+ | (_,OpenedModtype _) :: _ -> error "there are still opened module types"
+ | (_,FrozenState _) :: stk -> clean acc stk
+ in
+ clean ([],[],[]) (List.rev seg)
+
+let export_segment seg =
+ let rec clean acc = function
+ | (_,CompilingModule _) :: _ | [] -> acc
+ | (oname,Leaf o) as node :: stk ->
+ (match export_object o with
+ | None -> clean acc stk
+ | Some o' -> clean ((oname,Leaf o') :: acc) stk)
+ | (oname,ClosedSection _ as item) :: stk -> clean (item :: acc) stk
+ | (_,OpenedSection _) :: _ -> error "there are still opened sections"
+ | (_,OpenedModule _) :: _ -> error "there are still opened modules"
+ | (_,OpenedModtype _) :: _ -> error "there are still opened module types"
+ | (_,FrozenState _) :: stk -> clean acc stk
+ in
+ clean [] seg
+
+
+let start_module id mp nametab =
+ let dir = extend_dirpath (fst !path_prefix) id in
+ let prefix = dir,(mp,empty_dirpath) in
+ let oname = make_path id, make_kn id in
+ if Nametab.exists_module dir then
+ errorlabstrm "open_module" (pr_id id ++ str " already exists") ;
+ add_entry oname (OpenedModule (prefix,nametab));
+ path_prefix := prefix
+(* add_frozen_state () must be called in declaremods *)
+
+let end_module id =
+ let oname,nametab =
+ try match find_entry_p is_something_opened with
+ | oname,OpenedModule (_,nametab) ->
+ let sp = fst oname in
+ let id' = basename sp in
+ if id<>id' then error "this is not the last opened module";
+ oname,nametab
+ | _,OpenedModtype _ ->
+ error "there are some open module types"
+ | _,OpenedSection _ ->
+ error "there are some open sections"
+ | _ -> assert false
+ with Not_found ->
+ error "no opened modules"
+ in
+ let (after,_,before) = split_lib oname in
+ lib_stk := before;
+ let prefix = !path_prefix in
+ recalc_path_prefix ();
+ (* add_frozen_state must be called after processing the module,
+ because we cannot recache interactive modules *)
+ (oname, prefix, nametab,after)
+
+let start_modtype id mp nametab =
+ let dir = extend_dirpath (fst !path_prefix) id in
+ let prefix = dir,(mp,empty_dirpath) in
+ let sp = make_path id in
+ let name = sp, make_kn id in
+ if Nametab.exists_cci sp then
+ errorlabstrm "open_modtype" (pr_id id ++ str " already exists") ;
+ add_entry name (OpenedModtype (prefix,nametab));
+ path_prefix := prefix
+
+let end_modtype id =
+ let sp,nametab =
+ try match find_entry_p is_something_opened with
+ | sp,OpenedModtype (_,nametab) ->
+ let id' = basename (fst sp) in
+ if id<>id' then error "this is not the last opened module";
+ sp,nametab
+ | _,OpenedModule _ ->
+ error "there are some open modules"
+ | _,OpenedSection _ ->
+ error "there are some open sections"
+ | _ -> assert false
+ with Not_found ->
+ error "no opened module types"
+ in
+ let (after,_,before) = split_lib sp in
+ lib_stk := before;
+ let dir = !path_prefix in
+ recalc_path_prefix ();
+ (* add_frozen_state must be called after processing the module type.
+ This is because we cannot recache interactive module types *)
+ (sp,dir,nametab,after)
+
+
+
let contents_after = function
| None -> !lib_stk
| Some sp -> let (after,_,_) = split_lib sp in after
(* Modules. *)
-let check_for_module () =
+let check_for_comp_unit () =
let is_decl = function (_,FrozenState _) -> false | _ -> true in
try
let _ = find_entry_p is_decl in
- error "a module can not be started after some declarations"
+ error "a module cannot be started after some declarations"
with Not_found -> ()
(* TODO: use check_for_module ? *)
-let start_module s =
- if !module_name <> None then
- error "a module is already started";
- if !path_prefix <> default_module then
+let start_compilation s mp =
+ if !comp_name <> None then
+ error "compilation unit is already started";
+ if snd (snd (!path_prefix)) <> empty_dirpath then
error "some sections are already opened";
- module_name := Some s;
- let _ = add_anonymous_entry (Module s) in
- path_prefix := s
-
-let end_module s =
- match !module_name with
- | None -> error "no module declared"
- | Some m ->
- let (_,bm) = split_dirpath m in
- if bm <> s then
- error ("The current open module has basename "^(string_of_id bm));
- m
+ let prefix = s, (mp, empty_dirpath) in
+ let _ = add_anonymous_entry (CompilingModule prefix) in
+ comp_name := Some s;
+ path_prefix := prefix
+
+let end_compilation dir =
+ let _ =
+ try match find_entry_p is_something_opened with
+ | _, OpenedSection _ -> error "There are some open sections"
+ | _, OpenedModule _ -> error "There are some open modules"
+ | _, OpenedModtype _ -> error "There are some open module types"
+ | _ -> assert false
+ with
+ Not_found -> ()
+ in
+ let module_p =
+ function (_,CompilingModule _) -> true | x -> is_something_opened x
+ in
+ let oname =
+ try match find_entry_p module_p with
+ (oname, CompilingModule prefix) -> oname
+ | _ -> assert false
+ with
+ Not_found -> anomaly "No module declared"
+ in
+ let _ = match !comp_name with
+ | None -> anomaly "There should be a module name..."
+ | Some m ->
+ if m <> dir then anomaly
+ ("The current open module has name "^ (string_of_dirpath m) ^
+ " and not " ^ (string_of_dirpath m));
+ in
+ let (after,_,before) = split_lib oname in
+ !path_prefix,after
+
+(* Returns true if we are inside an opened module type *)
+let is_specification () =
+ let opened_p = function
+ | _, OpenedModtype _ -> true
+ | _ -> false
+ in
+ try
+ let _ = find_entry_p opened_p in true
+ with
+ Not_found -> false
+
+(* Returns the most recent OpenedThing node *)
+let what_is_opened () = find_entry_p is_something_opened
(* Sections. *)
let open_section id =
- let dir = extend_dirpath !path_prefix id in
- let sp = make_path id in
+ let olddir,(mp,oldsec) = !path_prefix in
+ let dir = extend_dirpath olddir id in
+ let prefix = dir, (mp, extend_dirpath oldsec id) in
+ let name = make_path id, make_kn id (* this makes little sense however *) in
if Nametab.exists_section dir then
errorlabstrm "open_section" (pr_id id ++ str " already exists");
let sum = freeze_summaries() in
- add_entry sp (OpenedSection (dir, sum));
+ add_entry name (OpenedSection (prefix, sum));
(*Pushed for the lifetime of the section: removed by unfrozing the summary*)
- Nametab.push_section dir;
- path_prefix := dir;
- sp
-
-let is_opened_section = function (_,OpenedSection _) -> true | _ -> false
+ Nametab.push_dir (Nametab.Until 1) dir (DirOpenSection prefix);
+ path_prefix := prefix;
+ prefix
let sections_are_opened () =
- try let _ = find_entry_p is_opened_section in true
+ try
+ match find_entry_p is_something_opened with
+ | (_,OpenedSection _) -> true
+ | (_,OpenedModule _) -> false
+ | _ -> false
with Not_found -> false
-let export_segment seg =
- let rec clean acc = function
- | (_,Module _) :: _ | [] -> acc
- | (sp,Leaf o) as node :: stk ->
- (match export_object o with
- | None -> clean acc stk
- | Some o' -> clean ((sp,Leaf o') :: acc) stk)
- | (sp,ClosedSection _ as item) :: stk -> clean (item :: acc) stk
- | (_,OpenedSection _) :: _ -> error "there are still opened sections"
- | (_,FrozenState _) :: stk -> clean acc stk
- in
- clean [] seg
-
(* Restore lib_stk and summaries as before the section opening, and
add a ClosedSection object. *)
let close_section ~export id =
- let sp,dir,fs =
- try match find_entry_p is_opened_section with
- | sp,OpenedSection (dir,fs) ->
- if id<>snd(split_dirpath dir) then
+ let oname,fs =
+ try match find_entry_p is_something_opened with
+ | oname,OpenedSection (_,fs) ->
+ if id <> basename (fst oname) then
error "this is not the last opened section";
- (sp,dir,fs)
- | _ -> assert false
+ (oname,fs)
+ | _ -> assert false
with Not_found ->
error "no opened section"
in
- let (after,_,before) = split_lib sp in
+ let (after,_,before) = split_lib oname in
lib_stk := before;
+ let prefix = !path_prefix in
pop_path_prefix ();
- let closed_sec = ClosedSection (export, dir, export_segment after) in
- add_entry (make_path id) closed_sec;
- (dir,after,fs)
-
-(* The following function exports the whole library segment, that will be
- saved as a module. Objects are presented in chronological order, and
- frozen states are removed. *)
-
-let export_module s =
- export_segment !lib_stk
+ let closed_sec =
+ ClosedSection (export, (fst prefix), export_segment after)
+ in
+ let name = make_path id, make_kn id in
+ add_entry name closed_sec;
+ (prefix, after, fs)
(* Backtracking. *)
@@ -207,6 +452,7 @@ let recache_decl = function
| (sp, Leaf o) -> cache_object (sp,o)
| _ -> ()
+
let recache_context ctx =
List.iter recache_decl ctx
@@ -226,21 +472,16 @@ let reset_to sp =
let reset_name id =
let (sp,_) =
try
- find_entry_p (fun (sp,_) -> let (_,spi) = repr_path sp in id = spi)
+ find_entry_p (fun (sp,_) -> let (_,spi) = repr_path (fst sp) in id = spi)
with Not_found ->
error (string_of_id id ^ ": no such entry")
in
reset_to sp
let point_obj =
- let (f,_) =
- declare_object
- ("DOT",
- {cache_function = (fun _ -> ());
- load_function = (fun _ -> ());
- open_function = (fun _ -> ());
- export_function = (fun _ -> None) }) in
- f()
+ let (f,_) = declare_object {(default_object "DOT") with
+ classify_function = (fun _ -> Dispose)} in
+ f()
let mark_end_of_command () =
match !lib_stk with
@@ -258,41 +499,41 @@ let back n = reset_to (back_stk n !lib_stk)
(* [dir] is a section dir if [module] < [dir] <= [path_prefix] *)
let is_section_p sp =
- not (is_dirpath_prefix_of sp (module_sp ()))
- & (is_dirpath_prefix_of sp !path_prefix)
+ not (is_dirpath_prefix_of sp (module_dp ()))
+ & (is_dirpath_prefix_of sp (fst !path_prefix))
(* State and initialization. *)
type frozen = dir_path option * library_segment
-let freeze () = (!module_name, !lib_stk)
+let freeze () = (!comp_name, !lib_stk)
let unfreeze (mn,stk) =
- module_name := mn;
+ comp_name := mn;
lib_stk := stk;
recalc_path_prefix ()
let init () =
lib_stk := [];
add_frozen_state ();
- module_name := None;
- path_prefix := make_dirpath [];
+ comp_name := None;
+ path_prefix := initial_prefix;
init_summaries()
(* Initial state. *)
-let initial_state = ref (None : section_path option)
+let initial_state = ref None
let declare_initial_state () =
- let sp = add_anonymous_entry (FrozenState (freeze_summaries())) in
- initial_state := Some sp
+ let name = add_anonymous_entry (FrozenState (freeze_summaries())) in
+ initial_state := Some name
let reset_initial () =
match !initial_state with
| None -> init ()
| Some sp ->
begin match split_lib sp with
- | (_,(_,FrozenState fs as hd),before) ->
+ | (_,[_,FrozenState fs as hd],before) ->
lib_stk := hd::before;
recalc_path_prefix ();
unfreeze_summaries fs