···8080 let exec rpc a = Wraw.exec rpc a |> Rpc_fut.T.get
8181 let compile_js rpc id s = Wraw.compile_js rpc id s |> Rpc_fut.T.get
8282 let query_errors rpc doc = Wraw.query_errors rpc doc |> Rpc_fut.T.get
8383-8383+ let exec_toplevel rpc doc = Wraw.exec_toplevel rpc doc |> Rpc_fut.T.get
8484+8485 let complete_prefix rpc doc pos =
8586 Wraw.complete_prefix rpc doc pos |> Rpc_fut.T.get
8687
+23
idl/toplevel_api.ml
···166166[@@deriving rpcty]
167167(** Represents the result of executing a toplevel phrase *)
168168169169+type exec_toplevel_result = {
170170+ script : string;
171171+ mime_vals : mime_val list;
172172+}
173173+[@@deriving rpcty]
174174+(** Represents the result of executing a toplevel script *)
175175+169176type cma = {
170177 url : string; (** URL where the cma is available *)
171178 fn : string; (** Name of the 'wrapping' function *)
···213220 let error_list_p = Param.mk error_list
214221 let typed_enclosings_p = Param.mk typed_enclosings_list
215222223223+ let toplevel_script_p = Param.mk ~description:[
224224+ "A toplevel script is a sequence of toplevel phrases interspersed with";
225225+ "The output from the toplevel. Each phase must be preceded by '# ', and";
226226+ "the output from the toplevel is indented by 2 spaces."
227227+ ] Types.string
228228+229229+ let exec_toplevel_result_p = Param.mk exec_toplevel_result
230230+216231 let init_libs =
217232 Param.mk ~name:"init_libs"
218233 ~description:
···249264 "Initialised first.";
250265 ]
251266 (phrase_p @-> returning exec_result_p err)
267267+268268+ let exec_toplevel =
269269+ declare "exec_toplevel"
270270+ [
271271+ "Execute a toplevel script. The toplevel must have been";
272272+ "Initialised first. Returns the updated toplevel script.";
273273+ ]
274274+ (toplevel_script_p @-> returning exec_toplevel_result_p err)
252275253276 let compile_js =
254277 declare "compile_js"
+78
idl/toplevel_api_gen.ml
···18231823 and _ = typ_of_exec_result
18241824 and _ = exec_result
18251825 end[@@ocaml.doc "@inline"][@@merlin.hide ]
18261826+type exec_toplevel_result = {
18271827+ script: string ;
18281828+ mime_vals: mime_val list }[@@deriving rpcty][@@ocaml.doc
18291829+ " Represents the result of executing a toplevel script "]
18301830+include
18311831+ struct
18321832+ let _ = fun (_ : exec_toplevel_result) -> ()
18331833+ let rec exec_toplevel_result_script :
18341834+ (_, exec_toplevel_result) Rpc.Types.field =
18351835+ {
18361836+ Rpc.Types.fname = "script";
18371837+ Rpc.Types.field = (let open Rpc.Types in Basic String);
18381838+ Rpc.Types.fdefault = None;
18391839+ Rpc.Types.fdescription = [];
18401840+ Rpc.Types.fversion = None;
18411841+ Rpc.Types.fget = (fun _r -> _r.script);
18421842+ Rpc.Types.fset = (fun v -> fun _s -> { _s with script = v })
18431843+ }
18441844+ and exec_toplevel_result_mime_vals :
18451845+ (_, exec_toplevel_result) Rpc.Types.field =
18461846+ {
18471847+ Rpc.Types.fname = "mime_vals";
18481848+ Rpc.Types.field = (Rpc.Types.List typ_of_mime_val);
18491849+ Rpc.Types.fdefault = None;
18501850+ Rpc.Types.fdescription = [];
18511851+ Rpc.Types.fversion = None;
18521852+ Rpc.Types.fget = (fun _r -> _r.mime_vals);
18531853+ Rpc.Types.fset = (fun v -> fun _s -> { _s with mime_vals = v })
18541854+ }
18551855+ and typ_of_exec_toplevel_result =
18561856+ Rpc.Types.Struct
18571857+ ({
18581858+ Rpc.Types.fields =
18591859+ [Rpc.Types.BoxedField exec_toplevel_result_script;
18601860+ Rpc.Types.BoxedField exec_toplevel_result_mime_vals];
18611861+ Rpc.Types.sname = "exec_toplevel_result";
18621862+ Rpc.Types.version = None;
18631863+ Rpc.Types.constructor =
18641864+ (fun getter ->
18651865+ let open Rresult.R in
18661866+ (getter.Rpc.Types.field_get "mime_vals"
18671867+ (Rpc.Types.List typ_of_mime_val))
18681868+ >>=
18691869+ (fun exec_toplevel_result_mime_vals ->
18701870+ (getter.Rpc.Types.field_get "script"
18711871+ (let open Rpc.Types in Basic String))
18721872+ >>=
18731873+ (fun exec_toplevel_result_script ->
18741874+ return
18751875+ {
18761876+ script = exec_toplevel_result_script;
18771877+ mime_vals = exec_toplevel_result_mime_vals
18781878+ })))
18791879+ } : exec_toplevel_result Rpc.Types.structure)
18801880+ and exec_toplevel_result =
18811881+ {
18821882+ Rpc.Types.name = "exec_toplevel_result";
18831883+ Rpc.Types.description =
18841884+ ["Represents the result of executing a toplevel script"];
18851885+ Rpc.Types.ty = typ_of_exec_toplevel_result
18861886+ }
18871887+ let _ = exec_toplevel_result_script
18881888+ and _ = exec_toplevel_result_mime_vals
18891889+ and _ = typ_of_exec_toplevel_result
18901890+ and _ = exec_toplevel_result
18911891+ end[@@ocaml.doc "@inline"][@@merlin.hide ]
18261892type cma =
18271893 {
18281894 url: string [@ocaml.doc " URL where the cma is available "];
···20512117 let completions_p = Param.mk completions
20522118 let error_list_p = Param.mk error_list
20532119 let typed_enclosings_p = Param.mk typed_enclosings_list
21202120+ let toplevel_script_p =
21212121+ Param.mk
21222122+ ~description:["A toplevel script is a sequence of toplevel phrases interspersed with";
21232123+ "The output from the toplevel. Each phase must be preceded by '# ', and";
21242124+ "the output from the toplevel is indented by 2 spaces."]
21252125+ Types.string
21262126+ let exec_toplevel_result_p = Param.mk exec_toplevel_result
20542127 let init_libs =
20552128 Param.mk ~name:"init_libs"
20562129 ~description:["Libraries to load during the initialisation of the toplevel. ";
···20752148 declare "exec"
20762149 ["Execute a phrase using the toplevel. The toplevel must have been";
20772150 "Initialised first."] (phrase_p @-> (returning exec_result_p err))
21512151+ let exec_toplevel =
21522152+ declare "exec_toplevel"
21532153+ ["Execute a toplevel script. The toplevel must have been";
21542154+ "Initialised first. Returns the updated toplevel script."]
21552155+ (toplevel_script_p @-> (returning exec_toplevel_result_p err))
20782156 let compile_js =
20792157 declare "compile_js"
20802158 ["Compile a phrase to javascript. The toplevel must have been";
···310310311311 let setup () =
312312 try
313313- Logs.info (fun m -> m "setup()");
313313+ Logs.info (fun m -> m "setup() ...");
314314315315 let o =
316316- match !functions with
317317- | Some l -> setup l ()
318318- | None -> failwith "Error: toplevel has not been initialised"
319319- in
316316+317317+ (try
318318+ match !functions with
319319+ | Some l -> setup l ()
320320+ | None -> failwith "Error: toplevel has not been initialised"
321321+ with
322322+ | Persistent_env.Error e ->
323323+ Persistent_env.report_error Format.err_formatter e;
324324+ let err = Format.asprintf "%a" Persistent_env.report_error e in
325325+ failwith ("Error: " ^ err)
326326+ | Env.Error e ->
327327+ Env.report_error Format.err_formatter e;
328328+ let err = Format.asprintf "%a" Env.report_error e in
329329+ failwith ("Error: " ^ err))
330330+ in
331331+332332+ Logs.info (fun m -> m "setup() finished");
333333+320334 IdlM.ErrM.return
321335 Toplevel_api_gen.
322336 {
···484498 | _ -> IdlM.ErrM.return_err (Toplevel_api_gen.InternalError "Parse error")
485499 with e -> IdlM.ErrM.return ("Exception: %s" ^ Printexc.to_string e)
486500501501+ let handle_toplevel stripped =
502502+ if String.length stripped < 2 || stripped.[0] <> '#' || stripped.[1] <> ' ' then begin
503503+ Printf.eprintf "Warning, ignoring toplevel block without a leading '# '.\n";
504504+ IdlM.ErrM.return { Toplevel_api_gen.script=stripped; mime_vals=[] }
505505+ end else begin
506506+ let s = String.sub stripped 2 (String.length stripped - 2) in
507507+ let list = Ocamltop.parse_toplevel s in
508508+ let buf = Buffer.create 1024 in
509509+ let mime_vals = List.fold_left (fun acc (phr, _output) ->
510510+ let new_output = execute phr |> IdlM.T.get |> M.run |> Result.get_ok in
511511+ Printf.bprintf buf "# %s\n" phr;
512512+ let r = (Option.to_list new_output.stdout) @ (Option.to_list new_output.stderr) @ (Option.to_list new_output.caml_ppf) in
513513+ let r = List.concat_map (fun l -> Astring.String.cuts ~sep:"\n" l) r in
514514+ List.iter (fun x -> Printf.bprintf buf " %s\n" x) r;
515515+ let mime_vals = new_output.mime_vals in
516516+ acc @ mime_vals
517517+ ) [] list in
518518+ let content_txt = Buffer.contents buf in
519519+ let content_txt = String.sub content_txt 0 (String.length content_txt - 1) in
520520+ let result = { Toplevel_api_gen.script=content_txt; mime_vals } in
521521+ IdlM.ErrM.return result
522522+ end
523523+524524+ let exec_toplevel (phrase : string) =
525525+ handle_toplevel phrase
526526+487527 let config () =
488528 let path =
489529 match !path with Some p -> p | None -> failwith "Path not set"
···629669 IdlM.ErrM.return { Toplevel_api_gen.from = 0; to_ = 0; entries = [] }
630670631671 let query_errors source =
632632- let source = Merlin_kernel.Msource.make source in
633633- let query =
634634- Query_protocol.Errors { lexing = true; parsing = true; typing = true }
635635- in
636636- let errors =
637637- wdispatch source query
638638- |> StdLabels.List.map
639639- ~f:(fun
640640- (Ocaml_parsing.Location.{ kind; main = _; sub; source } as error)
641641- ->
642642- let of_sub sub =
643643- Ocaml_parsing.Location.print_sub_msg Format.str_formatter sub;
644644- String.trim (Format.flush_str_formatter ())
645645- in
646646- let loc = Ocaml_parsing.Location.loc_of_report error in
647647- let main =
648648- Format.asprintf "@[%a@]" Ocaml_parsing.Location.print_main error
649649- |> String.trim
650650- in
651651- {
652652- Toplevel_api_gen.kind;
653653- loc;
654654- main;
655655- sub = StdLabels.List.map ~f:of_sub sub;
656656- source;
657657- })
658658- in
659659- IdlM.ErrM.return errors
672672+ try
673673+ let source = Merlin_kernel.Msource.make source in
674674+ let query =
675675+ Query_protocol.Errors { lexing = true; parsing = true; typing = true }
676676+ in
677677+ let errors =
678678+ wdispatch source query
679679+ |> StdLabels.List.map
680680+ ~f:(fun
681681+ (Ocaml_parsing.Location.{ kind; main = _; sub; source } as error)
682682+ ->
683683+ let of_sub sub =
684684+ Ocaml_parsing.Location.print_sub_msg Format.str_formatter sub;
685685+ String.trim (Format.flush_str_formatter ())
686686+ in
687687+ let loc = Ocaml_parsing.Location.loc_of_report error in
688688+ let main =
689689+ Format.asprintf "@[%a@]" Ocaml_parsing.Location.print_main error
690690+ |> String.trim
691691+ in
692692+ {
693693+ Toplevel_api_gen.kind;
694694+ loc;
695695+ main;
696696+ sub = StdLabels.List.map ~f:of_sub sub;
697697+ source;
698698+ })
699699+ in
700700+ IdlM.ErrM.return errors
701701+ with e ->
702702+ IdlM.ErrM.return_err
703703+ (Toplevel_api_gen.InternalError (Printexc.to_string e))
660704661705 let type_enclosing source position =
662706 let position =
+24
lib/ocamltop.ml
···11+let refill_lexbuf s p buffer len =
22+ if !p = String.length s then 0
33+ else
44+ let len' =
55+ try (String.index_from s !p '\n' - !p + 1)
66+ with _ -> (String.length s - !p)
77+ in
88+ let len'' = min len len' in
99+ String.blit s !p buffer 0 len'';
1010+ p := !p + len'';
1111+ len''
1212+1313+let parse_toplevel s =
1414+ let s = s in
1515+ let lexbuf = Lexing.from_string s in
1616+ let rec loop pos =
1717+ let _phr = !Toploop.parse_toplevel_phrase lexbuf in
1818+ let new_pos = Lexing.lexeme_end lexbuf in
1919+ let phr = String.sub s pos (new_pos - pos) in
2020+ let (cont, output) = Toplexer.entry lexbuf in
2121+ let new_pos = Lexing.lexeme_end lexbuf in
2222+ if cont then (phr, output) :: loop new_pos else [(phr, output)]
2323+ in
2424+ loop 0