hop-2012/server/thirdparty/lwt-2.3.2/src/top/toplevel.ml

132 lines
4.7 KiB
OCaml

(* Lightweight thread library for Objective Caml
* http://www.ocsigen.org/lwt
* Module Toplevel
* Copyright (C) 2009 Jérémie Dimino
* Pierre Chambart
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, with linking exceptions;
* either version 2.1 of the License, or (at your option) any later
* version. See COPYING file for details.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*)
open Types
open Lwt_read_line
module TextSet = Set.Make(Text)
type path =
| Path of Path.t
| Longident of Longident.t
module PathMap = Map.Make(struct type t = path let compare = compare end)
let keywords = Lwt_ocaml_completion.keywords
let global_env = ref(lazy(raise Exit))
let local_envs = ref(PathMap.empty)
(* Returns [acc] plus all modules of [dir] *)
let add_modules_from_directory acc dir =
let dir = if dir = "" then "./" else dir in
let acc = ref acc in
Array.iter (fun fname ->
if Filename.check_suffix fname ".cmi" then
acc := TextSet.add (Text.capitalize (Filename.chop_suffix fname ".cmi")) !acc)
(Sys.readdir (if dir = "" then Filename.current_dir_name else dir));
!acc
(* List all names of the module with path [path] *)
let get_names_of_module path =
try
match
match path with
| Path path ->
Env.find_module path !Toploop.toplevel_env
| Longident ident ->
snd (Env.lookup_module ident !Toploop.toplevel_env)
with
| Tmty_signature decls ->
List.fold_left
(fun acc decl -> match decl with
| Tsig_value(id, _)
| Tsig_type(id, _, _)
| Tsig_exception(id, _)
| Tsig_module(id, _, _)
| Tsig_modtype(id, _)
| Tsig_class(id, _, _)
| Tsig_cltype(id, _, _) ->
TextSet.add (Ident.name id) acc)
TextSet.empty decls
| _ ->
TextSet.empty
with Not_found ->
TextSet.empty
let names_of_module path =
try
PathMap.find path !local_envs
with Not_found ->
let names = get_names_of_module path in
local_envs := PathMap.add path names !local_envs;
names
(* List all names accessible without a path *)
let env_names () =
let rec loop acc = function
| Env.Env_empty -> acc
| Env.Env_value(summary, id, _) -> loop (TextSet.add (Ident.name id) acc) summary
| Env.Env_type(summary, id, _) -> loop (TextSet.add (Ident.name id) acc) summary
| Env.Env_exception(summary, id, _) -> loop (TextSet.add (Ident.name id) acc) summary
| Env.Env_module(summary, id, _) -> loop (TextSet.add (Ident.name id) acc) summary
| Env.Env_modtype(summary, id, _) -> loop (TextSet.add (Ident.name id) acc) summary
| Env.Env_class(summary, id, _) -> loop (TextSet.add (Ident.name id) acc) summary
| Env.Env_cltype(summary, id, _) -> loop (TextSet.add (Ident.name id) acc) summary
| Env.Env_open(summary, path) -> loop (TextSet.union acc (names_of_module (Path path))) summary
in
(* Add names of the environment: *)
let acc = loop TextSet.empty (Env.summary !Toploop.toplevel_env) in
(* Add accessible modules: *)
List.fold_left add_modules_from_directory acc !Config.load_path
let path_of_string text =
match Text.split ~sep:"." text with
| [] ->
invalid_arg "Toplevel.make_path"
| ident :: rest ->
let rec loop path = function
| [] -> Longident path
| component :: rest -> loop (Longident.Ldot(path, component)) rest
in
loop (Longident.Lident ident) rest
let complete_ident before ident after =
match Text.rev_split ~sep:"." ~max:2 ident with
| [ident]->
complete ~suffix:"" before ident after (TextSet.union keywords (Lazy.force !global_env))
| [path; ident] ->
let before = before ^ path ^ "." in
complete ~suffix:"" before ident after (names_of_module (path_of_string path))
| _ ->
assert false
let restart () =
global_env := lazy(env_names ());
local_envs := PathMap.empty
let () =
Topfind.don't_load_deeply ["lwt"; "lwt.react"; "lwt.unix"; "lwt.text"; "lwt.top"];
Lwt_ocaml_completion.complete_ident := complete_ident;
Lwt_ocaml_completion.restart := restart