aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Pierre-Marie Pédrot <pierre-marie.pedrot@inria.fr>2014-02-15 20:21:36 +0100
committerGravatar Pierre-Marie Pédrot <pierre-marie.pedrot@inria.fr>2014-05-12 14:01:10 +0200
commit9f8d5a9bcae4c4ca4d761e7ae0c2fdc99bcb1340 (patch)
tree9094c01899d2aa73e3ff8cdb31fd2148a131b72f
parentb6a68f67897819db729e43c1d9b6ecf2c3c77407 (diff)
Adding the possibility for ML modules to declare functions to be called at
caching time, i.e. when the Declare ML Module command is evaluated. This can be used by both static and dynamic plugins.
-rw-r--r--toplevel/mltop.ml50
-rw-r--r--toplevel/mltop.mli23
2 files changed, 56 insertions, 17 deletions
diff --git a/toplevel/mltop.ml b/toplevel/mltop.ml
index 196ab98ed..11f00d6e5 100644
--- a/toplevel/mltop.ml
+++ b/toplevel/mltop.ml
@@ -264,6 +264,21 @@ let add_known_plugin init name =
let init_known_plugins () =
String.Map.iter (fun _ f -> f()) !known_loaded_plugins
+(** Registering functions to be used at caching time, that is when the Declare
+ ML module command is issued. *)
+
+let cache_objs = ref String.Map.empty
+
+let declare_cache_obj f name =
+ let objs = try String.Map.find name !cache_objs with Not_found -> [] in
+ let objs = f :: objs in
+ cache_objs := String.Map.add name objs !cache_objs
+
+let perform_cache_obj name =
+ let objs = try String.Map.find name !cache_objs with Not_found -> [] in
+ let objs = List.rev objs in
+ List.iter (fun f -> f ()) objs
+
(** ml object = ml module or plugin *)
let init_ml_object mname =
@@ -299,21 +314,23 @@ let if_verbose_load verb f name fname =
or simulate its reload (i.e. doing nothing except maybe
an initialization function). *)
-let cache_ml_object verb reinit name =
- begin
- if module_is_known name then
- (if reinit then init_ml_object name)
- else if not has_dynlink then
- error ("Dynamic link not supported (module "^name^")")
- else
- if_verbose_load (verb && is_verbose ())
- load_ml_object name (file_of_name name)
- end;
- add_loaded_module name
+let trigger_ml_object verb cache reinit name =
+ if module_is_known name then begin
+ if reinit then init_ml_object name;
+ add_loaded_module name;
+ if cache then perform_cache_obj name
+ end else if not has_dynlink then
+ error ("Dynamic link not supported (module "^name^")")
+ else begin
+ let file = file_of_name name in
+ if_verbose_load (verb && is_verbose ()) load_ml_object name file;
+ add_loaded_module name;
+ if cache then perform_cache_obj name
+ end
let unfreeze_ml_modules x =
reset_loaded_modules ();
- List.iter (cache_ml_object false false) x
+ List.iter (trigger_ml_object false false false) x
let _ =
Summary.declare_summary Summary.ml_modules
@@ -329,7 +346,12 @@ type ml_module_object = {
}
let cache_ml_objects (_,{mnames=mnames}) =
- List.iter (cache_ml_object true true) mnames
+ let iter obj = trigger_ml_object true true true obj in
+ List.iter iter mnames
+
+let load_ml_objects _ (_,{mnames=mnames}) =
+ let iter obj = trigger_ml_object true false true obj in
+ List.iter iter mnames
let classify_ml_objects ({mlocal=mlocal} as o) =
if mlocal then Dispose else Substitute o
@@ -337,8 +359,8 @@ let classify_ml_objects ({mlocal=mlocal} as o) =
let inMLModule : ml_module_object -> obj =
declare_object
{(default_object "ML-MODULE") with
- load_function = (fun _ -> cache_ml_objects);
cache_function = cache_ml_objects;
+ load_function = load_ml_objects;
subst_function = (fun (_,o) -> o);
classify_function = classify_ml_objects }
diff --git a/toplevel/mltop.mli b/toplevel/mltop.mli
index 19b999631..196c0bf94 100644
--- a/toplevel/mltop.mli
+++ b/toplevel/mltop.mli
@@ -6,6 +6,8 @@
(* * GNU Lesser General Public License Version 2.1 *)
(************************************************************************)
+(** {5 Toplevel management} *)
+
(** If there is a toplevel under Coq, it is described by the following
record. *)
type toplevel = {
@@ -26,12 +28,14 @@ val remove : unit -> unit
(** Tests if an Ocaml toplevel runs under Coq *)
val is_ocaml_top : unit -> bool
-(** Tests if we can load ML files *)
-val has_dynlink : bool
-
(** Starts the Ocaml toplevel loop *)
val ocaml_toploop : unit -> unit
+(** {5 ML Dynlink} *)
+
+(** Tests if we can load ML files *)
+val has_dynlink : bool
+
(** Dynamic loading of .cmo *)
val dir_ml_load : string -> unit
@@ -51,6 +55,8 @@ val add_known_module : string -> unit
val module_is_known : string -> bool
val load_ml_object : string -> string -> unit
+(** {5 Initialization functions} *)
+
(** Declare a plugin and its initialization function.
A plugin is just an ML module with an initialization function.
Adding a known plugin implies adding it as a known ML module.
@@ -61,8 +67,19 @@ val add_known_plugin : (unit -> unit) -> string -> unit
(** Calls all initialization functions in a non-specified order *)
val init_known_plugins : unit -> unit
+(** Register a callback that will be called when the module is declared with
+ the Declare ML Module command. This is useful to define Coq objects at that
+ time only. Several functions can be defined for one module; they will be
+ called in the order of declaration, and after the ML module has been
+ properly initialized. *)
+val declare_cache_obj : (unit -> unit) -> string -> unit
+
+(** {5 Declaring modules} *)
+
val declare_ml_modules : Vernacexpr.locality_flag -> string list -> unit
+(** {5 Utilities} *)
+
val print_ml_path : unit -> Pp.std_ppcmds
val print_ml_modules : unit -> Pp.std_ppcmds
val print_gc : unit -> Pp.std_ppcmds