]> matita.cs.unibo.it Git - helm.git/blobdiff - matita/components/ng_library/nCicLibrary.ml
nCicLibrary
[helm.git] / matita / components / ng_library / nCicLibrary.ml
index ae6666be581fbae322e84226e43708be8cbc54b9..e2e7d1b34054a0448950d75596034a14019cceaa 100644 (file)
@@ -25,27 +25,30 @@ let refresh_uri_in_universe =
 let refresh_uri_in_reference (NReference.Ref (uri,spec)) =
  NReference.reference_of_spec (refresh_uri uri) spec
 
-let rec refresh_uri_in_term =
- function
+let refresh_uri_in_term status =
+ let rec aux =
+  function
   | NCic.Meta (i,(n,NCic.Ctx l)) ->
-     NCic.Meta (i,(n,NCic.Ctx (List.map refresh_uri_in_term l)))
+     NCic.Meta (i,(n,NCic.Ctx (List.map aux l)))
   | NCic.Meta _ as t -> t
   | NCic.Const ref -> NCic.Const (refresh_uri_in_reference ref)
   | NCic.Sort (NCic.Type l) -> NCic.Sort (NCic.Type (refresh_uri_in_universe l))
   | NCic.Match (NReference.Ref (uri,spec),outtype,term,pl) ->
      let r = NReference.reference_of_spec (refresh_uri uri) spec in
-     let outtype = refresh_uri_in_term outtype in
-     let term = refresh_uri_in_term term in
-     let pl = List.map refresh_uri_in_term pl in
+     let outtype = aux outtype in
+     let term = aux term in
+     let pl = List.map aux pl in
       NCic.Match (r,outtype,term,pl)
-  | t -> NCicUtils.map (fun _ _ -> ()) () (fun _ -> refresh_uri_in_term) t
+  | t -> NCicUtils.map status (fun _ _ -> ()) () (fun _ -> aux) t
+in
+ aux
 ;;
 
-let refresh_uri_in_obj (uri,height,metasenv,subst,obj_kind) =
+let refresh_uri_in_obj status (uri,height,metasenv,subst,obj_kind) =
  assert (metasenv = []);
  assert (subst = []);
  refresh_uri uri,height,metasenv,subst,
-  NCicUntrusted.map_obj_kind refresh_uri_in_term obj_kind
+  NCicUntrusted.map_obj_kind (refresh_uri_in_term status) obj_kind
 ;;
 
 let ng_path_of_baseuri ?(no_suffix=false) baseuri =
@@ -77,18 +80,12 @@ let db_path () = Helm_registry.get "matita.basedir" ^ "/ng_db.ng";;
 type timestamp =
  [ `Obj of NUri.uri * NCic.obj 
  | `Constr of NCic.universe * NCic.universe] list *
- (NUri.uri * string * NReference.reference) list *
- NCic.obj NUri.UriMap.t *
- NUri.uri list
+ (NUri.uri * string * NReference.reference) list
 ;;
 
-let time0 = [],[],NUri.UriMap.empty,[];;
+let time0 = [],[];;
 let storage = ref [];;
 let local_aliases = ref [];;
-let cache = ref NUri.UriMap.empty;;
-let includes = ref [];;
-
-let get_already_included () = !includes;;
 
 let load_db,set_global_aliases,get_global_aliases,add_deps,get_deps,remove_deps=
  let global_aliases = ref [] in
@@ -147,48 +144,67 @@ let load_db,set_global_aliases,get_global_aliases,add_deps,get_deps,remove_deps=
 
 let init = load_db;;
 
-class status =
+class virtual status =
  object
+  inherit NCic.status
   val timestamp = (time0 : timestamp)
   method timestamp = timestamp
   method set_timestamp v = {< timestamp = v >}
  end
 
-let time_travel status =
- let sto,ali,cac,inc = status#timestamp in
-  let diff_len = List.length !storage - List.length sto in
-  let to_be_deleted,_ = HExtlib.split_nth diff_len !storage in
-   if List.length to_be_deleted > 0 then
-     NCicEnvironment.invalidate_item (HExtlib.list_last to_be_deleted);
-   storage := sto; local_aliases := ali; cache := cac; includes := inc
+let time_travel0 (sto,ali) =
+ let diff_len = List.length !storage - List.length sto in
+ let to_be_deleted,_ = HExtlib.split_nth diff_len !storage in
+  if List.length to_be_deleted > 0 then
+   List.iter NCicEnvironment.invalidate_item to_be_deleted;
+  storage := sto; local_aliases := ali
 ;;
 
