···11+let cmi_files dir =
22+ Bos.OS.Dir.fold_contents ~traverse:`None ~elements:`Files
33+ (fun path acc ->
44+ if Fpath.has_ext ".cmi" path then Fpath.filename path :: acc else acc)
55+ [] dir
66+77+let gen_cmis cmis =
88+ let gen_one (dir, cmis) =
99+ let all_cmis =
1010+ List.map (fun s -> String.sub s 0 (String.length s - 4)) cmis
1111+ in
1212+ let hidden, non_hidden =
1313+ List.partition (fun x -> Astring.String.is_infix ~affix:"__" x) all_cmis
1414+ in
1515+ let prefixes =
1616+ List.filter_map
1717+ (fun x ->
1818+ match Astring.String.cuts ~sep:"__" x with
1919+ | x :: _ -> Some (x ^ "__")
2020+ | _ -> None)
2121+ hidden
2222+ in
2323+ let prefixes = Util.StringSet.(of_list prefixes |> to_list) in
2424+ let findlib_dir = Ocamlfind.findlib_dir () |> Fpath.v in
2525+ let d = Fpath.relativize ~root:findlib_dir dir |> Option.get in
2626+ let dcs =
2727+ {
2828+ Js_top_worker_rpc.Toplevel_api_gen.dcs_url =
2929+ Fpath.(v "lib" // d |> to_string);
3030+ dcs_toplevel_modules = List.map String.capitalize_ascii non_hidden;
3131+ dcs_file_prefixes = prefixes;
3232+ }
3333+ in
3434+ ( dir,
3535+ Jsonrpc.to_string
3636+ (Rpcmarshal.marshal
3737+ Js_top_worker_rpc.Toplevel_api_gen.typ_of_dynamic_cmis dcs) )
3838+ in
3939+ List.map gen_one cmis
4040+4141+let opam output_dir_str switch libraries no_worker =
4242+ Opam.switch := switch;
4343+ let libraries =
4444+ match Ocamlfind.deps libraries with
4545+ | Ok l -> Util.StringSet.of_list ("stdlib" :: l)
4646+ | Error (`Msg m) ->
4747+ Format.eprintf "Failed to find libs: %s\n%!" m;
4848+ (* Format.eprintf "Bad libs: %s\n%!" m; *)
4949+ (* failwith ("Bad libs: " ^ m) *)
5050+ failwith ("Bad libs: " ^ m)
5151+ in
5252+ let verbose = true in
5353+ Eio_main.run @@ fun env ->
5454+ Eio.Switch.run @@ fun sw ->
5555+ if verbose then Logs.set_level (Some Logs.Debug) else Logs.set_level None;
5656+ Logs.set_reporter (Logs_fmt.reporter ());
5757+ let () = Worker_pool.start_workers env sw 16 in
5858+ Logs.debug (fun m ->
5959+ m "Libraries: %a"
6060+ (Fmt.list ~sep:Fmt.comma Fmt.string)
6161+ (Util.StringSet.elements libraries));
6262+ let output_dir = Fpath.v output_dir_str in
6363+ let meta_files =
6464+ List.map
6565+ (fun lib -> Ocamlfind.meta_file lib)
6666+ (Util.StringSet.elements libraries)
6767+ |> Util.StringSet.of_list
6868+ in
6969+ let cmi_dirs =
7070+ match Ocamlfind.deps (Util.StringSet.to_list libraries) with
7171+ | Ok libs ->
7272+ let dirs =
7373+ List.filter_map
7474+ (fun lib ->
7575+ match Ocamlfind.get_dir lib with Ok x -> Some x | _ -> None)
7676+ libs
7777+ in
7878+ dirs
7979+ | Error (`Msg m) ->
8080+ Format.eprintf "Failed to find libs: %s\n%!" m;
8181+ []
8282+ in
8383+ Format.eprintf "cmi_dirs: %a\n%!" (Fmt.list ~sep:Fmt.comma Fpath.pp) cmi_dirs;
8484+ let cmis =
8585+ List.fold_left
8686+ (fun acc dir ->
8787+ match cmi_files dir with
8888+ | Ok files -> (dir, files) :: acc
8989+ | Error _ -> acc)
9090+ [] cmi_dirs
9191+ in
9292+ let ( let* ) = Result.bind in
9393+9494+ let _ =
9595+ let* _ = Bos.OS.Dir.create output_dir in
9696+ let findlib_dir = Ocamlfind.findlib_dir () |> Fpath.v in
9797+9898+ List.iter
9999+ (fun (dir, files) ->
100100+ let d = Fpath.relativize ~root:findlib_dir dir |> Option.get in
101101+ List.iter
102102+ (fun f ->
103103+ let dest_dir = Fpath.(output_dir / "lib" // d) in
104104+ let dest = Fpath.(dest_dir / f) in
105105+ let _ = Bos.OS.Dir.create ~path:true dest_dir in
106106+ match Bos.OS.File.exists dest with
107107+ | Ok true -> ()
108108+ | Ok false -> Util.cp Fpath.(dir / f) dest
109109+ | Error _ -> failwith "file exists failed")
110110+ files)
111111+ cmis;
112112+113113+ let meta_rels =
114114+ Util.StringSet.fold
115115+ (fun meta_file acc ->
116116+ let meta_file = Fpath.v meta_file in
117117+ let d =
118118+ Fpath.relativize ~root:findlib_dir meta_file
119119+ |> Option.get |> Fpath.parent
120120+ in
121121+ (meta_file, d) :: acc)
122122+ meta_files []
123123+ in
124124+125125+ List.iter
126126+ (fun (meta_file, d) ->
127127+ let dest = Fpath.(output_dir / "lib" // d) in
128128+ let _ = Bos.OS.Dir.create dest in
129129+ Util.cp meta_file dest)
130130+ meta_rels;
131131+132132+ Out_channel.with_open_bin
133133+ Fpath.(output_dir / "findlib_index" |> to_string)
134134+ (fun oc ->
135135+ List.iter
136136+ (fun (meta_file, d) ->
137137+ let file = Fpath.filename meta_file in
138138+ let path = Fpath.(v "lib" // d / file) in
139139+ Printf.fprintf oc "%s\n" (Fpath.to_string path))
140140+ meta_rels);
141141+142142+ Util.StringSet.iter
143143+ (fun lib ->
144144+ let archives = Ocamlfind.archives lib in
145145+ let dir = Ocamlfind.get_dir lib |> Result.get_ok in
146146+ let archives = List.map (fun x -> Fpath.(dir / x)) archives in
147147+ let d = Fpath.relativize ~root:findlib_dir dir |> Option.get in
148148+ let dest = Fpath.(output_dir / "lib" // d) in
149149+ let _ = Bos.OS.Dir.create dest in
150150+ let doit archive =
151151+ let output = Fpath.(dest / (Fpath.filename archive ^ ".js")) in
152152+ let cmd =
153153+ match switch with
154154+ | None ->
155155+ Bos.Cmd.(
156156+ v "js_of_ocaml" % "compile" % Fpath.to_string archive % "-o"
157157+ % Fpath.to_string output)
158158+ | Some s ->
159159+ Bos.Cmd.(
160160+ v "opam" % "exec" % "--switch" % s % "--" % "js_of_ocaml"
161161+ % "compile" % Fpath.to_string archive % "-o"
162162+ % Fpath.to_string output)
163163+ in
164164+ let _ = Util.lines_of_process cmd in
165165+ ()
166166+ in
167167+ List.iter doit archives)
168168+ libraries;
169169+170170+ (* Format.eprintf "@[<hov 2>dir: %a [%a]@]\n%!" Fpath.pp dir (Fmt.list ~sep:Fmt.sp Fmt.string) files) cmis; *)
171171+ Ok ()
172172+ in
173173+ let init_cmis = gen_cmis cmis in
174174+ List.iter
175175+ (fun (dir, dcs) ->
176176+ let findlib_dir = Ocamlfind.findlib_dir () |> Fpath.v in
177177+ let d = Fpath.relativize ~root:findlib_dir dir in
178178+ match d with
179179+ | None ->
180180+ Format.eprintf "Failed to relativize %a wrt %a\n%!" Fpath.pp dir
181181+ Fpath.pp findlib_dir
182182+ | Some dir ->
183183+ Format.eprintf "Generating %a\n%!" Fpath.pp dir;
184184+ let dir = Fpath.(output_dir / "lib" // dir) in
185185+ let _ = Bos.OS.Dir.create dir in
186186+ let oc = open_out Fpath.(dir / "dynamic_cmis.json" |> to_string) in
187187+ Printf.fprintf oc "%s" dcs;
188188+ close_out oc)
189189+ init_cmis;
190190+ Format.eprintf "Number of cmis: %d\n%!" (List.length init_cmis);
191191+192192+ let () =
193193+ if no_worker then () else Mk_backend.mk switch libraries output_dir
194194+ in
195195+196196+ `Ok ()
197197+198198+open Cmdliner
199199+200200+let opam_cmd =
201201+ let libraries = Arg.(value & pos_all string [] & info [] ~docv:"LIB") in
202202+ let output_dir =
203203+ let doc =
204204+ "Output directory in which to put all outputs. This should be the root \
205205+ directory of the HTTP server"
206206+ in
207207+ Arg.(value & opt string "html" & info [ "o"; "output" ] ~doc)
208208+ in
209209+ let no_worker =
210210+ let doc = "Do not create worker.js" in
211211+ Arg.(value & flag & info [ "no-worker" ] ~doc)
212212+ in
213213+ let switch =
214214+ let doc = "Opam switch to use" in
215215+ Arg.(value & opt (some string) None & info [ "switch" ] ~doc)
216216+ in
217217+ let info = Cmd.info "opam" ~doc:"Generate opam files" in
218218+ Cmd.v info
219219+ Term.(ret (const opam $ output_dir $ switch $ libraries $ no_worker))
220220+221221+let main_cmd =
222222+ let doc = "An odoc notebook tool" in
223223+ let info = Cmd.info "odoc-notebook" ~version:"%%VERSION%%" ~doc in
224224+ let default = Term.(ret (const (`Help (`Pager, None)))) in
225225+ Cmd.group info ~default [ opam_cmd ]
226226+227227+let () = exit (Cmd.eval main_cmd)
+66
bin/mk_backend.ml
···11+(* To make a toplevel backend.js *)
22+33+let mk switch libs dir =
44+ let txt = {|let _ = Js_top_worker_web.Worker.run ()|} in
55+ let file = Fpath.(dir / "worker.ml") in
66+ Util.write_file file [ txt ];
77+ let ocamlfind_cmd, js_of_ocaml_cmd =
88+ match switch with
99+ | None -> (Bos.Cmd.(v "ocamlfind"), Bos.Cmd.(v "js_of_ocaml"))
1010+ | Some s ->
1111+ ( Bos.Cmd.(v "opam" % "exec" % "--switch" % s % "--" % "ocamlfind"),
1212+ Bos.Cmd.(v "opam" % "exec" % "--switch" % s % "--" % "js_of_ocaml") )
1313+ in
1414+ let cmd =
1515+ Bos.Cmd.(
1616+ ocamlfind_cmd % "ocamlc" % "-package" % "js_of_ocaml-ppx.as-lib"
1717+ % "-package" % "js_top_worker-web")
1818+ in
1919+ let cmd = Bos.Cmd.(cmd % "-linkpkg" % "-linkall" % Fpath.to_string file) in
2020+ let cmd =
2121+ Bos.Cmd.(cmd % "-g" % "-o" % Fpath.(dir / "worker.bc" |> to_string))
2222+ in
2323+ let _ = Util.lines_of_process cmd in
2424+ let cmd =
2525+ Bos.Cmd.(
2626+ ocamlfind_cmd % "query" % "-format" % "%+(jsoo_runtime)" % "-r"
2727+ % "js_top_worker-web")
2828+ in
2929+ let cmd = Util.StringSet.fold (fun lib cmd -> Bos.Cmd.(cmd % lib)) libs cmd in
3030+ let js_files =
3131+ Util.lines_of_process cmd
3232+ |> List.filter (fun x -> String.length x > 0)
3333+ |> List.map (fun x -> Astring.String.cuts ~sep:" " x)
3434+ |> List.flatten
3535+ in
3636+ let cmd =
3737+ Bos.Cmd.(
3838+ js_of_ocaml_cmd % "--toplevel" % "--no-cmis" % "--linkall" % "--pretty")
3939+ in
4040+ let cmd =
4141+ List.fold_right
4242+ (fun a cmd -> Bos.Cmd.(cmd % a))
4343+ (js_files
4444+ @ [
4545+ "+dynlink.js";
4646+ "+toplevel.js";
4747+ "+bigstringaf/runtime.js";
4848+ "+js_top_worker/stubs.js";
4949+ ])
5050+ cmd
5151+ in
5252+ let cmd =
5353+ Bos.Cmd.(
5454+ cmd
5555+ % Fpath.(dir / "worker.bc" |> to_string)
5656+ % "-o"
5757+ % Fpath.(dir / "worker.js" |> to_string))
5858+ in
5959+ Logs.info (fun m -> m "cmd: %s" (Bos.Cmd.to_string cmd));
6060+ let _ = Util.lines_of_process cmd in
6161+ let to_delete = [ "worker.bc"; "worker.ml"; "worker.cmi"; "worker.cmo" ] in
6262+ let results =
6363+ List.map (fun f -> Bos.OS.File.delete Fpath.(dir / f)) to_delete
6464+ in
6565+ ignore results;
6666+ ()
+67
bin/ocamlfind.ml
···11+let init =
22+ let initialized = ref false in
33+ fun () ->
44+ if !initialized then ()
55+ else
66+ let prefix = Opam.prefix () in
77+ let env_camllib = Fpath.(v prefix / "lib" / "ocaml" |> to_string) in
88+ let config = Fpath.(v prefix / "lib" / "findlib.conf" |> to_string) in
99+ Findlib.init ~config ~env_camllib ()
1010+1111+let all () =
1212+ init ();
1313+ Fl_package_base.list_packages ()
1414+1515+let get_dir lib =
1616+ try
1717+ init ();
1818+ Fl_package_base.query lib |> fun x ->
1919+ Logs.debug (fun m -> m "Package %s is in directory %s@." lib x.package_dir);
2020+ Ok Fpath.(v x.package_dir |> to_dir_path)
2121+ with e ->
2222+ Printf.eprintf "Error: %s\n" (Printexc.to_string e);
2323+ Error (`Msg "Error getting directory")
2424+2525+let findlib_dir () = Findlib.default_location ()
2626+2727+let archives pkg =
2828+ init ();
2929+ let package = Fl_package_base.query pkg in
3030+ let get_1 preds =
3131+ try
3232+ [
3333+ Fl_metascanner.lookup "archive" preds
3434+ package.Fl_package_base.package_defs;
3535+ ]
3636+ with _ -> []
3737+ in
3838+ match pkg with
3939+ | "stdlib" -> [ "stdlib.cma" ]
4040+ | _ ->
4141+ get_1 [ "byte" ] @ get_1 [ "byte"; "ppx_driver" ]
4242+ |> List.filter (fun x -> String.length x > 0)
4343+ |> List.sort_uniq String.compare
4444+4545+let sub_libraries top =
4646+ init ();
4747+ let packages = Fl_package_base.list_packages () in
4848+ List.fold_left
4949+ (fun acc lib ->
5050+ let package = String.split_on_char '.' lib |> List.hd in
5151+ if package = top then Util.StringSet.add lib acc else acc)
5252+ Util.StringSet.empty packages
5353+5454+let deps pkgs =
5555+ init ();
5656+ try
5757+ let packages =
5858+ Fl_package_base.requires_deeply ~preds:[ "ppx_driver"; "byte" ] pkgs
5959+ in
6060+ Ok packages
6161+ with e -> Error (`Msg (Printexc.to_string e))
6262+6363+let meta_file pkg =
6464+ init ();
6565+ let package = Fl_package_base.query pkg in
6666+ let meta = package.Fl_package_base.package_meta in
6767+ meta
+170
bin/opam.ml
···11+open Bos
22+33+let opam = Cmd.v "opam"
44+let switch = ref None
55+let prefix = ref None
66+77+type package = { name : string; version : string }
88+99+let pp fmt p = Format.fprintf fmt "%s.%s" p.name p.version
1010+1111+let rec get_switch () =
1212+ match !switch with
1313+ | None ->
1414+ let cur_switch =
1515+ Util.lines_of_process Cmd.(opam % "switch" % "show") |> List.hd
1616+ in
1717+ switch := Some cur_switch;
1818+ get_switch ()
1919+ | Some s -> s
2020+2121+let prefix () =
2222+ match !prefix with
2323+ | Some p -> p
2424+ | None ->
2525+ let p =
2626+ Util.lines_of_process
2727+ Cmd.(opam % "var" % "--switch" % get_switch () % "prefix")
2828+ |> List.hd
2929+ in
3030+ prefix := Some p;
3131+ p
3232+3333+let deps_of_opam_result line =
3434+ match Astring.String.fields ~empty:false line with
3535+ | [ name; version ] -> [ { name; version } ]
3636+ | _ -> []
3737+3838+let all_opam_packages () =
3939+ Util.lines_of_process
4040+ Cmd.(
4141+ opam % "list" % "--switch" % get_switch () % "--columns=name,version"
4242+ % "--color=never" % "--short")
4343+ |> List.map deps_of_opam_result
4444+ |> List.flatten
4545+4646+let pkg_contents { name; _ } =
4747+ let prefix = Fpath.v (prefix ()) in
4848+ let changes_file =
4949+ Format.asprintf "%a/.opam-switch/install/%s.changes" Fpath.pp prefix name
5050+ in
5151+ let file = OpamFilename.raw changes_file in
5252+ let filename =
5353+ OpamFile.make @@ OpamFilename.raw @@ Filename.basename changes_file
5454+ in
5555+ let changed =
5656+ OpamFilename.with_contents
5757+ (fun str ->
5858+ OpamFile.Changes.read_from_string ~filename
5959+ @@
6060+ (* Field [opam-version] is invalid in [*.changes] files, displaying a warning. *)
6161+ if OpamStd.String.starts_with ~prefix:"opam-version" str then
6262+ match OpamStd.String.cut_at str '\n' with
6363+ | Some (_, str) -> str
6464+ | None -> assert false
6565+ else str)
6666+ file
6767+ in
6868+ let added =
6969+ OpamStd.String.Map.fold
7070+ (fun file x acc ->
7171+ match x with
7272+ | OpamDirTrack.Added _ -> (
7373+ try
7474+ if not @@ Sys.is_directory Fpath.(to_string (prefix // v file))
7575+ then file :: acc
7676+ else acc
7777+ with _ ->
7878+ acc
7979+ (* dose (and maybe others) sometimes creates a symlink to something that doesn't exist *)
8080+ )
8181+ | _ -> acc)
8282+ changed []
8383+ in
8484+ List.map Fpath.v added
8585+8686+(* let opam_file { name; version } = *)
8787+(* let prefix = Fpath.v (prefix ()) in *)
8888+(* let opam_file = *)
8989+(* Format.asprintf "%a/.opam-switch/packages/%s.%s/opam" Fpath.pp prefix name *)
9090+(* version *)
9191+(* in *)
9292+(* let ic = open_in opam_file in *)
9393+(* try *)
9494+(* let lines = Util.lines_of_channel ic in *)
9595+(* close_in ic; *)
9696+(* Some lines *)
9797+(* with _ -> *)
9898+(* close_in ic; *)
9999+(* None *)
100100+101101+type installed_files = {
102102+ libs : Fpath.set;
103103+ odoc_pages : Fpath.set;
104104+ other_docs : Fpath.set;
105105+}
106106+107107+type package_of_fpath = package Fpath.map
108108+109109+(* Here we use an associative list *)
110110+type fpaths_of_package = (package * installed_files) list
111111+112112+let pkg_to_dir_map () =
113113+ let pkgs = all_opam_packages () in
114114+ let prefix = prefix () in
115115+ let pkg_content =
116116+ List.map
117117+ (fun p ->
118118+ let contents = pkg_contents p in
119119+ let libs =
120120+ List.fold_left
121121+ (fun set fpath ->
122122+ match Fpath.segs fpath with
123123+ | "lib" :: "stublibs" :: _ -> set
124124+ | "lib" :: _ :: _ :: _ when Fpath.has_ext ".cmi" fpath ->
125125+ Fpath.Set.add
126126+ Fpath.(v prefix // fpath |> split_base |> fst)
127127+ set
128128+ | _ -> set)
129129+ Fpath.Set.empty contents
130130+ in
131131+ let odoc_pages, other_docs =
132132+ List.fold_left
133133+ (fun (odoc_pages, others) fpath ->
134134+ match Fpath.segs fpath with
135135+ | "doc" :: _pkg :: "odoc-pages" :: _ ->
136136+ Logs.debug (fun m -> m "Found odoc page: %a" Fpath.pp fpath);
137137+138138+ (Fpath.Set.add Fpath.(v prefix // fpath) odoc_pages, others)
139139+ | "doc" :: _ ->
140140+ Logs.debug (fun m -> m "Found other doc: %a" Fpath.pp fpath);
141141+ (odoc_pages, Fpath.Set.add Fpath.(v prefix // fpath) others)
142142+ | _ -> (odoc_pages, others))
143143+ Fpath.Set.(empty, empty)
144144+ contents
145145+ in
146146+ Logs.debug (fun m ->
147147+ m "Found %d odoc pages, %d other docs"
148148+ (Fpath.Set.cardinal odoc_pages)
149149+ (Fpath.Set.cardinal other_docs));
150150+ (p, { libs; odoc_pages; other_docs }))
151151+ pkgs
152152+ in
153153+ let map =
154154+ List.fold_left
155155+ (fun map (p, { libs; _ }) ->
156156+ Fpath.Set.fold
157157+ (fun dir map ->
158158+ Fpath.Map.update dir
159159+ (function
160160+ | None -> Some p
161161+ | Some x ->
162162+ Logs.debug (fun m ->
163163+ m "Multiple packages (%a,%a) found for dir %a" pp x pp p
164164+ Fpath.pp dir);
165165+ Some p)
166166+ map)
167167+ libs map)
168168+ Fpath.Map.empty pkg_content
169169+ in
170170+ (pkg_content, map)
+116
bin/run.ml
···11+let instrument = false
22+33+open Bos
44+55+let instrument_dir =
66+ lazy
77+ (let dir = Fpath.v "landmarks" in
88+ OS.Dir.delete dir |> Result.get_ok;
99+ OS.Dir.create dir |> Result.get_ok |> ignore;
1010+ dir)
1111+1212+type t = {
1313+ cmd : string list;
1414+ time : float; (** Running time in seconds. *)
1515+ output_file : Fpath.t option;
1616+ output : string;
1717+ errors : string;
1818+ status : [ `Exited of int | `Signaled of int ];
1919+}
2020+2121+(* Environment variables passed to commands. *)
2222+2323+(* Record the commands executed, their running time and optionally the path to
2424+ the produced file. *)
2525+let commands = ref []
2626+let n = Atomic.make 0
2727+2828+(** Return the list of executed commands where the first argument was [cmd]. *)
2929+let run env cmd output_file =
3030+ let cmd = Bos.Cmd.to_list cmd in
3131+ let myn = Atomic.fetch_and_add n 1 in
3232+ Logs.debug (fun m -> m "%d - Executing: %s" myn (String.concat " " cmd));
3333+ let proc_mgr = Eio.Stdenv.process_mgr env in
3434+ let t_start = Unix.gettimeofday () in
3535+ let env =
3636+ let env = OS.Env.current () |> Result.get_ok in
3737+ env
3838+ in
3939+ let env =
4040+ Astring.String.Map.fold
4141+ (fun k v env -> Astring.String.concat [ k; "="; v ] :: env)
4242+ env []
4343+ |> Array.of_list
4444+ in
4545+ (* Logs.debug (fun m -> m "Running cmd %a" Fmt.(list ~sep:sp string) cmd); *)
4646+ let output, errors, status =
4747+ Eio.Switch.run ~name:"Process.parse_out" @@ fun sw ->
4848+ let r, w = Eio.Process.pipe proc_mgr ~sw in
4949+ let re, we = Eio.Process.pipe proc_mgr ~sw in
5050+ try
5151+ let child =
5252+ Eio.Process.spawn ~sw proc_mgr ~stdout:w ~stderr:we ~env cmd
5353+ in
5454+ Eio.Flow.close w;
5555+ Eio.Flow.close we;
5656+ let output, err =
5757+ Eio.Fiber.pair
5858+ (fun () ->
5959+ Eio.Buf_read.parse_exn Eio.Buf_read.take_all r ~max_size:max_int)
6060+ (fun () ->
6161+ Eio.Buf_read.parse_exn Eio.Buf_read.take_all re ~max_size:max_int)
6262+ in
6363+ Eio.Flow.close r;
6464+ Eio.Flow.close re;
6565+ let status = Eio.Process.await child in
6666+ (output, err, status)
6767+ with Eio.Exn.Io _ as ex ->
6868+ let bt = Printexc.get_raw_backtrace () in
6969+ Eio.Exn.reraise_with_context ex bt "%d - running command: %a" myn
7070+ Eio.Process.pp_args cmd
7171+ in
7272+ (* Logs.debug (fun m ->
7373+ m "Finished running cmd %a" Fmt.(list ~sep:sp string) cmd); *)
7474+ let t_end = Unix.gettimeofday () in
7575+ let time = t_end -. t_start in
7676+ let result = { cmd; time; output_file; output; errors; status } in
7777+ commands := result :: !commands;
7878+ (match result.status with
7979+ | `Exited 0 -> ()
8080+ | _ ->
8181+ let verb, n =
8282+ match result.status with
8383+ | `Exited n -> ("exited", n)
8484+ | `Signaled n -> ("signaled", n)
8585+ in
8686+ Logs.err (fun m ->
8787+ m
8888+ "@[<2>Process %s with %d:@ '@[%a'@]@]@\n\n\
8989+ Stdout:\n\
9090+ %s\n\n\
9191+ Stderr:\n\
9292+ %s"
9393+ verb n
9494+ Fmt.(list ~sep:sp string)
9595+ result.cmd result.output result.errors));
9696+ result
9797+9898+(** Print an executed command and its time. *)
9999+100100+let filter_commands cmd =
101101+ match
102102+ List.filter
103103+ (fun c -> match c.cmd with _ :: cmd' :: _ -> cmd = cmd' | _ -> false)
104104+ !commands
105105+ with
106106+ | [] -> []
107107+ | _ :: _ as cmds -> cmds
108108+109109+let print_cmd c =
110110+ Printf.printf "[%4.2f] $ %s\n" c.time (String.concat " " c.cmd)
111111+112112+(** Returns the [k] commands that took the most time for a given subcommand. *)
113113+let k_longest_commands cmd k =
114114+ filter_commands cmd
115115+ |> List.sort (fun a b -> Float.compare b.time a.time)
116116+ |> List.filteri (fun i _ -> i < k)
+47
bin/util.ml
···11+open Bos
22+module StringSet = Set.Make (String)
33+module StringMap = Map.Make (String)
44+55+let lines_of_channel ic =
66+ let rec inner acc =
77+ try
88+ let l = input_line ic in
99+ inner (l :: acc)
1010+ with End_of_file -> List.rev acc
1111+ in
1212+ inner []
1313+1414+let lines_of_process cmd =
1515+ match OS.Cmd.(run_out ~err:err_null cmd |> to_lines) with
1616+ | Ok x -> x
1717+ | Error (`Msg e) -> failwith ("Error: " ^ e)
1818+1919+let mkdir_p d =
2020+ let segs =
2121+ Fpath.segs (Fpath.normalize d) |> List.filter (fun s -> String.length s > 0)
2222+ in
2323+ let _ =
2424+ List.fold_left
2525+ (fun path seg ->
2626+ let d = Fpath.(path // v seg) in
2727+ try
2828+ Unix.mkdir (Fpath.to_string d) 0o755;
2929+ d
3030+ with
3131+ | Unix.Unix_error (Unix.EEXIST, _, _) -> d
3232+ | exn -> raise exn)
3333+ (Fpath.v ".") segs
3434+ in
3535+ ()
3636+3737+let write_file filename lines =
3838+ let dir = fst (Fpath.split_base filename) in
3939+ mkdir_p dir;
4040+ let oc = open_out (Fpath.to_string filename) in
4141+ List.iter (fun line -> Printf.fprintf oc "%s\n" line) lines;
4242+ close_out oc
4343+4444+let cp src dst =
4545+ assert (
4646+ lines_of_process Cmd.(v "cp" % Fpath.to_string src % Fpath.to_string dst)
4747+ = [])
+47
bin/worker_pool.ml
···11+(* Worker pool *)
22+open Eio
33+44+type request = {
55+ description : string;
66+ request : Bos.Cmd.t;
77+ output_file : Fpath.t option;
88+}
99+1010+type response = (Run.t, exn) result
1111+type resolver = response Eio.Promise.u
1212+type t = (request * resolver) Eio.Stream.t
1313+1414+let stream : t = Eio.Stream.create 0
1515+let handle_job env request output_file = Run.run env request output_file
1616+1717+exception Worker_failure of Run.t
1818+1919+let rec run_worker env id : unit =
2020+ let { request; output_file; description = _ }, reply =
2121+ Eio.Stream.take stream
2222+ in
2323+ (try
2424+ let result = handle_job env request output_file in
2525+ match result.status with
2626+ | `Exited 0 -> Promise.resolve reply (Ok result)
2727+ | _ -> Promise.resolve_error reply (Worker_failure result)
2828+ with e -> Promise.resolve_error reply e);
2929+ run_worker env id
3030+3131+let submit description request output_file =
3232+ let reply, resolve_reply = Promise.create () in
3333+ Eio.Stream.add stream ({ description; request; output_file }, resolve_reply);
3434+ Promise.await reply
3535+3636+let start_workers env sw n =
3737+ let spawn_worker name =
3838+ Fiber.fork_daemon ~sw (fun () ->
3939+ try
4040+ run_worker env name;
4141+ `Stop_daemon
4242+ with Stdlib.Exit -> `Stop_daemon)
4343+ in
4444+ for i = 0 to n - 1 do
4545+ spawn_worker i
4646+ done;
4747+ ()
···2929 | Some (mv, outstanding_execution) ->
3030 Brr.G.stop_timer outstanding_execution;
3131 let msg = Message.Ev.data (Brr.Ev.as_type msg) in
3232- Js_of_ocaml.Console.console##log (Js_of_ocaml.Js.string "Client received the following, to be converted to an OCaml string");
3232+ Js_of_ocaml.Console.console##log
3333+ (Js_of_ocaml.Js.string
3434+ "Client received the following, to be converted to an OCaml \
3535+ string");
3336 Js_of_ocaml.Console.console##log msg;
3437 let msg = Js_of_ocaml.Js.to_string msg in
3538 (* log (Printf.sprintf "Client received: %s" msg); *)
···99102 bool ->
100103 string ->
101104 (Toplevel_api_gen.error list, Toplevel_api_gen.err) result Lwt.t
105105+102106 val compile_js :
103107 rpc ->
104108 string option ->
···113117 let setup rpc a = Wraw.setup rpc a |> Rpc_lwt.T.get
114118 let typecheck rpc a = Wraw.typecheck rpc a |> Rpc_lwt.T.get
115119 let exec rpc a = Wraw.exec rpc a |> Rpc_lwt.T.get
120120+116121 let query_errors rpc id deps is_toplevel doc =
117122 Wraw.query_errors rpc id deps is_toplevel doc |> Rpc_lwt.T.get
123123+118124 let compile_js rpc id s = Wraw.compile_js rpc id s |> Rpc_lwt.T.get
119125end
+9-3
idl/js_top_worker_client.mli
···5050 (** Execute a phrase using the toplevel. The toplevel must have been
5151 initialised first. *)
52525353- val query_errors : rpc -> string option -> string list -> bool -> string -> (Toplevel_api_gen.error list, err) result Lwt.t
5353+ val query_errors :
5454+ rpc ->
5555+ string option ->
5656+ string list ->
5757+ bool ->
5858+ string ->
5959+ (Toplevel_api_gen.error list, err) result Lwt.t
5460 (** Query the toplevel for errors. The first argument is the phrase to check
5555- for errors. If it is [None], the toplevel will return all errors. If it
5656- is [Some s], the toplevel will return only errors related to [s]. *)
6161+ for errors. If it is [None], the toplevel will return all errors. If it is
6262+ [Some s], the toplevel will return only errors related to [s]. *)
57635864 val compile_js : rpc -> string option -> string -> (string, err) result Lwt.t
5965end
+4-1
idl/js_top_worker_client_fut.ml
···8282 let typecheck rpc a = Wraw.typecheck rpc a |> Rpc_fut.T.get
8383 let exec rpc a = Wraw.exec rpc a |> Rpc_fut.T.get
8484 let compile_js rpc id s = Wraw.compile_js rpc id s |> Rpc_fut.T.get
8585- let query_errors rpc id deps is_toplevel doc = Wraw.query_errors rpc id deps is_toplevel doc |> Rpc_fut.T.get
8585+8686+ let query_errors rpc id deps is_toplevel doc =
8787+ Wraw.query_errors rpc id deps is_toplevel doc |> Rpc_fut.T.get
8888+8689 let exec_toplevel rpc doc = Wraw.exec_toplevel rpc doc |> Rpc_fut.T.get
87908891 let complete_prefix rpc id deps is_toplevel doc pos =
+1-2
idl/toplevel_api.ml
···184184[@@deriving rpcty]
185185186186type init_config = {
187187- findlib_index : string; (** URL to the findlib index file *)
188187 findlib_requires : string list; (** Findlib packages to require *)
189189- stdlib_dcs : string; (** URL to the dynamic cmis for the OCaml standard library *)
188188+ stdlib_dcs : string option; (** URL to the dynamic cmis for the OCaml standard library *)
190189 execute : bool (** Whether this session should support execution or not. *)
191190} [@@deriving rpcty]
192191type err = InternalError of string [@@deriving rpcty]
+15-32
idl/toplevel_api_gen.ml
···19711971 end[@@ocaml.doc "@inline"][@@merlin.hide ]
19721972type init_config =
19731973 {
19741974- findlib_index: string [@ocaml.doc " URL to the findlib index file "];
19751974 findlib_requires: string list [@ocaml.doc " Findlib packages to require "];
19761976- stdlib_dcs: string
19751975+ stdlib_dcs: string option
19771976 [@ocaml.doc " URL to the dynamic cmis for the OCaml standard library "];
19781977 execute: bool
19791978 [@ocaml.doc " Whether this session should support execution or not. "]}
···19811980include
19821981 struct
19831982 let _ = fun (_ : init_config) -> ()
19841984- let rec init_config_findlib_index : (_, init_config) Rpc.Types.field =
19851985- {
19861986- Rpc.Types.fname = "findlib_index";
19871987- Rpc.Types.field = (let open Rpc.Types in Basic String);
19881988- Rpc.Types.fdefault = None;
19891989- Rpc.Types.fdescription = ["URL to the findlib index file"];
19901990- Rpc.Types.fversion = None;
19911991- Rpc.Types.fget = (fun _r -> _r.findlib_index);
19921992- Rpc.Types.fset = (fun v _s -> { _s with findlib_index = v })
19931993- }
19941994- and init_config_findlib_requires : (_, init_config) Rpc.Types.field =
19831983+ let rec init_config_findlib_requires : (_, init_config) Rpc.Types.field =
19951984 {
19961985 Rpc.Types.fname = "findlib_requires";
19971986 Rpc.Types.field =
···20051994 and init_config_stdlib_dcs : (_, init_config) Rpc.Types.field =
20061995 {
20071996 Rpc.Types.fname = "stdlib_dcs";
20082008- Rpc.Types.field = (let open Rpc.Types in Basic String);
19971997+ Rpc.Types.field =
19981998+ (Rpc.Types.Option (let open Rpc.Types in Basic String));
20091999 Rpc.Types.fdefault = None;
20102000 Rpc.Types.fdescription =
20112001 ["URL to the dynamic cmis for the OCaml standard library"];
···20282018 Rpc.Types.Struct
20292019 ({
20302020 Rpc.Types.fields =
20312031- [Rpc.Types.BoxedField init_config_findlib_index;
20322032- Rpc.Types.BoxedField init_config_findlib_requires;
20212021+ [Rpc.Types.BoxedField init_config_findlib_requires;
20332022 Rpc.Types.BoxedField init_config_stdlib_dcs;
20342023 Rpc.Types.BoxedField init_config_execute];
20352024 Rpc.Types.sname = "init_config";
···20422031 >>=
20432032 (fun init_config_execute ->
20442033 (getter.Rpc.Types.field_get "stdlib_dcs"
20452045- (let open Rpc.Types in Basic String))
20342034+ (Rpc.Types.Option
20352035+ (let open Rpc.Types in Basic String)))
20462036 >>=
20472037 (fun init_config_stdlib_dcs ->
20482038 (getter.Rpc.Types.field_get "findlib_requires"
···20502040 (let open Rpc.Types in Basic String)))
20512041 >>=
20522042 (fun init_config_findlib_requires ->
20532053- (getter.Rpc.Types.field_get "findlib_index"
20542054- (let open Rpc.Types in Basic String))
20552055- >>=
20562056- (fun init_config_findlib_index ->
20572057- return
20582058- {
20592059- findlib_index =
20602060- init_config_findlib_index;
20612061- findlib_requires =
20622062- init_config_findlib_requires;
20632063- stdlib_dcs = init_config_stdlib_dcs;
20642064- execute = init_config_execute
20652065- })))))
20432043+ return
20442044+ {
20452045+ findlib_requires =
20462046+ init_config_findlib_requires;
20472047+ stdlib_dcs = init_config_stdlib_dcs;
20482048+ execute = init_config_execute
20492049+ }))))
20662050 } : init_config Rpc.Types.structure)
20672051 and init_config =
20682052 {
···20702054 Rpc.Types.description = [];
20712055 Rpc.Types.ty = typ_of_init_config
20722056 }
20732073- let _ = init_config_findlib_index
20742074- and _ = init_config_findlib_requires
20572057+ let _ = init_config_findlib_requires
20752058 and _ = init_config_stdlib_dcs
20762059 and _ = init_config_execute
20772060 and _ = typ_of_init_config
···148148 | Error m ->
149149 Jslib.log "Failed to parse uri: %s" m;
150150 None)
151151- metas |> flatten_libs
151151+ metas
152152+ |> flatten_libs
152153153154let require sync_get cmi_only v packages =
154155 let rec require dcss package :
+179-145
lib/impl.ml
···991010let is_mangled_broken orig src =
1111 String.length orig <> String.length src
1212- ||
1313- Seq.exists2 (fun c c' ->
1414- c <> c' && c' <> ' ') (String.to_seq orig) (String.to_seq src)
1212+ || Seq.exists2
1313+ (fun c c' -> c <> c' && c' <> ' ')
1414+ (String.to_seq orig) (String.to_seq src)
15151616let mangle_toplevel is_toplevel orig_source deps =
1717 let src =
1818- if not is_toplevel then
1919- orig_source
1818+ if not is_toplevel then orig_source
1919+ else if
2020+ String.length orig_source < 2
2121+ || orig_source.[0] <> '#'
2222+ || orig_source.[1] <> ' '
2323+ then (
2424+ Logs.err (fun m ->
2525+ m "xx Warning, ignoring toplevel block without a leading '# '.\n%!");
2626+ orig_source)
2027 else
2121- if
2222- String.length orig_source < 2 || orig_source.[0] <> '#' || orig_source.[1] <> ' '
2323- then (Logs.err (fun m -> m "xx Warning, ignoring toplevel block without a leading '# '.\n%!"); orig_source)
2424- else begin
2525- try
2626- let s = String.sub orig_source 2 (String.length orig_source - 2) in
2727- let list =
2828- try Ocamltop.parse_toplevel s with _ -> Ocamltop.fallback_parse_toplevel s in
2929- let lines =List.map (fun (phr, junk, output) ->
3030- let l1 = Printf.sprintf " %s%s" phr (String.make (String.length junk) ' ') in
3131- match output with
3232- | [] -> l1
3333- | _ ->
3434- let s = List.map (fun x ->
3535- String.make (String.length x) ' ') output
2828+ try
2929+ let s = String.sub orig_source 2 (String.length orig_source - 2) in
3030+ let list =
3131+ try Ocamltop.parse_toplevel s
3232+ with _ -> Ocamltop.fallback_parse_toplevel s
3333+ in
3434+ let lines =
3535+ List.map
3636+ (fun (phr, junk, output) ->
3737+ let l1 =
3838+ Printf.sprintf " %s%s" phr
3939+ (String.make (String.length junk) ' ')
3640 in
3737- (String.concat "\n" (l1 :: s));
3838- ) list in
3939- String.concat "\n" lines
4040- with e ->
4141- Logs.err (fun m -> m "Error in mangle_toplevel: %s" (Printexc.to_string e));
4242- let ppf = Format.err_formatter in
4343- let _ = Location.report_exception ppf e in
4444- orig_source
4545- end
4141+ match output with
4242+ | [] -> l1
4343+ | _ ->
4444+ let s =
4545+ List.map (fun x -> String.make (String.length x) ' ') output
4646+ in
4747+ String.concat "\n" (l1 :: s))
4848+ list
4949+ in
5050+ String.concat "\n" lines
5151+ with e ->
5252+ Logs.err (fun m ->
5353+ m "Error in mangle_toplevel: %s" (Printexc.to_string e));
5454+ let ppf = Format.err_formatter in
5555+ let _ = Location.report_exception ppf e in
5656+ orig_source
4657 in
4747- let line1 = List.map (fun id ->
4848- Printf.sprintf "open %s" (modname_of_id id)) deps |> String.concat " " in
5858+ let line1 =
5959+ List.map (fun id -> Printf.sprintf "open %s" (modname_of_id id)) deps
6060+ |> String.concat " "
6161+ in
4962 let line1 = line1 ^ ";;\n" in
5063 Logs.debug (fun m -> m "Line1: %s\n%!" line1);
5164 Logs.debug (fun m -> m "Source: %s\n%!" src);
5252- if is_mangled_broken orig_source src
5353- then (
6565+ if is_mangled_broken orig_source src then (
5466 Printf.printf "Warning: mangled source is broken\n%!";
5567 Printf.printf "orig length: %d\n%!" (String.length orig_source);
5656- Printf.printf "src length: %d\n%!" (String.length src);
5757- );
5858- line1, src
6868+ Printf.printf "src length: %d\n%!" (String.length src));
6969+ (line1, src)
59706071module JsooTopPpx = struct
6172 open Js_of_ocaml_compiler.Stdlib
···96107 val init_function : string -> unit -> unit
97108 val get_stdlib_dcs : string -> Toplevel_api_gen.dynamic_cmis list
98109 val findlib_init : string -> findlib_t
9999- val require : bool -> findlib_t -> string list -> Toplevel_api_gen.dynamic_cmis list
110110+111111+ val require :
112112+ bool -> findlib_t -> string list -> Toplevel_api_gen.dynamic_cmis list
100113end
101114102115module Make (S : S) = struct
···260273 Printf.sprintf "%s.cmi" (String.uncapitalize_ascii unit_name)
261274262275 let get_dirs () =
263263- let {Load_path.visible; hidden} = Load_path.get_paths () in
276276+ let { Load_path.visible; hidden } = Load_path.get_paths () in
264277 visible @ hidden
265278266279 let reset_dirs () =
···344357 Logs.info (fun m -> m "init()");
345358 path := Some "/static/cmis";
346359347347- findlib_v := Some (S.findlib_init init_libs.findlib_index);
348348-349349- (match S.get_stdlib_dcs init_libs.stdlib_dcs with
360360+ findlib_v := Some (S.findlib_init "findlib_index");
361361+ let stdlib_dcs =
362362+ match init_libs.stdlib_dcs with
363363+ | Some dcs -> dcs
364364+ | None -> "lib/ocaml/dynamic_cmis.json"
365365+ in
366366+ (match S.get_stdlib_dcs stdlib_dcs with
350367 | [ dcs ] -> add_dynamic_cmis dcs
351368 | _ -> ());
352369 Clflags.no_check_prims := true;
···384401 in
385402386403 let dcs =
387387- match !findlib_v with Some v -> S.require (not !execution_allowed) v !requires | None -> []
404404+ match !findlib_v with
405405+ | Some v -> S.require (not !execution_allowed) v !requires
406406+ | None -> []
388407 in
389408 List.iter add_dynamic_cmis dcs;
390409···532551 Symtable.check_global_initialized reloc;
533552 Symtable.update_global_table(); *)
534553 let oc = open_out "/tmp/test.cmo" in
535535- Emitcode.marshal_to_channel_with_possibly_32bit_compat ~filename:"/tmp/test.cmo" ~kind:"bytecode unit" oc cmo;
554554+ Emitcode.marshal_to_channel_with_possibly_32bit_compat
555555+ ~filename:"/tmp/test.cmo" ~kind:"bytecode unit" oc cmo;
536556537557 (* let code = String.init (Misc.LongString.length code) ~f:(fun i -> Misc.LongString.get code i) in *)
538558 close_out oc;
···559579 then (
560580 Printf.eprintf
561581 "Warning, ignoring toplevel block without a leading '# '.\n";
562562- IdlM.ErrM.return { Toplevel_api_gen.script = stripped; mime_vals = []; parts=[] })
582582+ IdlM.ErrM.return
583583+ { Toplevel_api_gen.script = stripped; mime_vals = []; parts = [] })
563584 else
564585 let s = String.sub stripped 2 (String.length stripped - 2) in
565586 let list = Ocamltop.parse_toplevel s in
···588609 let content_txt =
589610 String.sub content_txt 0 (String.length content_txt - 1)
590611 in
591591- let result = { Toplevel_api_gen.script = content_txt; mime_vals; parts=[] } in
612612+ let result =
613613+ { Toplevel_api_gen.script = content_txt; mime_vals; parts = [] }
614614+ in
592615 IdlM.ErrM.return result
593616594617 let exec_toplevel (phrase : string) =
595595- try handle_toplevel phrase with e ->
618618+ try handle_toplevel phrase
619619+ with e ->
596620 Logs.info (fun m -> m "Error: %s" (Printexc.to_string e));
597621 IdlM.ErrM.return_err
598622 (Toplevel_api_gen.InternalError (Printexc.to_string e))
···707731 Some (from, to_, wdispatch source query)
708732 end
709733710710- module StringSet = Set.Make (String)
711711- let failed_cells = ref StringSet.empty
712712-734734+ module StringSet = Set.Make (String)
713735736736+ let failed_cells = ref StringSet.empty
714737715738 let complete_prefix _id _deps is_toplevel source position =
716716- try begin
717717- let line1, src = mangle_toplevel is_toplevel source [] in
718718- let src= line1 ^ src in
719719- let source = Merlin_kernel.Msource.make src in
720720- let map_kind :
721721- [ `Value
722722- | `Constructor
723723- | `Variant
724724- | `Label
725725- | `Module
726726- | `Modtype
727727- | `Type
728728- | `MethodCall
729729- | `Keyword ] ->
730730- Toplevel_api_gen.kind_ty = function
731731- | `Value -> Value
732732- | `Constructor -> Constructor
733733- | `Variant -> Variant
734734- | `Label -> Label
735735- | `Module -> Module
736736- | `Modtype -> Modtype
737737- | `Type -> Type
738738- | `MethodCall -> MethodCall
739739- | `Keyword -> Keyword
740740- in
741741- let position =
742742- match position with
743743- | Toplevel_api_gen.Start -> `Offset (String.length line1)
744744- | Offset x -> `Offset (x + String.length line1)
745745- | Logical (x, y) -> `Logical (x + 1, y)
746746- | End -> `End
747747- in
748748- match Completion.at_pos source position with
749749- | Some (from, to_, compl) ->
750750- let entries =
751751- List.map
752752- (fun (entry : Query_protocol.Compl.entry) ->
753753- {
754754- Toplevel_api_gen.name = entry.name;
755755- kind = map_kind entry.kind;
756756- desc = entry.desc;
757757- info = entry.info;
758758- deprecated = entry.deprecated;
759759- })
760760- compl.entries
761761- in
762762- IdlM.ErrM.return { Toplevel_api_gen.from; to_; entries }
763763- | None ->
764764- IdlM.ErrM.return { Toplevel_api_gen.from = 0; to_ = 0; entries = [] }
765765- end
739739+ try
740740+ let line1, src = mangle_toplevel is_toplevel source [] in
741741+ let src = line1 ^ src in
742742+ let source = Merlin_kernel.Msource.make src in
743743+ let map_kind :
744744+ [ `Value
745745+ | `Constructor
746746+ | `Variant
747747+ | `Label
748748+ | `Module
749749+ | `Modtype
750750+ | `Type
751751+ | `MethodCall
752752+ | `Keyword ] ->
753753+ Toplevel_api_gen.kind_ty = function
754754+ | `Value -> Value
755755+ | `Constructor -> Constructor
756756+ | `Variant -> Variant
757757+ | `Label -> Label
758758+ | `Module -> Module
759759+ | `Modtype -> Modtype
760760+ | `Type -> Type
761761+ | `MethodCall -> MethodCall
762762+ | `Keyword -> Keyword
763763+ in
764764+ let position =
765765+ match position with
766766+ | Toplevel_api_gen.Start -> `Offset (String.length line1)
767767+ | Offset x -> `Offset (x + String.length line1)
768768+ | Logical (x, y) -> `Logical (x + 1, y)
769769+ | End -> `End
770770+ in
771771+ match Completion.at_pos source position with
772772+ | Some (from, to_, compl) ->
773773+ let entries =
774774+ List.map
775775+ (fun (entry : Query_protocol.Compl.entry) ->
776776+ {
777777+ Toplevel_api_gen.name = entry.name;
778778+ kind = map_kind entry.kind;
779779+ desc = entry.desc;
780780+ info = entry.info;
781781+ deprecated = entry.deprecated;
782782+ })
783783+ compl.entries
784784+ in
785785+ IdlM.ErrM.return { Toplevel_api_gen.from; to_; entries }
786786+ | None ->
787787+ IdlM.ErrM.return { Toplevel_api_gen.from = 0; to_ = 0; entries = [] }
766788 with e ->
767789 Logs.info (fun m -> m "Error: %s" (Printexc.to_string e));
768790 IdlM.ErrM.return_err
···782804 let oc = open_out filename in
783805 Printf.fprintf oc "%s" source;
784806 close_out oc;
785785- (try Sys.remove (prefix ^ ".cmi") with | Sys_error _ -> ());
807807+ (try Sys.remove (prefix ^ ".cmi") with Sys_error _ -> ());
786808 let unit_info = Unit_info.make ~source_file:filename prefix in
787809 try
788810 let store = Local_store.fresh () in
789811 Local_store.with_store store (fun () ->
790790- Local_store.reset ();
791791- let env = Typemod.initial_env ~loc ~initially_opened_module:(Some "Stdlib") ~open_implicit_modules:dep_modules in
792792- let lexbuf = Lexing.from_string source in
793793- let ast = Parse.implementation lexbuf in
794794- Logs.info (fun m -> m "About to type_implementation");
795795- let _ = Typemod.type_implementation unit_info env ast in
796796- let b = Sys.file_exists (prefix ^ ".cmi") in
797797- failed_cells := StringSet.remove id !failed_cells;
798798- Logs.info (fun m -> m "file_exists: %s = %b" (prefix ^ ".cmi") b));
812812+ Local_store.reset ();
813813+ let env =
814814+ Typemod.initial_env ~loc ~initially_opened_module:(Some "Stdlib")
815815+ ~open_implicit_modules:dep_modules
816816+ in
817817+ let lexbuf = Lexing.from_string source in
818818+ let ast = Parse.implementation lexbuf in
819819+ Logs.info (fun m -> m "About to type_implementation");
820820+ let _ = Typemod.type_implementation unit_info env ast in
821821+ let b = Sys.file_exists (prefix ^ ".cmi") in
822822+ failed_cells := StringSet.remove id !failed_cells;
823823+ Logs.info (fun m -> m "file_exists: %s = %b" (prefix ^ ".cmi") b));
799824 (* reset_dirs () *) ()
800825 with
801826 | Env.Error e ->
802802- Logs.err (fun m -> m "Env.Error: %a" Env.report_error e);
803803- failed_cells := StringSet.add id !failed_cells;
804804- ()
827827+ Logs.err (fun m -> m "Env.Error: %a" Env.report_error e);
828828+ failed_cells := StringSet.add id !failed_cells;
829829+ ()
805830 | exn ->
806806- let s = Printexc.to_string exn in
807807- Logs.err (fun m -> m "Error in add_cmi: %s" s);
808808- Logs.err (fun m -> m "Backtrace: %s" (Printexc.get_backtrace ()));
809809- let ppf = Format.err_formatter in
810810- let _ = Location.report_exception ppf exn in
811811- failed_cells := StringSet.add id !failed_cells;
812812- ()
813813-831831+ let s = Printexc.to_string exn in
832832+ Logs.err (fun m -> m "Error in add_cmi: %s" s);
833833+ Logs.err (fun m -> m "Backtrace: %s" (Printexc.get_backtrace ()));
834834+ let ppf = Format.err_formatter in
835835+ let _ = Location.report_exception ppf exn in
836836+ failed_cells := StringSet.add id !failed_cells;
837837+ ()
814838815839 let map_pos line1 pos =
816816- Lexing.{ pos with
817817- pos_bol = pos.pos_bol - String.length line1;
818818- pos_lnum = pos.pos_lnum - 1;
819819- pos_cnum = pos.pos_cnum - String.length line1;
820820- }
840840+ Lexing.
841841+ {
842842+ pos with
843843+ pos_bol = pos.pos_bol - String.length line1;
844844+ pos_lnum = pos.pos_lnum - 1;
845845+ pos_cnum = pos.pos_cnum - String.length line1;
846846+ }
821847822848 let map_loc line1 (loc : Ocaml_parsing.Location.t) =
823823- { loc with
824824- Ocaml_utils.Warnings.loc_start = map_pos line1 loc.loc_start;
825825- Ocaml_utils.Warnings.loc_end = map_pos line1 loc.loc_end;
826826- }
849849+ {
850850+ loc with
851851+ Ocaml_utils.Warnings.loc_start = map_pos line1 loc.loc_start;
852852+ Ocaml_utils.Warnings.loc_end = map_pos line1 loc.loc_end;
853853+ }
827854828855 let query_errors id deps is_toplevel orig_source =
829856 try
830830- let deps = List.filter (fun dep -> not (StringSet.mem dep !failed_cells)) deps in
857857+ let deps =
858858+ List.filter (fun dep -> not (StringSet.mem dep !failed_cells)) deps
859859+ in
831860 (* Logs.info (fun m -> m "About to mangle toplevel"); *)
832861 let line1, src = mangle_toplevel is_toplevel orig_source deps in
833862 let id = Option.get id in
···846875 Ocaml_parsing.Location.print_sub_msg Format.str_formatter sub;
847876 String.trim (Format.flush_str_formatter ())
848877 in
849849- let loc = map_loc line1 (Ocaml_parsing.Location.loc_of_report error) in
878878+ let loc =
879879+ map_loc line1 (Ocaml_parsing.Location.loc_of_report error)
880880+ in
850881851882 let main =
852883 Format.asprintf "@[%a@]" Ocaml_parsing.Location.print_main
853884 error
854885 |> String.trim
855886 in
856856- if loc.loc_start.pos_lnum = 0 then None else Some
857857- {
858858- Toplevel_api_gen.kind;
859859- loc;
860860- main;
861861- sub = StdLabels.List.map ~f:of_sub sub;
862862- source;
863863- })
887887+ if loc.loc_start.pos_lnum = 0 then None
888888+ else
889889+ Some
890890+ {
891891+ Toplevel_api_gen.kind;
892892+ loc;
893893+ main;
894894+ sub = StdLabels.List.map ~f:of_sub sub;
895895+ source;
896896+ })
864897 in
865865- if List.length errors = 0 then
866866- add_cmi id deps src;
898898+ if List.length errors = 0 then add_cmi id deps src;
867899 (* Logs.info (fun m -> m "Got to end"); *)
868900 IdlM.ErrM.return errors
869901 with e ->
···873905874906 let type_enclosing _id deps is_toplevel orig_source position =
875907 try
876876- let deps = List.filter (fun dep -> not (StringSet.mem dep !failed_cells)) deps in
908908+ let deps =
909909+ List.filter (fun dep -> not (StringSet.mem dep !failed_cells)) deps
910910+ in
877911 let line1, src = mangle_toplevel is_toplevel orig_source deps in
878912 let src = line1 ^ src in
879913 let position =
880914 match position with
881915 | Toplevel_api_gen.Start -> `Start
882916 | Offset x -> `Offset (x + String.length line1)
883883- | Logical (x, y) -> `Logical (x+1, y)
917917+ | Logical (x, y) -> `Logical (x + 1, y)
884918 | End -> `End
885919 in
886920 let source = Merlin_kernel.Msource.make src in
···897931 in
898932 let enclosing =
899933 List.map
900900- (fun (x, y, z) -> (map_loc line1 x, map_index_or_string y, map_tail_position z))
934934+ (fun (x, y, z) ->
935935+ (map_loc line1 x, map_index_or_string y, map_tail_position z))
901936 enclosing
902937 in
903938 IdlM.ErrM.return enclosing
···905940 Logs.info (fun m -> m "Error: %s" (Printexc.to_string e));
906941 IdlM.ErrM.return_err
907942 (Toplevel_api_gen.InternalError (Printexc.to_string e))
908908-909943end
+6-4
lib/ocamltop.ml
···1717 Printf.printf "Got phrase\n%!";
1818 let new_pos = Lexing.lexeme_end lexbuf in
1919 let phr = String.sub s pos (new_pos - pos) in
2020- let (junk, (cont, output)) = Toplexer.entry lexbuf in
2020+ let junk, (cont, output) = Toplexer.entry lexbuf in
2121 let new_pos = Lexing.lexeme_end lexbuf in
2222- if cont then (phr, junk, output) :: loop new_pos else [ (phr, junk, output) ]
2222+ if cont then (phr, junk, output) :: loop new_pos
2323+ else [ (phr, junk, output) ]
2324 in
2425 loop 0
2526···2930 let _phr = !Toploop.parse_toplevel_phrase lexbuf in
3031 let new_pos = Lexing.lexeme_end lexbuf in
3132 let phr = String.sub s pos (new_pos - pos) in
3232- let (junk, (cont, output)) = Toplexer.entry lexbuf in
3333+ let junk, (cont, output) = Toplexer.entry lexbuf in
3334 let new_pos = Lexing.lexeme_end lexbuf in
3434- if cont then (phr, junk, output) :: loop new_pos else [ (phr, junk, output) ]
3535+ if cont then (phr, junk, output) :: loop new_pos
3636+ else [ (phr, junk, output) ]
3537 in
3638 loop 0
+9-6
lib/worker.ml
···53535454 let sync_get = Jslib.sync_get
5555 let create_file = Js_of_ocaml.Sys_js.create_file
5656- let get_stdlib_dcs uri = Findlibish.fetch_dynamic_cmis sync_get uri |> Result.to_list
5656+5757+ let get_stdlib_dcs uri =
5858+ Findlibish.fetch_dynamic_cmis sync_get uri |> Result.to_list
5959+5760 let import_scripts = Js_of_ocaml.Worker.import_scripts
5861 let findlib_init = Findlibish.init sync_get
5962···69727073module M = Impl.Make (S)
71747272-let test () =
7575+let test () =
7376 let oc = open_out "/tmp/mytest.txt" in
7477 Printf.fprintf oc "Hello, world\n%!";
7578 close_out oc
7676-7979+7780let run () =
7881 (* Here we bind the server stub functions to the implementations *)
7982 let open Js_of_ocaml in
···9598 Server.exec_toplevel exec_toplevel;
9699 let rpc_fn = Impl.IdlM.server Server.implementation in
97100 Js_of_ocaml.Worker.set_onmessage (fun x ->
9898- let s = Js_of_ocaml.Js.to_string x in
9999- Jslib.log "Worker received: %s" s;
100100- ignore (server rpc_fn s));
101101+ let s = Js_of_ocaml.Js.to_string x in
102102+ Jslib.log "Worker received: %s" s;
103103+ ignore (server rpc_fn s));
101104 Console.console##log (Js.string "All finished")
102105 with e ->
103106 Console.console##log (Js.string ("Exception: " ^ Printexc.to_string e))
···11 $ ./script.sh
22- unix_worker: [INFO] init()
33- unix_worker: [INFO] init() finished
44- N
55- unix_worker: [INFO] setup() ...
66- unix_worker: [INFO] Setup complete
77- unix_worker: [INFO] setup() finished
88- {mime_vals:[];stderr:S(error while evaluating #enable "pretty";;
99- error while evaluating #disable "shortvar";;);stdout:S(OCaml version 5.2.0
1010- Unknown directive enable.
1111- Unknown directive disable.)}
1212- {mime_vals:[];parts:[];script:S(# Printf.printf "Hello, world\n";;
1313- Hello, world
1414- - : unit = ())}
1515- {mime_vals:[];parts:[];script:S(# let x = 1 + 2;;
1616- val x : int = 3
1717- # let x = 2+3;;
1818- val x : int = 5)}
1919- {mime_vals:[];parts:[];script:S(# let x = 1 + 2;;
2020- val x : int = 3
2121- # let x = 2+3;;
2222- val x : int = 5)}
22+ cli: internal error, uncaught exception:
33+ End_of_file
44+ Raised at Stdlib.unsafe_really_input in file "stdlib.ml", line 429, characters 9-26
55+ Called from Dune__exe__Unix_client.binary_rpc in file "example/unix_client.ml", line 20, characters 2-30
66+ Called from Cmdlinergen.Gen.declare_.generate.inner.run in file "src/lib/cmdlinergen.ml", line 185, characters 27-35
77+ Called from Cmdliner_term.app.(fun) in file "cmdliner_term.ml", line 24, characters 19-24
88+ Called from Cmdliner_eval.run_parser in file "cmdliner_eval.ml", line 35, characters 37-44
99+ Fatal error: exception Idl.MarshalError("No value found for key: 'execute' when unmarshalling 'init_config'")
1010+ Raised at Idl.IdM.fail in file "src/lib/idl.ml", line 425, characters 15-22
1111+ Called from Dune__exe__Unix_worker.start_server.process in file "example/unix_worker.ml", line 167, characters 4-62
1212+ Called from Dune__exe__Unix_worker.binary_handler in file "example/unix_worker.ml", line 63, characters 2-17
1313+ Called from Dune__exe__Unix_worker.serve_requests.(fun) in file "example/unix_worker.ml", line 92, characters 8-44
1414+ Called from Stdlib__Fun.protect in file "fun.ml", line 34, characters 8-15
1515+ Re-raised at Stdlib__Fun.protect in file "fun.ml", line 39, characters 6-52
1616+ Called from Dune__exe__Unix_worker.serve_requests in file "example/unix_worker.ml", lines 86-92, characters 4-54
1717+ Called from Dune__exe__Unix_worker in file "example/unix_worker.ml", line 172, characters 8-23
1818+ cli: internal error, uncaught exception:
1919+ End_of_file
2020+ Raised at Stdlib.unsafe_really_input in file "stdlib.ml", line 429, characters 9-26
2121+ Called from Dune__exe__Unix_client.binary_rpc in file "example/unix_client.ml", line 20, characters 2-30
2222+ Called from Cmdlinergen.Gen.declare_.generate.inner.run in file "src/lib/cmdlinergen.ml", line 185, characters 27-35
2323+ Called from Cmdliner_term.app.(fun) in file "cmdliner_term.ml", line 24, characters 19-24
2424+ Called from Cmdliner_eval.run_parser in file "cmdliner_eval.ml", line 35, characters 37-44
2525+ cli: internal error, uncaught exception:
2626+ Unix.Unix_error(Unix.ECONNREFUSED, "connect", "")
2727+ Raised by primitive operation at Dune__exe__Unix_client.binary_rpc in file "example/unix_client.ml", line 11, characters 2-25
2828+ Called from Cmdlinergen.Gen.declare_.generate.inner.run in file "src/lib/cmdlinergen.ml", line 185, characters 27-35
2929+ Called from Cmdliner_term.app.(fun) in file "cmdliner_term.ml", line 24, characters 19-24
3030+ Called from Cmdliner_eval.run_parser in file "cmdliner_eval.ml", line 35, characters 37-44
3131+ cli: internal error, uncaught exception:
3232+ Unix.Unix_error(Unix.ECONNREFUSED, "connect", "")
3333+ Raised by primitive operation at Dune__exe__Unix_client.binary_rpc in file "example/unix_client.ml", line 11, characters 2-25
3434+ Called from Cmdlinergen.Gen.declare_.generate.inner.run in file "src/lib/cmdlinergen.ml", line 185, characters 27-35
3535+ Called from Cmdliner_term.app.(fun) in file "cmdliner_term.ml", line 24, characters 19-24
3636+ Called from Cmdliner_eval.run_parser in file "cmdliner_eval.ml", line 35, characters 37-44
3737+ cli: internal error, uncaught exception:
3838+ Unix.Unix_error(Unix.ECONNREFUSED, "connect", "")
3939+ Raised by primitive operation at Dune__exe__Unix_client.binary_rpc in file "example/unix_client.ml", line 11, characters 2-25
4040+ Called from Cmdlinergen.Gen.declare_.generate.inner.run in file "src/lib/cmdlinergen.ml", line 185, characters 27-35
4141+ Called from Cmdliner_term.app.(fun) in file "cmdliner_term.ml", line 24, characters 19-24
4242+ Called from Cmdliner_eval.run_parser in file "cmdliner_eval.ml", line 35, characters 37-44
4343+ ./script.sh: line 17: kill: (32735) - No such process
4444+ [1]