(***********************************************************************) (* v * The Coq Proof Assistant / The Coq Development Team *) (* unit; use_file : string -> unit; add_dir : string -> unit } (* Determines the behaviour of Coq with respect to ML files (compiled or not) *) type kind_load = | WithTop of toplevel | WithoutTop | Native (* Must be always initialized *) let load = ref Native (* Sets and initializes the kind of loading *) let set kload = load := kload let get () = !load (* Resets load *) let remove ()= load := Native (* Tests if an Ocaml toplevel runs under Coq *) let is_ocaml_top () = match !load with | WithTop _ -> true |_ -> false (* Tests if we can load ML files *) let enable_load () = match !load with | WithTop _ | WithoutTop -> true |_ -> false (* Dynamic loading of .cmo *) let dir_ml_load s = match !load with | WithTop t -> if is_in_path !coq_mlpath_copy s then try t.load_obj s with | (UserError _ | Failure _ | Anomaly _ | Not_found as u) -> raise u | _ -> errorlabstrm "Mltop.load_object" [< 'sTR"Cannot link ml-object "; 'sTR s; 'sTR" to Coq code." >] else errorlabstrm "Mltop.load_object" [< 'sTR"File not found on loadpath : "; 'sTR s >] | WithoutTop -> ifdef Byte then (if is_in_path !coq_mlpath_copy s then let _,gname = where_in_path !coq_mlpath_copy s in try Dynlink.loadfile gname; Dynlink.add_interfaces [(String.capitalize (Filename.chop_suffix (Filename.basename gname) ".cmo"))] [Filename.dirname gname] with | Dynlink.Error(a) -> errorlabstrm "Mltop.load_object" [< 'sTR (Dynlink.error_message a) >] else errorlabstrm "Mltop.load_object" [< 'sTR"File not found on loadpath : "; 'sTR s >]) else () | Native -> errorlabstrm "Mltop.no_load_object" [< 'sTR"Loading of ML object file forbidden in a native Coq" >] (* Dynamic interpretation of .ml *) let dir_ml_use s = match !load with | WithTop t -> t.use_file s | _ -> warning "Cannot access the ML compiler" (* Adds a path to the ML paths *) let add_ml_dir s = match !load with | WithTop t -> t.add_dir s; keep_copy_mlpath s | WithoutTop -> keep_copy_mlpath s | _ -> () (* For Rec Add ML Path *) let add_rec_ml_dir dir = List.iter (fun lpe -> add_ml_dir lpe.directory) (all_subdirs dir None) (* Adding files to Coq and ML loadpath *) let add_path dir coq_dirpath = if coq_dirpath = [] then anomaly "add_path: empty path in library"; if exists_dir dir then begin add_ml_dir dir; Library.add_load_path_entry { directory = dir; coq_dirpath = coq_dirpath }; Nametab.push_library_root (List.hd coq_dirpath) end else wARNING [< 'sTR ("Cannot open " ^ dir) >] let add_rec_path dir coq_dirpath = if coq_dirpath = [] then anomaly "add_path: empty path in library"; let dirs = all_subdirs dir (Some coq_dirpath) in if dirs <> [] then begin List.iter (fun lpe -> add_ml_dir lpe.directory) dirs; List.iter Library.add_load_path_entry dirs; Nametab.push_library_root (List.hd coq_dirpath) end else wARNING [< 'sTR ("Cannot open " ^ dir) >] (* convertit un nom quelconque en nom de fichier ou de module *) let mod_of_name name = let base = if Filename.check_suffix name ".cmo" then Filename.chop_suffix name ".cmo" else name in String.capitalize base let file_of_name name = make_suffix (String.uncapitalize name) ".cmo" (* TODO: supprimer ce hack, si possible *) (* Initialisation of ML modules that need the state (ex: tactics like * natural, omega ...) * Each module may add some inits (function of type unit -> unit). * These inits are executed right after the initial state loading if the * module is statically linked, or after the loading if it is required. *) let init_list = ref ([] : (unit -> unit) list) let add_init_with_state init_fun = init_list := init_fun :: !init_list let init_with_state () = List.iter (fun f -> f()) (List.rev !init_list); init_list := [] (* [known_loaded_module] contains the names of the loaded ML modules * (linked or loaded with load_object). It is used not to load a * module twice. It is NOT the list of ML modules Coq knows. *) type ml_module_object = { mnames : string list } let known_loaded_modules = ref Stringset.empty let add_known_module mname = known_loaded_modules := Stringset.add mname !known_loaded_modules let module_is_known mname = Stringset.mem mname !known_loaded_modules let load_object mname fname= dir_ml_load fname; init_with_state(); add_known_module mname (* Summary of declared ML Modules *) let loaded_modules = ref Stringset.empty let get_loaded_modules () = Stringset.elements !loaded_modules let add_loaded_module md = loaded_modules := Stringset.add md !loaded_modules let orig_loaded_modules = ref !loaded_modules let init_ml_modules () = loaded_modules := !orig_loaded_modules let unfreeze_ml_modules x = List.iter (fun name -> let mname = mod_of_name name in if not (module_is_known mname) then if enable_load() then let fname = file_of_name mname in load_object mname fname else errorlabstrm "Mltop.unfreeze_ml_modules" [< 'sTR"Loading of ML object file forbidden in a native Coq" >]; add_loaded_module mname) x let _ = Summary.declare_summary "ML-MODULES" { Summary.freeze_function = (fun () -> List.rev (get_loaded_modules())); Summary.unfreeze_function = (fun x -> unfreeze_ml_modules x); Summary.init_function = (fun () -> init_ml_modules ()); Summary.survive_section = true } (* Same as restore_ml_modules, but verbosely *) let cache_ml_module_object (_,{mnames=mnames}) = List.iter (fun name -> let mname = mod_of_name name in if not (module_is_known mname) then let fname = file_of_name mname in begin try mSG [< 'sTR"[Loading ML file " ; 'sTR fname ; 'sTR" ..." >]; load_object mname fname; mSGNL [< 'sTR"done]" >] with e -> pPNL [< 'sTR"failed]" >]; raise e end; add_loaded_module mname) mnames let export_ml_module_object x = Some x let (inMLModule,outMLModule) = declare_object ("ML-MODULE", { load_function = cache_ml_module_object; cache_function = cache_ml_module_object; open_function = (fun _ -> ()); export_function = export_ml_module_object }) let declare_ml_modules l = Lib.add_anonymous_leaf (inMLModule {mnames=l}) let print_ml_path () = let l = !coq_mlpath_copy in pPNL [< 'sTR"ML Load Path:"; 'fNL; 'sTR" "; hV 0 (prlist_with_sep pr_fnl (fun e -> [< 'sTR e.directory >]) l) >] (* Printing of loaded ML modules *) let print_ml_modules () = let l = get_loaded_modules () in pP [< 'sTR"Loaded ML Modules : " ; hOV 0 (prlist_with_sep pr_fnl (fun s -> [< 'sTR s >]) l); 'fNL >]