123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857(* Sexp: Module for handling S-expressions (I/O, etc.) *)openFormatopenBigarraymoduleSexplib=Sexplib0moduleConv=Sexplib.Sexp_conv(* conv.ml depends on us so we can only use this module *)includeTypetypebigstring=(char,int8_unsigned_elt,c_layout)Array1.tinclude(Sexplib.Sexp:moduletypeofstructincludeSexplib.Sexpendwithtypet:=t)includePrivate(* Output of S-expressions to I/O-channels *)letwith_new_bufferocf=letbuf=buffer()infbuf;Buffer.output_bufferocbufletoutput_humocsexp=with_new_bufferoc(funbuf->to_buffer_humsexp~buf)letoutput_hum_indentindentocsexp=with_new_bufferoc(funbuf->to_buffer_hum~indentsexp~buf)letoutput_machocsexp=with_new_bufferoc(funbuf->to_buffer_machsexp~buf)letoutput=output_mach(* Output of S-expressions to file *)(* The temp file functions in the OCaml Filename module do not support
permissions. But opening a file with given permissions is different
from opening it and chmoding it to these permissions, because the umask
is taken in account. Under Unix there's no easy way to get the umask in
a thread-safe way. *)moduleTmp_file=structletprng=refNonelettemp_file_nameprefixsuffix=letrand_state=match!prngwith|Somev->v|None->letret=Random.State.make_self_init()inprng:=Someret;retinletrnd=(Random.State.bitsrand_state)land0xFFFFFFinPrintf.sprintf"%s%06x%s"prefixrndsuffix(* Keep the permissions loose. Sexps are usually shared and rarely private*)letopen_temp_file?(perm=0o666)prefixsuffix=letrectry_namecounter=letname=temp_file_nameprefixsuffixintryletoc=open_out_gen[Open_wronly;Open_creat;Open_excl;Open_text]permnameinname,ocwithSys_error_ase->ifcounter>=1000thenraiseeelsetry_name(counter+1)intry_name0endletsave_of_output?permoutput_functionfilesexp=lettmp_name,oc=Tmp_file.open_temp_file?permfile"tmp"inbegintryoutput_functionocsexp;close_outoc;withe->close_out_noerroc;begintrySys.removetmp_namewith_->()end;raiseeend;Sys.renametmp_namefileletoutput_sexp_nldo_outputocsexp=do_outputocsexp;output_stringoc"\n"letsave_hum?permfilesexp=save_of_output?perm(output_sexp_nloutput_hum)filesexpletsave_mach?permfilesexp=save_of_output?permoutput_machfilesexpletsave=save_machletoutput_sexps_nldo_outputocsexps=List.iter(output_sexp_nldo_outputoc)sexpsletsave_sexps_hum?permfilesexps=save_of_output?perm(output_sexps_nloutput_hum)filesexpsletsave_sexps_mach?permfilesexps=save_of_output?perm(output_sexps_nloutput_mach)filesexpsletsave_sexps=save_sexps_mach(* Scan functions *)letscan_sexp?buflexbuf=Parser.sexp(Lexer.main?buf)lexbufletscan_sexp_opt?buflexbuf=Parser.sexp_opt(Lexer.main?buf)lexbufletscan_sexps?buflexbuf=Parser.sexps(Lexer.main?buf)lexbufletscan_rev_sexps?buflexbuf=Parser.rev_sexps(Lexer.main?buf)lexbufletget_main_bufbuf=letbuf=matchbufwith|None->Buffer.create128|Somebuf->bufinLexer.main~bufletscan_fold_sexps?buf~f~initlexbuf=letmain=get_main_bufbufinletrecloopacc=matchParser.sexp_optmainlexbufwith|None->acc|Somesexp->loop(faccsexp)inloopinitletscan_iter_sexps?buf~flexbuf=scan_fold_sexps?buflexbuf~init:()~f:(fun()sexp->fsexp)letscan_sexps_conv?buf~flexbuf=letcollaccsexp=fsexp::accinList.rev(scan_fold_sexps?buf~f:coll~init:[]lexbuf)letsexp_conversion_error_message?containing_sexp?location?invalid_sexp()~exn:t=List(List.concat[[Atom"Of_sexp_error"];(matchlocationwithNone->[]|Somex->[Atomx]);[matchexnwith|Failurex->Atomx|_->Conv.sexp_of_exnexn];(matchinvalid_sexpwith|None->[]|Somex->[List[Atom"invalid_sexp";x]]);(matchcontaining_sexpwith|None->[]|Somex->[List[Atom"containing_sexp";x]])])(* Partial parsing *)moduleAnnot=structtypepos=Parsexp.Positions.pos={line:int;col:int;offset:int}typerange=Parsexp.Positions.range={start_pos:pos;end_pos:pos}typet=Atomofrange*Type.t|Listofrange*tlist*Type.ttype'aconv=[`Resultof'a|`Errorofexn*t]exceptionConv_exnofstring*exnlet()=Conv.Exn_converter.add~finalise:false[%extension_constructorConv_exn](function|Conv_exn(location,exn)->sexp_conversion_error_message()~location~exn|_->assertfalse)typestack={mutablepositions:poslist;mutablestack:tlistlist;}letget_sexp=functionAtom(_,sexp)|List(_,_,sexp)->sexpletget_range=functionAtom(range,_)|List(range,_,_)->rangeletsexp_of_convsexp_of_a=function|`Resulta->Type.List[Atom"Result";a|>sexp_of_a]|`Error(exn,t)->List[Atom"Error";List[exn|>Conv.sexp_of_exn;t|>get_sexp]]exceptionAnnot_sexpoftletfind_sexpannot_sexpsexp=letrecloopannot_sexp=matchannot_sexpwith|Atom(_,sub_sexp)|List(_,_,sub_sexp)whensexp==sub_sexp->raise(Annot_sexpannot_sexp)|List(_,annots,_)->List.iterloopannots|Atom_->()intryloopannot_sexp;NonewithAnnot_sexpres->Someresendlet()=Conv.Exn_converter.add~finalise:false[%extension_constructorOf_sexp_error](function|Of_sexp_error(Annot.Conv_exn(location,exn),invalid_sexp)->sexp_conversion_error_message()~location~invalid_sexp~exn|Of_sexp_error(exn,invalid_sexp)->sexp_conversion_error_message()~invalid_sexp~exn|_->(* Reaching this branch indicates a bug in sexplib. *)assertfalse)moduleParse_pos=structtypet={mutabletext_line:int;mutabletext_char:int;mutableglobal_offset:int;mutablebuf_pos:int;}letcreate?(text_line=1)?(text_char=0)?(buf_pos=0)?(global_offset=0)()=letfailmsg=failwith("Sexplib.Sexp.Parse_pos.create: "^msg)iniftext_line<1thenfail"text_line < 1"elseiftext_char<0thenfail"text_char < 0"elseifglobal_offset<0thenfail"global_offset < 0"elseifbuf_pos<0thenfail"buf_pos < 0"else{text_line;text_char;global_offset;buf_pos}letwith_buf_postbuf_pos={twithbuf_pos}endmoduleCont_state=structtypet=Parsexp.Private.Parser_automaton.Old_parser_cont_state.t=|Parsing_toplevel_whitespace|Parsing_nested_whitespace|Parsing_atom|Parsing_list|Parsing_sexp_comment|Parsing_block_commentletto_string=function|Parsing_toplevel_whitespace->"Parsing_toplevel_whitespace"|Parsing_nested_whitespace->"Parsing_nested_whitespace"|Parsing_atom->"Parsing_atom"|Parsing_list->"Parsing_list"|Parsing_sexp_comment->"Parsing_sexp_comment"|Parsing_block_comment->"Parsing_block_comment"endtype('a,'t)parse_result=|Doneof't*Parse_pos.t|ContofCont_state.t*('a,'t)parse_funand('a,'t)parse_fun=pos:int->len:int->'a->('a,'t)parse_resulttype'tparse_state={parse_pos:Parse_pos.t;}typeparse_error={err_msg:string;parse_state:[|`Sexpoftlistlistparse_state|`AnnotofAnnot.stackparse_state]}exceptionParse_errorofparse_errorlet()=Conv.Exn_converter.add~finalise:false[%extension_constructorParse_error](function|Parse_errorpe->letppos=matchpe.parse_statewith|`Sexp{parse_pos;}|`Annot{parse_pos;}->parse_posinList[Atom"Sexplib.Sexp.Parse_error";List[List[Atom"err_msg";Atompe.err_msg];List[Atom"text_line";Conv.sexp_of_intppos.Parse_pos.text_line];List[Atom"text_char";Conv.sexp_of_intppos.Parse_pos.text_char];List[Atom"global_offset";Conv.sexp_of_intppos.Parse_pos.global_offset];List[Atom"buf_pos";Conv.sexp_of_intppos.Parse_pos.buf_pos];]]|_->assertfalse)moduleParser_output:sigmoduletypeT=sigmoduleImpl:Parsexp.Eager_parsertypeoutputexceptionFoundofoutputvalraise_found:Impl.State.Read_only.t->Impl.parsed_value->unitendmoduleBare_sexp:Twithtypeoutput=Type.tmoduleAnnotated_sexp:Twithtypeoutput=Annot.tend=structmoduletypeT=sigmoduleImpl:Parsexp.Eager_parsertypeoutputexceptionFoundofoutputvalraise_found:Impl.State.Read_only.t->Impl.parsed_value->unitendmoduleI=Parsexp.Positions.Iteratorletrecannotate_sexpsexpiter=matchsexpwith|Type.Atom_->letstart_pos=I.advance_exniter~skip:0inletend_pos=I.advance_exniter~skip:0inAnnot.Atom({start_pos;end_pos},sexp)|Type.Listl->letstart_pos=I.advance_exniter~skip:0inletannot=annotate_sexp_listliterinletend_pos=I.advance_exniter~skip:0inAnnot.List({start_pos;end_pos},annot,sexp)andannotate_sexp_listsexpsiter=List.rev(List.rev_map(funsexp->annotate_sexpsexpiter)sexps)moduleBare_sexp=structmoduleImpl=Parsexp.Eagertypeoutput=Type.texceptionFoundofoutputletraise_found_statesexp=raise_notrace(Foundsexp)endmoduleAnnotated_sexp=structmoduleImpl=Parsexp.Eager_and_positionstypeoutput=Annot.texceptionFoundofoutputletraise_found_state(sexp,positions)=letannot=annotate_sexpsexp(I.createpositions)inraise_notrace(Foundannot)endendmoduleMake_parser(T:sigincludeParser_output.Ttypeinputvallength:input->intvalunsafe_feed_loop:Impl.State.t->Impl.Stack.t->input->max_pos:int->pos:int->Impl.Stack.tend):sigvalparse:?parse_pos:Parse_pos.t->?len:int->T.input->(T.input,T.output)parse_resultend=structletparse_pos_of_statestatebuf_pos={Parse_pos.text_line=T.Impl.State.linestate;Parse_pos.text_char=T.Impl.State.columnstate;Parse_pos.global_offset=T.Impl.State.offsetstate;Parse_pos.buf_pos=buf_pos;}letcheck_str_bounds~pos~lenstr=ifpos<0theninvalid_arg"parse: pos < 0";iflen<0theninvalid_arg"parse: len < 0";letstr_len=T.lengthstrinletpos_len=pos+leninifpos_len>str_lentheninvalid_arg"parse: pos + len > str_len";pos_len-1letraise_parse_errorstateposmsg=letparse_state={parse_pos=parse_pos_of_statestatepos}inletparse_error={err_msg=msg;parse_state=`Sexpparse_state}inraise(Parse_errorparse_error)lethandle_parsexp_errorstatepose=letopenParsexp.Private.Parser_automatoninletmsg=Error.messageeinmatchError.old_parser_exnewith|`Parse_error->raise_parse_errorstateposmsg|`Failure->failwithmsgletrecrun_feed_loopstatestack~pos~lenstr=letmax_pos=check_str_bounds~pos~lenstrinletprevious_offset=T.Impl.State.offsetstateinmatchT.unsafe_feed_loopstatestackstr~max_pos~poswith|stack->mk_cont_statestatestack|exceptionT.Foundresult->letoffset=T.Impl.State.offsetstateinletnext_pos=pos+(offset-previous_offset)inDone(result,parse_pos_of_statestatenext_pos)|exceptionParsexp.Private.Parser_automaton.Parse_errorerr->handle_parsexp_errorstate(pos+(T.Impl.State.offsetstate-previous_offset))errandmk_cont_statestatestack=letparse_fun=letused_ref=reffalseinfun~pos~lenstr->if!used_refthenfailwith"Sexplib.Sexp: parser continuation called twice"elsebeginused_ref:=true;run_feed_loopstatestack~pos~lenstrendinletcont_state=T.Impl.State.old_parser_cont_statestateinCont(cont_state,parse_fun)letparse?(parse_pos=Parse_pos.create())?lenstr=letpos,buf_pos=let{Parse_pos.text_line;text_char;global_offset;buf_pos;}=parse_posin{Parsexp.Positions.line=text_line;col=text_char;offset=global_offset},buf_posinletstate=T.Impl.State.create~pos~no_sexp_is_error:falseT.raise_foundinletstack=T.Impl.Stack.emptyinletlen=matchlenwith|Somex->x|None->T.lengthstr-buf_posinrun_feed_loopstatestackstr~pos:buf_pos~lenend[@@inlinealways]moduleString_single_sexp=Make_parser(structincludeParser_output.Bare_sexptypeinput=stringletlength=String.lengthletrecunsafe_feed_loopstatestackstr~max_pos~pos=ifpos<=max_posthenbeginletstack=Impl.feedstate(String.unsafe_getstrpos)stackinunsafe_feed_loopstatestackstr~max_pos~pos:(pos+1)endelsestackend)letparse_str=String_single_sexp.parseletparse=String_single_sexp.parsemoduleString_single_annot=Make_parser(structincludeParser_output.Annotated_sexptypeinput=stringletlength=String.lengthletrecunsafe_feed_loopstatestackstr~max_pos~pos=ifpos<=max_posthenbeginletstack=Impl.feedstate(String.unsafe_getstrpos)stackinunsafe_feed_loopstatestackstr~max_pos~pos:(pos+1)endelsestackend)letparse_str_annot=String_single_annot.parsemoduleBigstring_single_sexp=Make_parser(structincludeParser_output.Bare_sexptypeinput=bigstringletlength=Array1.dimletrecunsafe_feed_loopstatestack(str:input)~max_pos~pos=ifpos<=max_posthenbeginletstack=Impl.feedstate(Array1.unsafe_getstrpos)stackinunsafe_feed_loopstatestackstr~max_pos~pos:(pos+1)endelsestackend)letparse_bigstring=Bigstring_single_sexp.parsemoduleBigstring_single_annot=Make_parser(structincludeParser_output.Annotated_sexptypeinput=bigstringletlength=Array1.dimletrecunsafe_feed_loopstatestack(str:input)~max_pos~pos=ifpos<=max_posthenbeginletstack=Impl.feedstate(Array1.unsafe_getstrpos)stackinunsafe_feed_loopstatestackstr~max_pos~pos:(pos+1)endelsestackend)letparse_bigstring_annot=Bigstring_single_annot.parse(* Input functions *)letmk_this_parse?parse_posmy_parse=();fun~pos~lenstr->letparse_pos=matchparse_poswith|None->Parse_pos.create~buf_pos:pos()|Someparse_pos->parse_pos.Parse_pos.buf_pos<-pos;parse_posinmy_parse?parse_pos:(Someparse_pos)?len:(Somelen)str(* [ws_buf] must contain a single space character *)letfeed_end_of_input~this_parse~ws_buf=(* When parsing atoms, the incremental parser cannot tell whether
it is at the end until it hits whitespace. We therefore feed it
one space to determine whether it is finished. *)matchthis_parse~pos:0~len:1ws_bufwith|Done(sexp,_)->Oksexp|Cont(cont_state,_)->Errorcont_stateletgen_input_sexpmy_parse?parse_posic=letbuf=Bytes.create1inletrecloopthis_parse=matchinput_charicwith|exceptionEnd_of_file->(matchfeed_end_of_input~this_parse~ws_buf:" "with|Oksexp->sexp|Error_->raiseEnd_of_file)|c->Bytes.setbuf0c;matchthis_parse~pos:0~len:1(Bytes.unsafe_to_stringbuf)with|Done(sexp,_)->sexp|Cont(_,this_parse)->loopthis_parseinloop(mk_this_parse?parse_posmy_parse)letinput_sexp?parse_posic=gen_input_sexpparse?parse_posicletgen_input_rev_sexpsmy_parse~ws_buf?parse_pos?(buf=Bytes.create8192)ic=letrev_sexps_ref=ref[]inletbuf_len=Bytes.lengthbufinletrecloopthis_parse~pos~len=iflen>0thenmatchthis_parse~pos~len(Bytes.unsafe_to_stringbuf)with|Done(sexp,({Parse_pos.buf_pos;_}asparse_pos))->rev_sexps_ref:=sexp::!rev_sexps_ref;letn_parsed=buf_pos-posinletthis_parse=mk_this_parse~parse_posmy_parseinifn_parsed=lenthenletnew_len=inputicbuf0buf_leninloopthis_parse~pos:0~len:new_lenelseloopthis_parse~pos:buf_pos~len:(len-n_parsed)|Cont(_,this_parse)->loopthis_parse~pos:0~len:(inputicbuf0buf_len)elsematchfeed_end_of_input~this_parse~ws_bufwith|Oksexp->sexp::!rev_sexps_ref|ErrorParsing_toplevel_whitespace->!rev_sexps_ref|Errorcont_state->failwith("Sexplib.Sexp.input_rev_sexps: reached EOF while in state "^Cont_state.to_stringcont_state)inletlen=inputicbuf0buf_leninletthis_parse=mk_this_parse?parse_posmy_parseinloopthis_parse~pos:0~lenletinput_rev_sexps?parse_pos?bufic=gen_input_rev_sexpsparse~ws_buf:" "?parse_pos?buficletinput_sexps?parse_pos?bufic=List.rev(input_rev_sexps?parse_pos?bufic)(* of_string and of_bigstring *)letof_string_bigstringlocmy_parsews_bufget_lenget_substr=matchmy_parse?parse_pos:None?len:Nonestrwith|Done(sexp,parse_pos)->beginmatchmy_parse?parse_pos:(Someparse_pos)?len:Nonestrwith|Done(_sexp2,_)->failwith(sprintf("Sexplib.Sexp.%s: got multiple S-expressions where only one was expected.")loc)|Cont(Cont_state.Parsing_toplevel_whitespace,_)->sexp|Cont(_,_)->(* not using [feed_end_of_input] here means "a b" will end up here and not in
"multiple S-expressions" branch, but it doesn't matter that much *)failwith(sprintf("Sexplib.Sexp.%s: S-expression followed by data at position %d...")locparse_pos.buf_pos)end|Cont(_,this_parse)->matchfeed_end_of_input~this_parse~ws_bufwith|Oksexp->sexp|Errorcont_state->letcont_state_str=Cont_state.to_stringcont_stateinfailwith(sprintf"Sexplib.Sexp.%s: incomplete S-expression while in state %s: %s"loccont_state_str(get_substr0(get_lenstr)))letof_stringstr=of_string_bigstring"of_string"parse" "String.lengthString.substrletget_bstr_sub_strbstrposlen=letstr=Bytes.createleninfori=0tolen-1doBytes.setstri(bstr.{pos+i})done;Bytes.unsafe_to_stringstrletbstr_ws_buf=Array1.createcharc_layout1let()=bstr_ws_buf.{0}<-' 'letof_bigstringbstr=of_string_bigstring"of_bigstring"parse_bigstringbstr_ws_bufArray1.dimget_bstr_sub_strbstr(* Loading *)letgen_load_rev_sexpsinput_rev_sexps?buffile=letic=open_infileintryletsexps=input_rev_sexps?parse_pos:None?buficinclose_inic;sexpswithexc->close_in_noerric;raiseexcletload_rev_sexps?buffile=gen_load_rev_sexpsinput_rev_sexps?buffileletload_sexps?buffile=List.rev(load_rev_sexps?buffile)letgen_load_sexp_loc="Sexplib.Sexp.gen_load_sexp"letgen_load_sexpmy_parse?(strict=true)?(buf=Bytes.create8192)file=letbuf_len=Bytes.lengthbufinletic=open_infileinletrecloopthis_parse=letlen=inputicbuf0buf_leniniflen=0thenmatchfeed_end_of_input~this_parse~ws_buf:" "with|Oksexp->sexp|Errorcont_state->failwith(sprintf"%s: EOF in %s while in state %s"gen_load_sexp_locfile(Cont_state.to_stringcont_state))elsematchthis_parse~pos:0~len(Bytes.unsafe_to_stringbuf)with|Done(sexp,({Parse_pos.buf_pos;_}asparse_pos))whenstrict->letrecstrict_loopthis_parse~pos~len=matchthis_parse~pos~len(Bytes.unsafe_to_stringbuf)with|Done_->failwith(sprintf"%s: more than one S-expression in file %s"gen_load_sexp_locfile)|Cont(cont_state,this_parse)->letlen=inputicbuf0buf_leniniflen>0thenstrict_loopthis_parse~pos:0~lenelseifcont_state=Cont_state.Parsing_toplevel_whitespacethensexpelsefailwith(sprintf"%s: %s in state %s loading file %s"gen_load_sexp_loc"additional incomplete data"(Cont_state.to_stringcont_state)file)inletthis_parse=mk_this_parse~parse_posmy_parseinstrict_loopthis_parse~pos:buf_pos~len:(len-buf_pos)|Done(sexp,_)->sexp|Cont(_,this_parse)->loopthis_parseintryletsexp=loop(mk_this_parsemy_parse)inclose_inic;sexpwithexc->close_in_noerric;raiseexcletload_sexp?strict?buffile=gen_load_sexpparse?strict?buffilemoduleAnnotated=structincludeAnnotletparse=parse_str_annotletparse_bigstring=parse_bigstring_annotletinput_rev_sexps?parse_pos?bufic=gen_input_rev_sexpsparse~ws_buf:" "?parse_pos?buficletinput_sexp?parse_posic=gen_input_sexpparse?parse_posicletinput_sexps?parse_pos?bufic=List.rev(input_rev_sexps?parse_pos?bufic)letof_stringstr=of_string_bigstring"Annotated.of_string"parse" "String.lengthString.substrletof_bigstringbstr=of_string_bigstring"Annotated.of_bigstring"parse_bigstringbstr_ws_bufArray1.dimget_bstr_sub_strbstrletload_rev_sexps?buffile=gen_load_rev_sexpsinput_rev_sexps?buffileletload_sexps?buffile=List.rev(load_rev_sexps?buffile)letload_sexp?strict?buffile=gen_load_sexpparse?strict?buffileletconvfannot_sexp=letsexp=get_sexpannot_sexpintry`Result(fsexp)withOf_sexp_error(exc,bad_sexp)ase->matchfind_sexpannot_sexpbad_sexpwith|None->raisee|Somebad_annot_sexp->`Error(exc,bad_annot_sexp)letget_conv_exn~file~excannot_sexp=letrange=get_rangeannot_sexpinlet{start_pos={line;col;offset=_};end_pos=_}=rangeinletloc=sprintf"%s:%d:%d"filelinecolinOf_sexp_error(Annot.Conv_exn(loc,exc),get_sexpannot_sexp)endletload_sexp_conv?(strict=true)?(buf=Bytes.create8192)filef=letsexp=load_sexp~strict~buffileintry`Result(fsexp)withOf_sexp_error_->Annotated.convf(Annotated.load_sexp~strict~buffile)letraise_conv_exn~file=function|`Resultres->res|`Error(exc,annot_sexp)->raise(Annotated.get_conv_exn~file~excannot_sexp)letload_sexp_conv_exn?strict?buffilef=raise_conv_exn~file(load_sexp_conv?strict?buffilef)letload_sexps_conv?(buf=Bytes.create8192)filef=letrev_sexps=load_rev_sexps~buffileintryList.rev_map(funsexp->`Result(fsexp))rev_sexpswithOf_sexp_error_ase->(matchAnnotated.load_rev_sexps~buffilewith|[]->(* File is now empty - perhaps it was a temporary file handle? *)raisee|rev_annot_sexps->List.rev_map(funannot_sexp->Annotated.convfannot_sexp)rev_annot_sexps)letload_sexps_conv_exn?(buf=Bytes.create8192)filef=letrev_sexps=load_rev_sexps~buffileintryList.rev_mapfrev_sexpswithOf_sexp_error_ase->(matchAnnotated.load_rev_sexps~buffilewith|[]->(* File is now empty - perhaps it was a temporary file handle? *)raisee|rev_annot_sexps->List.rev_map(funannot_sexp->raise_conv_exn~file(Annotated.convfannot_sexp))rev_annot_sexps)letgen_of_string_convof_stringannot_of_stringstrf=letsexp=of_stringstrintry`Result(fsexp)withOf_sexp_error_->Annotated.convf(annot_of_stringstr)letof_string_convstrf=gen_of_string_convof_stringAnnotated.of_stringstrfletof_bigstring_convbstrf=gen_of_string_convof_bigstringAnnotated.of_bigstringbstrfmoduleOf_string_conv_exn=structtypet={exc:exn;sexp:Type.t;sub_sexp:Type.t}exceptionEoftlet()=Conv.Exn_converter.add~finalise:false[%extension_constructorE](function|Eosce->sexp_conversion_error_message()~invalid_sexp:osce.sub_sexp~exn:osce.exc~containing_sexp:osce.sexp|_->assertfalse)endletgen_of_string_conv_exnof_stringstrf=letsexp=of_stringstrintryfsexpwithOf_sexp_error(exc,sub_sexp)->raise(Of_string_conv_exn.E{Of_string_conv_exn.exc;sexp;sub_sexp})letof_string_conv_exnstrf=gen_of_string_conv_exnof_stringstrfletof_bigstring_conv_exnbstrf=gen_of_string_conv_exnof_bigstringbstrf(* Utilities for automated type conversions *)letunit=List[]letis_unit=function|List[]->true|_->falseexternalsexp_of_t:t->t="%identity"externalt_of_sexp:t->t="%identity"(* Utilities for conversion error handling *)typefound=[`Found|`Posofint*found]typesearch_result=[`Not_found|found]letrecsearch_physicalsexp~contained=ifsexp==containedthen`Foundelsematchsexpwith|Atom_->`Not_found|Listlst->letrecloopi=function|[]->`Not_found|h::t->letres=search_physicalh~containedinmatchreswith|`Not_found->loop(i+1)t|#foundasfound->`Pos(i,found)inloop0lstletrecsubst_foundsexp~subst=function|`Found->subst|`Pos(pos,found)->matchsexpwith|Atom_->failwith"Sexplib.Sexp.subst_found: atom when position requested"|Listlst->letrecloopaccpos=function|[]->failwith"Sexplib.Sexp.subst_found: short list when position requested"|h::twhenpos<>0->loop(h::acc)(pos-1)t|h::t->List(List.rev_appendacc(subst_foundh~substfound::t))inloop[]poslst