-let serialize ~baseuri ~dependencies dump =
- let ch = open_out (ng_path_of_baseuri baseuri) in
- Marshal.to_channel ch (magic,(dependencies,dump)) [];
- close_out ch;
- List.iter
-  (function 
-   | `Obj (uri,obj) ->
-       let ch = open_out (ng_path_of_baseuri uri) in
-       Marshal.to_channel ch (magic,obj) [];
-       close_out ch
-   | `Constr _ -> ()
-  ) !storage;
- set_global_aliases (!local_aliases @ get_global_aliases ());
- List.iter (fun u -> add_deps u [baseuri]) !includes;
- time_travel (new status)
+let time_travel status = time_travel0 status#timestamp;;
+
+let replace status =
+ let sto,ali = status#timestamp in
+  storage := sto; local_aliases := ali
 ;;
-  
+
 type obj = string * Obj.t
+(* includes are transitively closed; dependencies are only immediate *)
+type dump =
+ { objs: obj list ; includes: NUri.uri list; dependencies: string list }
+
+class type g_dumpable_status =
+ object
+  method dump: dump
+ end
 
 class dumpable_status =
  object
-  val dump = ([] : obj list)
-  method dump = dump
-  method set_dump v = {< dump = v >}
+  val db = { objs = []; includes = []; dependencies = [] }
+  method dump = db
+  method set_dump v = {< db = v >}
+  method set_dumpable_status
+   : 'status. #g_dumpable_status as 'status -> 'self
+   = fun o -> {< db = o#dump >}
  end
 
+let get_transitively_included status =
+ status#dump.includes
+;;
+
+let dump_obj status obj =
+ status#set_dump {status#dump with objs = obj::status#dump.objs }
+;;
+
+let remove_objects ~baseuri =
+   let uri = NUri.string_of_uri baseuri in   
+   let path = String.sub uri 4 (String.length uri - 4) in
+   let path = Helm_registry.get "matita.basedir" ^ path in
+   let map name = Sys.remove (Filename.concat path name) in
+   if HExtlib.is_dir path && HExtlib.is_regular (path ^ ".ng") then begin
+      HLog.warn ("removing contents of baseuri: " ^ uri);
+      Array.iter map (Sys.readdir path)
+   end
+
 module type SerializerType =
  sig
   type dumpable_status
@@ -196,28 +212,31 @@ module type SerializerType =
   type 'a register_type =
    'a ->
     refresh_uri_in_universe:(NCic.universe -> NCic.universe) ->
-    refresh_uri_in_term:(NCic.term -> NCic.term) ->
+    refresh_uri_in_term:(NCic.status -> NCic.term -> NCic.term) ->
     refresh_uri_in_reference:(NReference.reference -> NReference.reference) ->
+    alias_only:bool ->
      dumpable_status -> dumpable_status
 
   val register: < run: 'a.  string -> 'a register_type -> ('a -> obj) >
-  val serialize: baseuri:NUri.uri -> dependencies:string list -> obj list -> unit
-   (* the obj is the "include" command to be added to the dump list *)
-  val require: baseuri:NUri.uri -> dumpable_status -> dumpable_status * obj
+  val serialize: baseuri:NUri.uri -> dumpable_status -> unit
+  val require:
+   baseuri:NUri.uri -> fname:string -> alias_only:bool ->
+    dumpable_status -> dumpable_status
   val dependencies_of: baseuri:NUri.uri -> string list
  end
 
-module Serializer(D: sig type dumpable_status end) =
+module Serializer(D: sig type dumpable_s = private #dumpable_status end) =
  struct
-  type dumpable_status = D.dumpable_status
+  type dumpable_status = D.dumpable_s
   type 'a register_type =
    'a ->
     refresh_uri_in_universe:(NCic.universe -> NCic.universe) ->
-    refresh_uri_in_term:(NCic.term -> NCic.term) ->
+    refresh_uri_in_term:(NCic.status -> NCic.term -> NCic.term) ->
     refresh_uri_in_reference:(NReference.reference -> NReference.reference) ->
+    alias_only:bool ->
      dumpable_status -> dumpable_status
 
-  let require1 = ref (fun _ -> assert false) (* unknown data*)
+  let require1 = ref (fun ~alias_only:_ _ -> assert false) (* unknown data*)
   let already_registered = ref []
 
   let register =
@@ -228,22 +247,43 @@ module Serializer(D: sig type dumpable_status end) =
      already_registered := tag :: !already_registered;
      let old_require1 = !require1 in
      require1 :=
-      (fun ((tag',data) as x) ->
+      (fun ~alias_only ((tag',data) as x) ->
         if tag=tag' then
          require (Obj.magic data) ~refresh_uri_in_universe ~refresh_uri_in_term
-          ~refresh_uri_in_reference
+          ~refresh_uri_in_reference ~alias_only
         else
-         old_require1 x);
+         old_require1 ~alias_only x);
      (fun x -> tag,Obj.repr x)
    end
 
-  let serialize = serialize
-
-  let require2 ~baseuri status =
+  let serialize ~baseuri status =
+   let ch = open_out (ng_path_of_baseuri baseuri) in
+   Marshal.to_channel ch (magic,(status#dump.dependencies,status#dump.objs)) [];
+   close_out ch;
+
+   if Helm_registry.get_bool "matita.remove_old_objects" then
+   remove_objects ~baseuri; (* FG: we remove the old objects before putting the new ones*)
+
+   List.iter
+    (function 
+     | `Obj (uri,obj) ->
+         let ch = open_out (ng_path_of_baseuri uri) in
+         Marshal.to_channel ch (magic,obj) [];
+         close_out ch
+     | `Constr _ -> ()
+    ) !storage;
+   set_global_aliases (!local_aliases @ get_global_aliases ());
+   List.iter (fun u -> add_deps u [baseuri]) status#dump.includes;
+   time_travel0 time0
+
+  let require2 ~baseuri ~alias_only status =
    try
-    includes := baseuri::!includes;
+    let status =
+     status#set_dump
+      {status#dump with
+        includes = baseuri::List.filter ((<>) baseuri) status#dump.includes} in
     let _dependencies,dump = require0 ~baseuri in
-     List.fold_right !require1 dump status
+     List.fold_right (!require1 ~alias_only) dump status
    with
     Sys_error _ ->
      raise (IncludedFileNotCompiled(ng_path_of_baseuri baseuri,NUri.string_of_uri baseuri))
@@ -251,53 +291,36 @@ module Serializer(D: sig type dumpable_status end) =
   let dependencies_of ~baseuri = fst (require0 ~baseuri)
 
   let record_include =
-   let aux baseuri ~refresh_uri_in_universe ~refresh_uri_in_term
-   ~refresh_uri_in_reference =
-     (* memorizzo baseuri in una tabella; *)
-     require2 ~baseuri
+   let aux (baseuri,fname) ~refresh_uri_in_universe:_ ~refresh_uri_in_term:_
+   ~refresh_uri_in_reference:_ ~alias_only status =
+     let baseuri = refresh_uri baseuri in
+     if not alias_only && List.mem baseuri (get_transitively_included status) then status
+     else
+      (HLog.warn ("include " ^ (if alias_only then "alias " else "") ^ fname);
+      let status = require2 ~baseuri ~alias_only status in
+      HLog.warn ("done: include " ^ (if alias_only then "alias " else "") ^ fname);
+      status)
    in
     register#run "include" aux
 
-  let require ~baseuri status =
-   let status = require2 ~baseuri status in
-    status,record_include baseuri
+  let require ~baseuri ~fname ~alias_only status =
+   if not alias_only && List.mem baseuri (get_transitively_included status) then status
+   else
+    (let status =
+     if not alias_only then
+      status#set_dump
+       {status#dump with dependencies = fname::status#dump.dependencies}
+     else
+      status in
+    let status = require2 ~baseuri ~alias_only status in
+      status#set_dump
+       {status#dump with
+         objs = record_include (baseuri,fname)::status#dump.objs })
 end
 
-
-let decompile ~baseuri =
- let baseuris = get_deps baseuri in
- List.iter (fun baseuri ->
-  remove_deps baseuri;
-  HExtlib.safe_remove (ng_path_of_baseuri baseuri);
-  let basepath = ng_path_of_baseuri ~no_suffix:true baseuri in
-  try
-   let od = Unix.opendir basepath in
-   let rec aux names =
-    try
-     let name = Unix.readdir od in
-      if name <> "." && name <> ".." then aux (name::names) else aux names
-    with
-     End_of_file -> names in
-   let names = List.map (fun name -> basepath ^ "/" ^ name) (aux []) in
-    Unix.closedir od;
-    List.iter Unix.unlink names;
-    HExtlib.rmdir_descend basepath;
-    set_global_aliases
-     (List.filter
-      (fun (_,_,NReference.Ref (nuri,_)) ->
-        Filename.dirname (NUri.string_of_uri nuri) <> NUri.string_of_uri baseuri
-      ) (get_global_aliases ()))
-  with
-   Unix.Unix_error _ -> () (* raised by Unix.opendir, we hope :-) *)
- ) baseuris
-;;
-
-LibraryClean.set_decompile_cb
- (fun ~baseuri -> decompile ~baseuri:(NUri.uri_of_string baseuri));;
-
-let fetch_obj uri =
+let fetch_obj status uri =
  let obj = require0 ~baseuri:uri in
-  refresh_uri_in_obj obj
+  refresh_uri_in_obj status obj
 ;;
 
 let resolve name =
@@ -315,10 +338,10 @@ let aliases_of uri =
      if NUri.eq uri' uri then Some nref else None) !local_aliases
 ;;
 
-let add_obj status ((u,_,_,_,_) as obj) =
- NCicEnvironment.check_and_add_obj obj;
- storage := (`Obj (u,obj))::!storage;
-  let _,height,_,_,obj = obj in
+let add_obj status ((u,_,_,_,_) as orig_obj) =
+ NCicEnvironment.check_and_add_obj status orig_obj;
+ storage := (`Obj (u,orig_obj))::!storage;
+  let _,height,_,_,obj = orig_obj in
   let references =
    match obj with
       NCic.Constant (_,name,None,_,_) ->
@@ -347,31 +370,32 @@ let add_obj status ((u,_,_,_,_) as obj) =
          ) il)
   in
   local_aliases := references @ !local_aliases;
-  status#set_timestamp (!storage,!local_aliases,!cache,!includes)
+  status#set_timestamp (!storage,!local_aliases)
 ;;
 
-let add_constraint status u1 u2 = 
-  NCicEnvironment.add_lt_constraint u1 u2;
+let add_constraint status ~acyclic u1 u2 = 
+  if
+   List.exists
+    (function `Constr (u1',u2') when u1=u1' && u2=u2' -> true | _ -> false)
+    !storage
+  then
+   (*CSC: raise an exception here! *)
+   (prerr_endline "CANNOT ADD A CONSTRAINT TWICE"; assert false);
+  NCicEnvironment.add_lt_constraint ~acyclic u1 u2;
   storage := (`Constr (u1,u2)) :: !storage;
-  status#set_timestamp (!storage,!local_aliases,!cache,!includes)
+  status#set_timestamp (!storage,!local_aliases)
 ;;
 
-let get_obj u =
+let get_obj status u =
  try 
   List.assq u 
    (HExtlib.filter_map 
     (function `Obj (u,o) -> Some (u,o) | _ -> None )
     !storage)
  with Not_found ->
-  try fetch_obj u
+  try fetch_obj status u
   with Sys_error _ ->
-   try NUri.UriMap.find u !cache
-   with Not_found ->
-    raise (NCicEnvironment.ObjectNotFound 
-             (lazy (NUri.string_of_uri u)))
+   raise (NCicEnvironment.ObjectNotFound (lazy (NUri.string_of_uri u)))
 ;;
 
-let clear_cache () = cache := NUri.UriMap.empty;;
-
-NCicEnvironment.set_get_obj get_obj;;
-NCicPp.set_get_obj get_obj;;
+NCicEnvironment.set_get_obj get_obj