123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423openCommontypec_string=C_stringtypebyte_array=Byte_ArraymoduleLiteral=structtype_t=|Int:int->intt|String:string->byte_arrayt|Bool:bool->booltletpp:typea._->at->unit=letopenFormatinfunfmt->function|Inti->fprintffmt"@[(int@ %d)@]"i|Strings->fprintffmt"@[(string@ %S)@]"s|Boolb->fprintffmt"@[(bool@ %b)@]"bmoduleStr=structleteasy_to_escapes=String.for_alls~f:(function|'a'..'z'|'A'..'Z'|'0'..'9'|'-'|'_'|'*'|'&'|'^'|'='|'+'|'%'|'$'|'"'|'\''|'/'|'#'|'@'|'!'|' '|'~'|'`'|'\\'|'|'|'?'|'>'|'<'|'.'|','|':'|';'|'{'|'}'|'('|')'|'['|']'->true|other->false)letimpossible_to_escape_for_variable=String.exists~f:((=)'\x00')endendtyperaw_command_annotation=..typeraw_command_annotation+=Magic_unittypefd_redirection={take:intt;redirect_to:[`Pathofc_stringt|`Fdofintt(* | `Input_of of unit t *)]}and_t=|Exec:c_stringtlist->unitt|Raw_cmd:(raw_command_annotationoption*string)->'at|Bool_operator:boolt*[`And|`Or]*boolt->boolt|String_operator:byte_arrayt*[`Eq|`Neq]*byte_arrayt->boolt|Not:boolt->boolt|Returns:{expr:'at;value:int}->boolt|No_op:unitt|If:boolt*unitt*unitt->unitt|Seq:unittlist->unitt|Literal:'aLiteral.t->'at|Output_as_string:unitt->byte_arrayt|Redirect_output:unitt*fd_redirectionlist->unitt|Write_output:{expr:unitt;stdout:c_stringtoption;stderr:c_stringtoption;return_value:c_stringtoption}->unitt|Feed:byte_arrayt*unitt->unitt|Pipe:unittlist->unitt|While:{condition:boolt;body:unitt}->unitt|Fail:string->unitt|Int_to_string:intt->c_stringt|String_to_int:c_stringt->intt|Bool_to_string:boolt->c_stringt|String_to_bool:c_stringt->boolt|List_to_string:'alistt*('at->byte_arrayt)->byte_arrayt|String_to_list:byte_arrayt*(byte_arrayt->'at)->'alistt|List:'atlist->'alistt|C_string_concat:c_stringlistt->c_stringt|Byte_array_concat:byte_arraylistt->byte_arrayt|List_append:('alistt*'alistt)->'alistt|List_iter:'alistt*((unit->'at)->unitt)->unitt|Byte_array_to_c_string:byte_arrayt->c_stringt|C_string_to_byte_array:c_stringt->byte_arrayt|Int_bin_op:intt*[`Plus|`Minus|`Mult|`Div|`Mod]*intt->intt|Int_bin_comparison:intt*[`Eq|`Ne|`Gt|`Ge|`Lt|`Le]*intt->boolt|Getenv:c_stringt->c_stringt(* See [man execve]. *)|Setenv:c_stringt*c_stringt->unitt|Comment:string*'at->'atletpp_in_exprfmtpp=letopenFormatinpp_open_boxfmt2;fprintffmt"(%a)"pp();pp_close_boxfmt();()letpp_fun_callfmtnamepp_argargs=letopenFormatinpp_open_boxfmt2;fprintffmt"(%s@ %a)"name(pp_print_list~pp_sep:(funfmt()->pp_print_spacefmt())pp_arg)args;pp_close_boxfmt();()letrecpp:typea.Format.formatter->at->unit=letopenFormatinfunfmt->function|Execl->pp_fun_callfmt"exec"ppl|Raw_cmd(_,s)->pp_fun_callfmt"raw-command"(funfmt->fprintffmt"%S")[s]|Bool_operator(a,op,b)->pp_fun_callfmt(matchopwith`And->"and"|`Or->"or")pp[a;b]|String_operator(a,op,b)->pp_fun_callfmt(matchopwith`Eq->"string-eq"|`Neq->"string-neq")pp[a;b]|Int_bin_comparison(a,op,b)->letsop=matchopwith|`Eq->"int-eq"|`Ne->"int-neq"|`Gt->"gt"|`Ge->"ge"|`Lt->"lt"|`Le->"le"inpp_fun_callfmtsoppp[a;b]|Int_bin_op(a,op,b)->letsop=matchopwith|`Plus->"+"|`Minus->"-"|`Mult->"×"|`Div->"÷"|`Mod->"%"inpp_fun_callfmtsoppp[a;b]|Notb->pp_fun_callfmt"not"pp[b]|Returns{expr;value:int}->pp_fun_callfmt(sprintf"returns-{%d}"value)pp[expr]|No_op->fprintffmt"(noop)"|If(c,t,e)->pp_open_boxfmt1;fprintffmt"(if@ %a@ then: %a@ else: %a)"ppcpptppe;pp_close_boxfmt()|Seql->pp_fun_callfmt"seq"ppl|Literall->Literal.ppfmtl|Output_as_stringu->pp_fun_callfmt"as-string"pp[u]|Redirect_output(u,l)->letredirsfmt{take;redirect_to}=fprintffmt"@[(%a@ >@ %a)@]"pptake(funfmt->function`Fdf->fprintffmt"%a"ppf|`Pathf->fprintffmt"%a"ppf)redirect_toinpp_in_exprfmt(funfmt()->fprintffmt"redirect@ %a@ %a"ppu(pp_print_list~pp_sep:pp_print_spaceredirs)l)|Write_output{expr;stdout;stderr;return_value}->letonamefmtopt=matchoptwith|None->()|Somec->fprintffmt"@ @[<hov 2>(%s → %a)@]"nameppcinpp_in_exprfmt(funfmt()->fprintffmt"write-output@ %a%a%a%a"ppexpr(o"stdout")stdout(o"stderr")stderr(o"return-value")return_value)|Feed(s,u)->pp_in_exprfmt(funfmt()->fprintffmt"%a@ >>@ %a"ppsppu)|Pipel->pp_in_exprfmt(funfmt()->fprintffmt"pipe:@ %a"(pp_print_list~pp_sep:(funfmt()->fprintffmt"@ |@ ")pp)l)|While{condition;body}->pp_in_exprfmt(funfmt()->fprintffmt"while@ %a@ do:@ %a"ppconditionppbody)|Fails->pp_in_exprfmt(funfmt()->fprintffmt"FAIL@ %S"s)|Int_to_stringi->pp_fun_callfmt"int-to-string"pp[i]|String_to_inti->pp_fun_callfmt"string-to-int"pp[i]|Bool_to_stringb->pp_fun_callfmt"bool-to-string"pp[b]|String_to_boolb->pp_fun_callfmt"string-to-bool"pp[b]|List_to_string(l,f)->pp_fun_callfmt"list-to-string"pp[l](* : 'a list t * ('a t -> byte_array t) -> byte_array t *)|String_to_list(s,f)->pp_fun_callfmt"string-to-list"pp[s]|Listl->pp_fun_callfmt"list"ppl|C_string_concatt->pp_fun_callfmt"c-string-concat"pp[t]|Byte_array_concatt->pp_fun_callfmt"byte-array-concat"pp[t]|List_append(la,lb)->pp_fun_callfmt"list-append"pp[la;lb]|List_iter(l,f)->letbody=f(fun()->Raw_cmd(None,"VARIABLE"))inpp_open_boxfmt1;fprintffmt"(list-iter@ list: %a@ f: @[<hov 4>(fun VARIABLE ->@ %a)@])"pplppbody;pp_close_boxfmt()(* : 'a list t * ((unit -> 'a t) -> unit t) -> unit t *)|Byte_array_to_c_stringba->pp_fun_callfmt"byte-array-to-c-string"pp[ba]|C_string_to_byte_arrayc->pp_fun_callfmt"c-string-to-byte-array"pp[c]|Getenvs->pp_fun_callfmt"getenv"pp[s]|Setenv(s,v)->pp_fun_callfmt"setenv"pp[s;v]|Comment(cmt,expr)->fprintffmt"@[<hov 1>(comment@ %S@ %a)@]"cmtppexprmoduleConstruct=structletto_c_stringba=Byte_array_to_c_stringbaletto_byte_arrayc=C_string_to_byte_arraycmoduleC_string=structletequalsab=String_operator(to_byte_arraya,`Eq,to_byte_arrayb)let(=$=)ab=String_operator(to_byte_arraya,`Eq,to_byte_arrayb)let(<$>)ab=String_operator(to_byte_arraya,`Neq,to_byte_arrayb)letto_byte_arrayc=C_string_to_byte_arraycletto_bytesc=C_string_to_byte_arraycletconcat_elistl=C_string_concatlletconcat_listsl=concat_elist(Listsl)endmoduleByte_array=structlet(=$=)ab=String_operator(a,`Eq,b)let(<$>)ab=String_operator(a,`Neq,b)letto_c_stringba=Byte_array_to_c_stringbaletto_cba=Byte_array_to_c_stringbaendmoduleBase=structletliterall=Literallletbyte_arrays=Literal.Strings|>literalletints=Literal.Ints|>literalletboolt=Literal.Boolt|>literalletc_strings=byte_arrays|>to_c_stringletstring=c_stringletexecl=Exec(List.mapl~f:(funs->strings))letcalll=Execllet(&&&)ab=Bool_operator(a,`And,b)let(|||)ab=Bool_operator(a,`Or,b)letreturnsexpr~value=Returns{expr;value}letsucceedsexpr=returnsexpr~value:0letnop=No_opletif_then_elseabc=If(a,b,c)letif_thenab=if_then_elseabnopletseql=Seqlletnott=Nottletfails=Failsletcommentsu=Comment(s,u)let(%%%)su=commentsuletmake_switch:typea.(boolt*unitt)list->default:unitt->unitt=funconds~default->List.fold_rightconds~init:default~f:(fun(x,body)prev->if_then_elsexbodyprev)letwrite_output?stdout?stderr?return_valueexpr=Write_output{expr;stdout;stderr;return_value}letwrite_stdout~pathexpr=write_outputexpr~stdout:pathletto_fdtakefd={take;redirect_to=`Fdfd}letto_filetakefile={take;redirect_to=`Pathfile}letwith_redirectionscmdl=Redirect_output(cmd,l)letfile_existsp=call[c_string"test";c_string"-f";p]|>succeedsletgetenvv=Getenvvletsetenv~varv=Setenv(var,v)letget_stdoute=Output_as_stringeletfeed~stringe=Feed(string,e)let(>>)stringe=feed~stringeletpipel=Pipellet(||>)ab=Pipe[a;b]letloop_whilecondition~body=While{condition;body}letloop_seq_whileconditionbody=While{condition;body=Seqbody}letbyte_array_concat_listl=Byte_array_concatlendincludeBasemoduleBool=structletof_strings=String_to_boolsletto_stringb=Bool_to_stringbendmoduleInteger=structletto_stringi=Int_to_stringiletto_byte_arrayi=C_string_to_byte_array(Int_to_stringi)letof_strings=String_to_intsletof_byte_arrays=String_to_int(Byte_array_to_c_strings)letbin_opaob=Int_bin_op(a,o,b)letaddab=bin_opa`Plusblet(+)=addletsubab=bin_opa`Minusblet(-)=subletmulab=bin_opa`Multblet(*)=mulletdivab=bin_opa`Divblet(/)=divletmoduloab=bin_opa`Modblet(mod)=moduloletcmpopab=Int_bin_comparison(a,op,b)leteq=cmp`Eqletne=cmp`Neletlt=cmp`Ltletle=cmp`Leletge=cmp`Geletgt=cmp`Gtlet(=)=eqlet(<>)=nelet(<)=ltlet(<=)=lelet(>=)=gelet(>)=gtendmoduleMagic=structletunits:unitt=Raw_cmd(SomeMagic_unit,s)endmoduleElist=structletmakel=Listlletappendlalb=List_append(la,lb)letiterl~f=List_iter(l,f)letto_stringfl=List_to_string(l,f)letof_stringfl=String_to_list(l,f)letserialize_byte_array_list:byte_arraylistt->byte_arrayt=to_string(fune->e)letdeserialize_to_byte_array_list:byte_arrayt->byte_arraylistt=of_string(fune->e)letserialize_c_string_list:c_stringlistt->byte_arrayt=to_string(fune->to_byte_arraye)letdeserialize_to_c_string_list:byte_arrayt->c_stringlistt=of_string(fune->to_c_stringe)letserialize_int_list:intlistt->byte_arrayt=to_stringInteger.to_byte_arrayletdeserialize_to_int_list:byte_arrayt->intlistt=of_stringInteger.of_byte_arrayletto_string_=`Do_not_useletof_string_=`Do_not_useendend