123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862(*
* uTop.ml
* -------
* Copyright : (c) 2011, Jeremie Dimino <jeremie@dimino.org>
* Licence : BSD3
*
* This file is a part of utop.
*)[@@@warning"-27"]openLwt_reactopenLTerm_textopenLTerm_geomopenLTerm_stylelet(>>=)=Lwt.(>>=)moduleString_set=Set.Make(String)letversion="2.13.0"(* +-----------------------------------------------------------------+
| History |
+-----------------------------------------------------------------+ *)moduleDefault_paths=UTop_private.Default_pathslethistory=LTerm_history.create []lethistory_file_name =ref(Some(Default_paths.history_file_name))lethistory_file_max_size=refNonelethistory_file_max_entries =refNoneletstashable_session_history =UTop_history.create()(* +-----------------------------------------------------------------+
| Hooks |
+-----------------------------------------------------------------+ *)letnew_command_hooks=LTerm_dlist.create()letat_new_commandf=ignore(LTerm_dlist.add_lfnew_command_hooks)(* +-----------------------------------------------------------------+
| Config |
+-----------------------------------------------------------------+ *)typeui=UTop_private.ui=Console|Emacsletget_ui()=S.value UTop_private.uitypeprofile=Dark|Lightletprofile,set_profile =S.createDarkletset_profile p=set_profilepletsize=UTop_private.sizeletkey_sequence=UTop_private.key_sequenceletcount=UTop_private.countlettime=ref(Unix.time())let()=at_new_command (fun()->time:=Unix.time())letmake_variable?eqx=letsignal,set=S.create?eqxinletsetv=setvin(signal,(fun()->S.valuesignal),set)lethide_reserved,get_hide_reserved,set_hide_reserved=make_variabletrueletcreate_implicits,get_create_implicits,set_create_implicits=make_variablefalseletshow_box,get_show_box,set_show_box =make_variable trueletphrase_terminator,get_phrase_terminator,set_phrase_terminator =make_variable";;"letauto_run_lwt,get_auto_run_lwt,set_auto_run_lwt=make_variabletrueletauto_run_async,get_auto_run_async,set_auto_run_async=make_variabletruelettopfind_verbose,get_topfind_verbose,set_topfind_verbose=make_variablefalseletexternal_editor,get_external_editor,set_external_editor=make_variable(trySys.getenv"EDITOR"withNot_found ->"vi")(* Ugly hack until the action system of lambda-term is improved *)letend_and_accept_current_phrase:LTerm_read_line.action=Edit(Custom(fun()->assertfalse))letset_margin_functionf=UTop_private.set_margin_function f(* +-----------------------------------------------------------------+
| Keywords |
+-----------------------------------------------------------------+ *)letdefault_keywords=["and";"as";"assert";"begin";"class";"constraint";"do";"done";"downto";"else";"end";"exception";"external";"for";"fun";"function";"functor";"if";"in";"include";"inherit";"initializer";"lazy";"let";"match";"method";"module";"mutable";"new";"object";"of";"open";"private";"rec";"sig";"struct";"then";"to";"try";"type";"val";"virtual";"when";"while";"with";"try_lwt";"finally";"for_lwt";"lwt";]letkeywords=ref(String_set.of_listdefault_keywords)letadd_keywordkwd=keywords:=String_set.addkwd!keywords(* +-----------------------------------------------------------------+
| Span of Lines |
+-----------------------------------------------------------------+ *)typelines={start:int;stop:int;}(* +-----------------------------------------------------------------+
| Error reporting |
+-----------------------------------------------------------------+ *)letget_messagefuncx=letbuffer=Buffer.create1024inletpp=Format.formatter_of_bufferbufferinUTop_private.set_marginpp;funcppx;Format.pp_print_flushpp();Buffer.contentsbufferletget_ocaml_error_message exn=letbuffer=Buffer.create1024inletpp=Format.formatter_of_bufferbufferinUTop_private.set_marginpp;Errors.report_errorppexn;Format.pp_print_flush pp();letstr=Buffer.contentsbufferintryScanf.sscanfstr"Characters %d-%d:\n%[\000-\255]"(funstartstopmsg->((start,stop),msg,None))withScanf.Scan_failure(_)->tryScanf.sscanfstr"Line %d, characters %d-%d:\n%[\000-\255]"(funlinestartstopmsg->((start,stop),msg,Some{start=line;stop=line}))withScanf.Scan_failure(_)->tryScanf.sscanfstr"Lines %d-%d, characters %d-%d:\n%[\000-\255]"(funstart_linestop_linestartstopmsg->((start,stop),msg,Some{start=start_line;stop=stop_line}))withScanf.Scan_failure(_)->((0,0),str,None)letcollect_formattersbufppsf=(* First flush all formatters. *)List.iter(funpp->Format.pp_print_flushpp())pps;(* Saveall formatter functions. *)letsave=List.map(funpp->Format.pp_get_formatter_out_functionspp())ppsinletrestore()=List.iter2(funppout_functions ->Format.pp_print_flush pp();Format.pp_set_formatter_out_functions ppout_functions)ppssavein(* Outputfunctions. *)letout_functions=letppb=Format.formatter_of_bufferbufinFormat.pp_get_formatter_out_functionsppb()in(* Replace formatter functions. *)List.iter(funpp->UTop_private.set_marginpp;Format.pp_set_formatter_out_functionsppout_functions)pps;trylet x=f()inrestore();xwithexn->restore();raiseexnlet discard_formattersppsf=(* First flush all formatters. *)List.iter(funpp->Format.pp_print_flushpp())pps;(* Saveall formatter functions. *)letsave=List.map(funpp->Format.pp_get_formatter_out_functionspp())ppsinletrestore()=List.iter2(funppout_functions ->Format.pp_print_flush pp();Format.pp_set_formatter_out_functions ppout_functions)ppssavein(* Outputfunctions. *)letout_functions={Format.out_string =(fun___->());out_flush=ignore;out_newline=ignore;out_spaces=ignore;out_indent=ignore}in(* Replace formatter functions. *)List.iter(funpp->Format.pp_set_formatter_out_functionsppout_functions)pps;tryletx=f()inrestore();xwithexn->restore();raiseexn(* +-----------------------------------------------------------------+
| Parsing |
+-----------------------------------------------------------------+ *)typelocation=int*inttype'aresult=|Valueof'a|Erroroflocationlist*stringexception Need_moreletinput_name="//toplevel//"letlexbuf_of_stringeofstr=letpos=ref0inletlexbuf=Lexing.from_function(funbuflen->if!pos=String.lengthstrthenbegineof:=true;0endelsebeginletlen=minlen(String.lengthstr-!pos)inString.blitstr!posbuf0len;pos:=!pos +len;lenend)inLocation.initlexbufinput_name;lexbufletmklocloc=(loc.Location.loc_start.Lexing.pos_cnum,loc.Location.loc_end.Lexing.pos_cnum)letparse_defaultparsestreos_is_error=leteof=reffalseinletlexbuf=lexbuf_of_stringeofstrintry(* Try to parse the phrase. *)letphrase=parselexbufinValuephrasewith|_when!eof&¬eos_is_error->(* This is not an error, we just need more input. *)raiseNeed_more|End_of_file->(* If the string is empty, do not report an error. *)raiseNeed_more|Lexer.Error(error,loc)->(matchLocation.error_of_exn(Lexer.Error(error,loc))with|Some(`Okerror)->Error([mklocloc],get_messageLocation.print_reporterror)|_->raiseNeed_more)|Syntaxerr.Errorerror->beginmatcherrorwith|Syntaxerr.Unclosed(opening_loc,opening,closing_loc,closing)->Error([mklocopening_loc;mklocclosing_loc],Printf.sprintf"Syntax error: '%s' expected, the highlighted '%s' might be unmatched"closingopening)|Syntaxerr.Applicative_path loc->Error([mkloc loc],"Syntax error: applicative paths of the form F(X).t are not supported when the option -no-app-funct is set.")|Syntaxerr.Otherloc->Error([mkloc loc],"Syntax error")|Syntaxerr.Expecting(loc,nonterm)->Error([mklocloc],Printf.sprintf"Syntax error: %s expected."nonterm)|Syntaxerr.Variable_in_scope(loc,var)->Error([mkloc loc],Printf.sprintf"In this scoped type, variable '%s is reserved for the local type %s."varvar)|Syntaxerr.Not_expecting (loc,nonterm)->Error([mklocloc],Printf.sprintf"Syntax error: %s not expected"nonterm)|Syntaxerr.Ill_formed_ast(loc,s)->Error([mklocloc],Printf.sprintf"Error: broken invariant in parsetree: %s"s)|Syntaxerr.Invalid_package_type(loc,s)->Error([mklocloc],Printf.sprintf"Invalid package type: %s"s)#ifOCAML_VERSION>=(5,0,0)|Syntaxerr.Removed_string_setloc->Error([mklocloc],"Syntax error: strings are immutable, there is no assignment \
syntax for them.\n\
Hint: Mutable sequences of bytes are available in the Bytes module.\n\
Hint: Did you mean to use 'Bytes.set'?")#endifend|Syntaxerr.Escape_error|Parsing.Parse_error->Error([mkloc(Location.currlexbuf)],"Syntax error")|exn->Error([],"Unknown parsing error (please report it to the utop project): "^Printexc.to_stringexn)letparse_toplevel_phrase_default=parse_defaultParse.toplevel_phraseletparse_toplevel_phrase=refparse_toplevel_phrase_defaultletparse_use_file_default=parse_defaultParse.use_fileletparse_use_file =refparse_use_file_default(* +-----------------------------------------------------------------+
| Safety checking |
+-----------------------------------------------------------------+ *)letnull=Format.make_formatter(funstrofslen->())ignoreletreclast headtail =match tailwith|[]->head|head::tail->lastheadtailletwith_loclocstr={Location.txt=str;Location.loc=loc;}(* Check that the given phrase can be evaluated without typing/compile
errors. *)letcheck_phrasephrase=letopenParsetreeinmatchphrasewith|Ptop_dir_->None|Ptop_def[]->None|Ptop_def(item::items)->letloc={Location.loc_start=item.pstr_loc.Location.loc_start;Location.loc_end=(lastitemitems).pstr_loc.Location.loc_end;Location.loc_ghost=false;}in(* Backup. *)letsnap=Btype.snapshot()inletenv=!Toploop.toplevel_env in(* Construct "let _ () = let module _ = struct <items> end in ()" in order to test
the typing and compilation of [items] without evaluating them. *)letunit=let(%.)ab=Longident.Ldot(a,b)inwith_loc loc(Lident"Stdlib"%."Unit"%."()")inlettop_def=letopenAst_helperinwith_default_locloc(fun()->Str.eval(Exp.fun_NolabelNone(Pat.constructunitNone)(Exp.letmodule(with_loc loc(Some"_"))(Mod.structure(item::items))(Exp.constructunitNone))))inletcheck_phrase =Ptop_def[top_def]intrylet_=discard_formatters[Format.err_formatter](fun()->Env.reset_cache_toplevel ();Toploop.execute_phrasefalsenullcheck_phrase)in(* The phrase is safe. *)Toploop.toplevel_env:=env;Btype.backtracksnap;Nonewithexn->(* The phrase contains errors. *)letloc,msg,line=get_ocaml_error_messageexninToploop.toplevel_env:=env;Btype.backtracksnap;Some([loc],msg,[line])(* +-----------------------------------------------------------------+
| Prompt |
+-----------------------------------------------------------------+ *)letmake_promptuiprofilecountsizekey_sequence(recording,macro_count,macro_counter)=lettm=Unix.localtime!timeinletcolordarklight=matchprofilewith|Dark->dark|Light->lightinmatchuiwith|Emacs->[||]|Console->letbold=profile=Darkinlettxta=ifkey_sequence =[]theneval[B_boldbold;B_fg(colorlcyanblue);S"─( ";B_fg (colorlmagentamagenta);S(Printf.sprintf"%02d:%02d:%02d"tm.Unix.tm_hourtm.Unix.tm_mintm.Unix.tm_sec);E_fg;S" )─< ";B_fg(colorlyellowyellow);S(Printf.sprintf"command%d"count);E_fg;S" >─";]elseeval[B_boldbold;B_fg(colorlcyanblue);S"─( ";B_fg (colorlmagentamagenta);S(Printf.sprintf"%02d:%02d:%02d"tm.Unix.tm_hourtm.Unix.tm_mintm.Unix.tm_sec);E_fg;S" )─< ";B_fg(colorlyellowyellow);S(Printf.sprintf"command%d"count);E_fg;S" >─[ ";B_fg(colorlgreengreen);S(String.concat" "(List.mapLTerm_key.to_string_compactkey_sequence));E_fg;S" ]─";]inlettxtb=ifrecordingtheneval [B_bold bold;B_fg(colorlcyanblue);S"{ ";B_fg(colorlwhiteblack);S(Printf.sprintf"counter: %d"macro_counter);E_fg;S" }─[ ";B_fg(colorlwhiteblack);S(Printf.sprintf"macro: %d"macro_count);E_fg;S" ]─";]elseeval[B_boldbold;B_fg(colorlcyanblue);S"{ ";B_fg(colorlwhiteblack);S(Printf.sprintf"counter: %d"macro_counter);E_fg;S" }─";]inletsecond_line=eval[S"\n";B_boldbold;B_fg(rgb0xe30xaa0x73);S"utop";B_fg(colorlgreengreen);S" # ";]inArray.append(ifArray.lengthtxta+Array.lengthtxtb>size.colsthenArray.sub(Array.appendtxtatxtb)0size.colselseArray.concat[txta;Array.make(size.cols-Array.lengthtxta-Array.lengthtxtb)(Zed_char.of_utf8"\u{2500}",{nonewithforeground=Some(colorlcyanblue);bold=Somebold});txtb;])second_lineletdefault_prompt=S.l6make_promptUTop_private.uiprofilecountsizekey_sequence(S.l3(funxyz->(x,y,z))(Zed_macro.recordingLTerm_read_line.macro)(Zed_macro.count LTerm_read_line.macro)(Zed_macro.counter LTerm_read_line.macro))letprompt=refdefault_promptletedit_mode=refLTerm_editor.Defaultletdefault_info={Toploop.section="UTop";doc="";(* TODO: have some kind of documentation *)}let()=Toploop.add_directive"utop_prompt_simple"(Toploop.Directive_none(fun()->prompt:=S.map(Printf.ksprintfLTerm_text.of_utf8"utop [%d]: ")count))default_info;Toploop.add_directive"utop_prompt_dummy"(Toploop.Directive_none(fun()->prompt:=S.const(LTerm_text.of_utf8"# ")))default_info;Toploop.add_directive "utop_prompt_fancy_light"(Toploop.Directive_none(fun()->set_profileLight;prompt:=default_prompt))default_info;Toploop.add_directive"utop_prompt_fancy_dark"(Toploop.Directive_none(fun()->set_profileDark;prompt:=default_prompt))default_info;Toploop.add_directive"edit_mode_default"(Toploop.Directive_none(fun()->edit_mode:=LTerm_editor.Default))default_info;Toploop.add_directive"edit_mode_vi"(Toploop.Directive_none(fun()->edit_mode:=LTerm_editor.Vi))default_info(* +-----------------------------------------------------------------+
| Help |
+-----------------------------------------------------------------+ *)moduleBindings=Zed_input.Make(LTerm_key)moduleKeys_map=Map.Make(struct typet=LTerm_key.tlistletcompare=compareend)letname_of_action action=ifaction ==end_and_accept_current_phrasethen"end-and-accept-current-phrase"elseLTerm_read_line.name_of_actionactionletdoc_of_actionaction=ifaction==end_and_accept_current_phrasethen"end the current phrase with the phrase terminator (;;) and evaluate it"elseLTerm_read_line.doc_of_actionactionlet()=Toploop.add_directive"utop_help"(Toploop.Directive_none(fun()->print_endline"If you can't see the prompt properly try: #utop_prompt_simple
utop defines the following directives:
#help : list all directives
#utop_bindings : list all the current key bindings
#utop_macro : display the currently recorded macro
#utop_stash : store all the valid commands from your current session in a file
#utop_save : store the current session with a simple prompt in a file
#topfind_log : display messages recorded from findlib since the beginning of the session
#topfind_verbose : enable/disable topfind verbosity
For a complete description of utop, look at the utop(1) manual page."))default_info;Toploop.add_directive"utop_bindings"(Toploop.Directive_none(fun()->letmake_lineskeysactionsacc=matchactionswith|[]->(String.concat" "(List.mapLTerm_key.to_string_compactkeys),"","does nothing")::acc|action::actions->letrecloopactionsacc=matchactions with|[]->acc|action::actions->loopactions(("",name_of_actionaction,doc_of_actionaction)::acc)inloopactions((String.concat" "(List.mapLTerm_key.to_string_compactkeys),name_of_actionaction,doc_of_actionaction)::acc)inletbindings=Bindings.fold(funkeyactionsmap->Keys_map.addkey(List.map(funaction->(LTerm_read_line.Editaction))actions)map)!LTerm_edit.bindingsKeys_map.emptyinletbindings =Bindings.foldKeys_map.add!LTerm_read_line.bindingsbindingsinlettable=List.rev (Keys_map.fold(funkeysactionacc->make_lines keysactionacc)bindings[])inletsize_key,size_name,size_doc=List.fold_left(fun(size_key,size_name,size_doc)(key,name,doc)->(max(String.lengthkey)size_key,max(String.length name)size_name,max(String.length doc)size_doc))(0,0,0)tableinletbuf=Buffer.create128inletformat_line(key,name,doc)=Buffer.clearbuf;Buffer.add_stringbufkey;whileBuffer.lengthbuf<size_keydoBuffer.add_charbuf' 'done;Buffer.add_string buf" : ";Buffer.add_stringbufname;whileBuffer.lengthbuf<size_key+size_name+3doBuffer.add_charbuf' 'done;Buffer.add_string buf" -> ";Buffer.add_stringbufdoc;Buffer.add_charbuf'\n';output_stringstdout(Buffer.contentsbuf)inList.iterformat_line table;flushstdout))default_info;Toploop.add_directive"utop_macro"(Toploop.Directive_none(fun()->letmacro=Zed_macro.contentsLTerm_read_line.macroinList.iter(funaction ->output_string stdout(name_of_actionaction);output_char stdout'\n')macro;flush stdout))default_infolet()=Toploop.add_directive"pwd"(Toploop.Directive_none(fun()->print_endline(Sys.getcwd())))default_infoletmake_stash_directiveentry_formatterfname=ifget_ui()=Emacs thenprint_endline "Stashing is currently not supported in Emacs"elseletentries=UTop_history.contentsstashable_session_historyin(* remove the stash directive from its output *)letentries=matchentrieswith[]->[]|_::e->einletentries =List.reventriesinPrintf.printf"Stashing %d entries in %s ... "(List.lengthentries)fname;tryletoc=open_outfnameintryList.iter(fun e->letline=entry_formattereinoutput_stringocline;output_charoc'\n')entries;close_outoc;Printf.printf"Done.\n";withexn->close_outoc;raiseexnwith exn->Printf.printf "Error with file %s: %s\n"fname@@Printexc.to_stringexnlet()=letfn =make_stash_directivebeginfunction|UTop_history.Inputi->i|Outputout|Errorout|Bad_inputout|Warningsout->Printf.sprintf"(* %s *)"outendinToploop.add_directive"utop_stash"(Toploop.Directive_stringfn)default_infolet()=letfn=make_stash_directivebeginfunction|UTop_history.Inputi|Bad_inputi->Printf.sprintf"# %s"i|Outputout|Errorout|Warningsout->outendinToploop.add_directive"utop_save"(Toploop.Directive_stringfn)default_info(* +-----------------------------------------------------------------+
| Findlib stuff |
+-----------------------------------------------------------------+ *)letprint_errormsg=Lazy.forceLTerm.stdout>>=funterm->LTerm.set_styleterm!UTop_private.error_style >>=fun()->Lwt_io.printmsg>>=fun()->LTerm.set_styletermLTerm_style.none>>=fun()->LTerm.flushtermlethandle_findlib_error =function|Failure msg->Lwt_main.run(print_errormsg)|Fl_package_base.No_such_package(pkg,reason)->Lwt_main.run(print_error(Printf.sprintf"No such package: %s%s\n"pkg(ifreason<>""then" - "^reasonelse"")))|Fl_package_base.Package_looppkg->Lwt_main.run(print_error(Printf.sprintf"Package requires itself: %s\n"pkg))|exn->raiseexnlettopfind_log,set_topfind_log=S.create ~eq:(fun__->false)[]let()=letreal_log =!Topfind.loginTopfind.log:=funstr->set_topfind_log (str::S.valuetopfind_log);ifS.valuetopfind_verbosethenreal_logstrlet()=Toploop.add_directive"topfind_log"(Toploop.Directive_none(fun()->List.iter(funstr->print_stringstr;print_char'\n')(S.valuetopfind_log);flushstdout))default_info;Toploop.add_directive"topfind_verbose"(Toploop.Directive_bool set_topfind_verbose)default_infoletsplit_wordsstr=letlen=String.lengthstrinletis_sep =function|' '|'\t'|'\r'|'\n'|','->true|_->falseinletrecskipacci=ifi=lenthenaccelseifis_sepstr.[i]thenskipacc(i+1)elseextractacci(i+1)andextractaccij=ifj=lenthen(String.substri(j-i))::accelseifis_sep str.[j]thenskip(String.substri(j-i)::acc)(j+1)elseextractacci(j+1)inList.rev(skip[]0)letrequirepackages=tryleteff_packages=Findlib.package_deep_ancestors!Topfind.predicatespackagesinTopfind.loadeff_packageswithexn->handle_findlib_errorexnlet()=Toploop.add_directive"require"(Toploop.Directive_string(funstr->require(split_wordsstr)))default_info(* +-----------------------------------------------------------------+
| Backports |
+-----------------------------------------------------------------+ *)letuse_outputcommand=letfn=Filename.temp_file"ocaml""_toploop.ml"inMisc.try_finally~always:(fun()->trySys.removefnwith Sys_error_->())(fun()->matchPrintf.ksprintfSys.command"%s > %s"command(Filename.quotefn)with|0->ignore (Toploop.use_fileFormat.std_formatterfn:bool)|n->Format.printf"Command exited with code %d.@."n)let()=letname="use_output"inifUTop_compat.toploop_get_directivename=NonethenToploop.add_directivename(Toploop.Directive_stringuse_output)default_info(* +-----------------------------------------------------------------+
| Initialization |
+-----------------------------------------------------------------+ *)let()=(* "utop" is an internal library so it is not passed as "-package"
to "ocamlfind ocamlmktop". *)Topfind.don't_load_deeply["utop"];Topfind.add_predicates["byte";"toploop"];(* Add findlib path so Topfind is available and it won't be
initialized twice if the user does [#use "topfind"]. *)Topdirs.dir_directory(Findlib.package_directory"findlib");(* Make UTop accessible. *)Topdirs.dir_directory(Findlib.package_directory"utop")(* +-----------------------------------------------------------------+
| Compiler-libs re-exports |
+-----------------------------------------------------------------+ *)letget_load_path()=Load_path.get_paths()letset_load_path=UTop_compat.set_load_pathmodulePrivate=structletfix_stringstr=letlen=String.lengthstriniflen=0thenstrelseletofs,_,_=Zed_utf8.next_errorstr0inifofs=lenthenstrelsebeginlet buf=Buffer.create(len+128)inifofs>0thenBuffer.add_substring bufstr0ofs;letrecloopofs=Zed_utf8.addbuf(Uchar.of_charstr.[ofs]);letofs1=ofs+1inifofs1<lenthenletofs2,_,_=Zed_utf8.next_errorstrofs1inifofs1<ofs2thenBuffer.add_substringbufstrofs1(ofs2-ofs1);ifofs2<len thenloopofs2elseBuffer.contentsbufelseBuffer.contents bufinloopofsendend