summaryrefslogtreecommitdiff
path: root/library/lib.ml
diff options
context:
space:
mode:
authorGravatar Stephane Glondu <steph@glondu.net>2013-05-08 18:03:54 +0200
committerGravatar Stephane Glondu <steph@glondu.net>2013-05-08 18:03:54 +0200
commitdb38bb4ad9aff74576d3b7f00028d48f0447d5bd (patch)
tree09dafc3e5c7361d3a28e93677eadd2b7237d4f9f /library/lib.ml
parent6e34b272d789455a9be589e27ad3a998cf25496b (diff)
parent499a11a45b5711d4eaabe84a80f0ad3ae539d500 (diff)
Merge branch 'experimental/upstream' into upstream
Diffstat (limited to 'library/lib.ml')
-rw-r--r--library/lib.ml336
1 files changed, 96 insertions, 240 deletions
diff --git a/library/lib.ml b/library/lib.ml
index 6f8655d3..44a3c973 100644
--- a/library/lib.ml
+++ b/library/lib.ml
@@ -1,26 +1,26 @@
(************************************************************************)
(* v * The Coq Proof Assistant / The Coq Development Team *)
-(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2011 *)
+(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2012 *)
(* \VV/ **************************************************************)
(* // * This file is distributed under the terms of the *)
(* * GNU Lesser General Public License Version 2.1 *)
(************************************************************************)
-(* $Id: lib.ml 14641 2011-11-06 11:59:10Z herbelin $ *)
-
open Pp
open Util
open Libnames
open Nameops
open Libobject
open Summary
+
+type is_type = bool (* Module Type or just Module *)
+type export = bool option (* None for a Module Type *)
+
type node =
| Leaf of obj
| CompilingLibrary of object_prefix
- | OpenedModule of bool option * object_prefix * Summary.frozen
+ | OpenedModule of is_type * export * object_prefix * Summary.frozen
| ClosedModule of library_segment
- | OpenedModtype of object_prefix * Summary.frozen
- | ClosedModtype of library_segment
| OpenedSection of object_prefix * Summary.frozen
| ClosedSection of library_segment
| FrozenState of Summary.frozen
@@ -31,6 +31,9 @@ and library_segment = library_entry list
type lib_objects = (Names.identifier * obj) list
+let module_kind is_type =
+ if is_type then "module type" else "module"
+
let iter_objects f i prefix =
List.iter (fun (id,obj) -> f i (make_oname prefix id, obj))
@@ -69,10 +72,9 @@ let classify_segment seg =
(* LEM; TODO: Understand what this does and see if what I do is the
correct thing for ClosedMod(ule|type) *)
| (_,ClosedModule _) :: stk -> clean acc stk
- | (_,ClosedModtype _) :: 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"
+ | (_,OpenedModule (ty,_,_,_)) :: _ ->
+ error ("there are still opened " ^ module_kind ty ^"s")
| (_,FrozenState _) :: stk -> clean acc stk
in
clean ([],[],[]) (List.rev seg)
@@ -144,8 +146,7 @@ let make_oname id = make_path id, make_kn id
let recalc_path_prefix () =
let rec recalc = function
| (sp, OpenedSection (dir,_)) :: _ -> dir
- | (sp, OpenedModule (_,dir,_)) :: _ -> dir
- | (sp, OpenedModtype (dir,_)) :: _ -> dir
+ | (sp, OpenedModule (_,_,dir,_)) :: _ -> dir
| (sp, CompilingLibrary dir) :: _ -> dir
| _::l -> recalc l
| [] -> initial_prefix
@@ -181,7 +182,6 @@ let split_lib_gen test =
then Some (collect after [hd] before)
else (match hd with
| (sp,ClosedModule seg)
- | (sp,ClosedModtype seg)
| (sp,ClosedSection seg) ->
(match findeq after seg with
| None -> findeq (hd::after) before
@@ -197,11 +197,11 @@ let split_lib_gen test =
let split_lib sp = split_lib_gen (fun x -> fst x = sp)
let split_lib_at_opening sp =
- let a,s,b = split_lib_gen (function
- | x,(OpenedSection _|OpenedModule _|OpenedModtype _|CompilingLibrary _) ->
- x = sp
- | _ ->
- false) in
+ let is_sp = function
+ | x,(OpenedSection _|OpenedModule _|CompilingLibrary _) -> x = sp
+ | _ -> false
+ in
+ let a,s,b = split_lib_gen is_sp in
assert (List.tl s = []);
(a,List.hd s,b)
@@ -254,97 +254,66 @@ let add_frozen_state () =
(* Modules. *)
-
-let is_opened id = function
- oname,(OpenedSection _ | OpenedModule _ | OpenedModtype _) when
- basename (fst oname) = id -> true
- | _ -> false
-
let is_opening_node = function
- _,(OpenedSection _ | OpenedModule _ | OpenedModtype _) -> true
+ | _,(OpenedSection _ | OpenedModule _) -> true
| _ -> false
+let is_opening_node_or_lib = function
+ | _,(CompilingLibrary _ | OpenedSection _ | OpenedModule _) -> true
+ | _ -> false
let current_mod_id () =
- try match find_entry_p is_opening_node with
- | oname,OpenedModule (_,_,fs) ->
- basename (fst oname)
- | oname,OpenedModtype (_,fs) ->
- basename (fst oname)
+ try match find_entry_p is_opening_node_or_lib with
+ | oname,OpenedModule (_,_,_,fs) -> basename (fst oname)
+ | oname,CompilingLibrary _ -> basename (fst oname)
| _ -> error "you are not in a module"
- with Not_found ->
- error "no opened modules"
+ with Not_found -> error "no opened modules"
-let start_module export id mp fs =
+let start_mod is_type export id mp fs =
let dir = add_dirpath_suffix (fst !path_prefix) id in
let prefix = dir,(mp,Names.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 (export,prefix,fs));
+ let sp = make_path id in
+ let oname = sp, make_kn id in
+ let exists =
+ if is_type then Nametab.exists_cci sp else Nametab.exists_module dir
+ in
+ if exists then
+ errorlabstrm "open_module" (pr_id id ++ str " already exists");
+ add_entry oname (OpenedModule (is_type,export,prefix,fs));
path_prefix := prefix;
prefix
(* add_frozen_state () must be called in declaremods *)
+let start_module = start_mod false
+let start_modtype = start_mod true None
+
let error_still_opened string oname =
let id = basename (fst oname) in
- errorlabstrm "" (str string ++ spc () ++ pr_id id ++ str " is still opened.")
+ errorlabstrm ""
+ (str ("The "^string^" ") ++ pr_id id ++ str " is still opened.")
-let end_module () =
+let end_mod is_type =
let oname,fs =
try match find_entry_p is_opening_node with
- | oname,OpenedModule (_,_,fs) -> oname,fs
- | oname,OpenedModtype _ -> error_still_opened "Module Type" oname
- | oname,OpenedSection _ -> error_still_opened "Section" oname
+ | oname,OpenedModule (ty,_,_,fs) ->
+ if ty = is_type then oname,fs
+ else error_still_opened (module_kind ty) oname
+ | oname,OpenedSection _ -> error_still_opened "section" oname
| _ -> assert false
- with Not_found ->
- error "No opened modules."
+ with Not_found -> error "No opened modules."
in
let (after,mark,before) = split_lib_at_opening oname in
lib_stk := before;
add_entry oname (ClosedModule (List.rev (mark::after)));
let prefix = !path_prefix in
- (* LEM: This module business seems more complicated than sections;
- shouldn't a backtrack into a closed module also do something
- with global.ml, given that closing a module does?
- TODO
- *)
recalc_path_prefix ();
(* add_frozen_state must be called after processing the module,
because we cannot recache interactive modules *)
(oname, prefix, fs, after)
-let start_modtype id mp fs =
- let dir = add_dirpath_suffix (fst !path_prefix) id in
- let prefix = dir,(mp,Names.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,fs));
- path_prefix := prefix;
- prefix
-
-let end_modtype () =
- let oname,fs =
- try match find_entry_p is_opening_node with
- | oname,OpenedModtype (_,fs) -> oname,fs
- | oname,OpenedModule _ -> error_still_opened "Module" oname
- | oname,OpenedSection _ -> error_still_opened "Section" oname
- | _ -> assert false
- with Not_found ->
- error "no opened module types"
- in
- let (after,mark,before) = split_lib_at_opening oname in
- lib_stk := before;
- add_entry oname (ClosedModtype (List.rev (mark::after)));
- 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 *)
- (oname,dir,fs,after)
-
+let end_module () = end_mod false
+let end_modtype () = end_mod true
let contents_after = function
| None -> !lib_stk
@@ -352,13 +321,6 @@ let contents_after = function
(* Modules. *)
-let check_for_comp_unit () =
- let is_decl = function (_,FrozenState _) -> false | _ -> true in
- try
- let _ = find_entry_p is_decl in
- error "a module cannot be started after some declarations"
- with Not_found -> ()
-
(* TODO: use check_for_module ? *)
let start_compilation s mp =
if !comp_name <> None then
@@ -374,21 +336,18 @@ let end_compilation dir =
let _ =
try match snd (find_entry_p is_opening_node) with
| OpenedSection _ -> error "There are some open sections."
- | OpenedModule _ -> error "There are some open modules."
- | OpenedModtype _ -> error "There are some open module types."
+ | OpenedModule (ty,_,_,_) ->
+ error ("There are some open "^module_kind ty^"s.")
| _ -> assert false
- with
- Not_found -> ()
+ with Not_found -> ()
in
- let module_p =
- function (_,CompilingLibrary _) -> true | x -> is_opening_node x
+ let is_opening_lib = function _,CompilingLibrary _ -> true | _ -> false
in
let oname =
- try match find_entry_p module_p with
- (oname, CompilingLibrary prefix) -> oname
+ try match find_entry_p is_opening_lib with
+ | (oname, CompilingLibrary prefix) -> oname
| _ -> assert false
- with
- Not_found -> anomaly "No module declared"
+ with Not_found -> anomaly "No module declared"
in
let _ =
match !comp_name with
@@ -399,31 +358,23 @@ let end_compilation dir =
" and not " ^ (Names.string_of_dirpath m));
in
let (after,mark,before) = split_lib_at_opening oname in
- comp_name := None;
- !path_prefix,after
+ comp_name := None;
+ !path_prefix,after
-(* Returns true if we are inside an opened module type *)
-let is_modtype () =
- let opened_p = function
- | _, OpenedModtype _ -> true
- | _ -> false
- in
- try
- let _ = find_entry_p opened_p in true
- with
- Not_found -> false
-
-(* Returns true if we are inside an opened module *)
-let is_module () =
- let opened_p = function
- | _, OpenedModule _ -> true
+(* Returns true if we are inside an opened module or module type *)
+
+let is_module_gen which =
+ let test = function
+ | _, OpenedModule (ty,_,_,_) -> which ty
| _ -> false
in
- try
- let _ = find_entry_p opened_p in true
- with
- Not_found -> false
+ try
+ let _ = find_entry_p test in true
+ with Not_found -> false
+let is_module_or_modtype () = is_module_gen (fun _ -> true)
+let is_modtype () = is_module_gen (fun b -> b)
+let is_module () = is_module_gen (fun b -> not b)
(* Returns the opening node of a given name *)
let find_opening_node id =
@@ -495,8 +446,6 @@ let add_section_constant kn =
let replacement_context () = pi2 (List.hd !sectab)
-let variables_context () = pi1 (List.hd !sectab)
-
let section_segment_of_constant con =
Names.Cmap.find con (fst (pi3 (List.hd !sectab)))
@@ -563,8 +512,8 @@ let discharge_item ((sp,_ as oname),e) =
| Leaf lobj ->
Option.map (fun o -> (basename sp,o)) (discharge_object (oname,lobj))
| FrozenState _ -> None
- | ClosedSection _ | ClosedModtype _ | ClosedModule _ -> None
- | OpenedSection _ | OpenedModtype _ | OpenedModule _ | CompilingLibrary _ ->
+ | ClosedSection _ | ClosedModule _ -> None
+ | OpenedSection _ | OpenedModule _ | CompilingLibrary _ ->
anomaly "discharge_item"
let close_section () =
@@ -590,8 +539,8 @@ let close_section () =
(*****************)
(* Backtracking. *)
-let (inLabel,outLabel) =
- declare_object {(default_object "DOT") with
+let (inLabel : int -> obj), (outLabel : obj -> int) =
+ declare_object_full {(default_object "DOT") with
classify_function = (fun _ -> Dispose)}
let recache_decl = function
@@ -604,13 +553,6 @@ let recache_context ctx =
let is_frozen_state = function (_,FrozenState _) -> true | _ -> false
-let has_top_frozen_state () =
- let rec aux = function
- | (sp, FrozenState _)::_ -> Some sp
- | (sp, Leaf o)::t when object_tag o = "DOT" -> aux t
- | _ -> None
- in aux !lib_stk
-
let set_lib_stk new_lib_stk =
lib_stk := new_lib_stk;
recalc_path_prefix ();
@@ -630,106 +572,43 @@ let reset_to_gen test =
let reset_to sp = reset_to_gen (fun x -> fst x = sp)
-let reset_to_state sp =
- let (_,eq,before) = split_lib sp in
- (* if eq a frozen state, we'll reset to it *)
- match eq with
- | [_,FrozenState f] -> lib_stk := eq@before; recalc_path_prefix (); unfreeze_summaries f
- | _ -> error "Not a frozen state"
-
-
-(* LEM: TODO
- * We will need to muck with frozen states in after, too!
- * Not only FrozenState, but also those embedded in Opened(Section|Module|Modtype)
- *)
-let delete_gen test =
- let (after,equal,before) = split_lib_gen test in
- let rec chop_at_dot = function
- | [] as l -> l
- | (_, Leaf o)::t when object_tag o = "DOT" -> t
- | _::t -> chop_at_dot t
- and chop_before_dot = function
- | [] as l -> l
- | (_, Leaf o)::t as l when object_tag o = "DOT" -> l
- | _::t -> chop_before_dot t
- in
- set_lib_stk (List.rev_append (chop_at_dot after) (chop_before_dot before))
-
-let delete sp = delete_gen (fun x -> fst x = sp)
-
-let reset_name (loc,id) =
- let (sp,_) =
- try
- find_entry_p (fun (sp,_) -> let (_,spi) = repr_path (fst sp) in id = spi)
- with Not_found ->
- user_err_loc (loc,"reset_name",pr_id id ++ str ": no such entry")
- in
- reset_to sp
-
-let remove_name (loc,id) =
- let (sp,_) =
- try
- find_entry_p (fun (sp,_) -> let (_,spi) = repr_path (fst sp) in id = spi)
- with Not_found ->
- user_err_loc (loc,"remove_name",pr_id id ++ str ": no such entry")
- in
- delete sp
-
-let is_mod_node = function
- | OpenedModule _ | OpenedModtype _ | OpenedSection _
- | ClosedModule _ | ClosedModtype _ | ClosedSection _ -> true
- | Leaf o -> let t = object_tag o in t = "MODULE" || t = "MODULE TYPE"
- || t = "MODULE ALIAS"
- | _ -> false
-
-(* Reset on a module or section name in order to bypass constants with
- the same name *)
+let first_command_label = 1
-let reset_mod (loc,id) =
- let (_,before) =
- try
- find_split_p (fun (sp,node) ->
- let (_,spi) = repr_path (fst sp) in id = spi
- && is_mod_node node)
- with Not_found ->
- user_err_loc (loc,"reset_mod",pr_id id ++ str ": no such entry")
- in
- set_lib_stk before
-
-let mark_end_of_command, current_command_label, set_command_label =
- let n = ref 0 in
+let mark_end_of_command, current_command_label, reset_command_label =
+ let n = ref (first_command_label-1) in
(fun () ->
match !lib_stk with
(_,Leaf o)::_ when object_tag o = "DOT" -> ()
| _ -> incr n;add_anonymous_leaf (inLabel !n)),
(fun () -> !n),
- (fun x -> n:=x)
+ (fun x -> n:=x;add_anonymous_leaf (inLabel x))
let is_label_n n x =
match x with
| (sp,Leaf o) when object_tag o = "DOT" && n = outLabel o -> true
| _ -> false
-(* Reset the label registered by [mark_end_of_command()] with number n. *)
-let reset_label n =
- let current = current_command_label() in
- if n < current then
- let res = reset_to_gen (is_label_n n) in
- set_command_label (n-1); (* forget state numbers after n only if reset succeeded *)
- res
- else (* optimisation to avoid recaching when not necessary (why is it so long??) *)
- match !lib_stk with
- | [] -> ()
- | x :: ls -> (lib_stk := ls;set_command_label (n-1))
-
-let rec back_stk n stk =
- match stk with
- (sp,Leaf o)::tail when object_tag o = "DOT" ->
- if n=0 then sp else back_stk (n-1) tail
- | _::tail -> back_stk n tail
- | [] -> error "Reached begin of command history"
+(** Reset the label registered by [mark_end_of_command()] with number n,
+ which should be strictly in the past. *)
-let back n = reset_to (back_stk n !lib_stk)
+let reset_label n =
+ if n >= current_command_label () then
+ error "Cannot backtrack to the current label or a future one";
+ reset_to_gen (is_label_n n);
+ (* forget state numbers after n only if reset succeeded *)
+ reset_command_label n
+
+(** Search the last label registered before defining [id] *)
+
+let label_before_name (loc,id) =
+ let found = ref false in
+ let search = function
+ | (_,Leaf o) when !found && object_tag o = "DOT" -> true
+ | (sp,_) -> (if id = snd (repr_path (fst sp)) then found := true); false
+ in
+ match find_entry_p search with
+ | (_,Leaf o) -> outLabel o
+ | _ -> raise Not_found
(* State and initialization. *)
@@ -749,29 +628,6 @@ let init () =
path_prefix := initial_prefix;
init_summaries()
-(* Initial state. *)
-
-let initial_state = ref None
-
-let declare_initial_state () =
- let name = add_anonymous_entry (FrozenState (freeze_summaries())) in
- initial_state := Some name
-
-let reset_initial () =
- match !initial_state with
- | None ->
- error "Resetting to the initial state is possible only interactively"
- | Some sp ->
- begin match split_lib sp with
- | (_,[_,FrozenState fs as hd],before) ->
- lib_stk := hd::before;
- recalc_path_prefix ();
- set_command_label 0;
- unfreeze_summaries fs
- | _ -> assert false
- end
-
-
(* Misc *)
let mp_of_global ref =
@@ -793,7 +649,7 @@ let rec split_mp mp =
| Names.MPdot (prfx, lbl) ->
let mprec, dprec = split_mp prfx in
mprec, Names.make_dirpath (Names.id_of_string (Names.string_of_label lbl) :: (Names.repr_dirpath dprec))
- | Names.MPbound mbid -> let (_, id, dp) = Names.repr_mbid mbid in library_dp(), Names.make_dirpath [Names.id_of_string id]
+ | Names.MPbound mbid -> let (_, id, dp) = Names.repr_mbid mbid in library_dp(), Names.make_dirpath [id]
let split_modpath mp =
let rec aux = function