123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632(*
* Copyright (c) 2014 Jeremy Yallop.
*
* This file is distributed under the terms of the MIT License.
* See the file LICENSE for details.
*)(* ML stub generation *)[@@@warning"-9-27"]openCtypes_staticopenCtypes_pathopenCstubs_errorstypenon_lwt=[`Sequential|`Unlocked]typelwt=[`Lwt_jobs|`Lwt_preemptive]typeconcurrency_policy=[non_lwt|lwt]typeerrno_policy=[`Ignore_errno|`Return_errno]typelident=stringtypeml_type=[`Identofpath|`Applofpath*ml_typelist|`Pairofml_type*ml_type|`Fnofml_type*ml_type]typeml_external_type=[`Primofml_typelist*ml_type]typeml_pat=[`Varofstring|`Recordof(path*ml_pat)list*[`Etc|`Complete]|`Asofml_pat*string|`Underscore|`Conofpath*ml_patlist]typeml_exp=[`Identofpath|`Projectofml_exp*path|`MakePtrofml_exp*ml_exp|`MakeFunPtrofml_exp*ml_exp|`MakeStructuredofml_exp*ml_exp|`Applofml_exp*ml_exp|`Tupleofml_explist|`Seqofml_exp*ml_exp|`Letofml_pat*ml_exp*ml_exp|`Unit|`Funoflidentlist*ml_exp]typeattributes={float:bool;noalloc:bool}typeextern={ident:string;typ:ml_external_type;primname:string;primname_byte:stringoption;attributes:attributes;}moduleEmit_ML:sigtypeappl_parens=ApplParens|NoApplParensvalml_exp:appl_parens->Format.formatter->ml_exp->unitvalml_pat:appl_parens->Format.formatter->ml_pat->unitvalml_external_type:Format.formatter->ml_external_type->unitvalextern:Format.formatter->extern->unitend=structletfprintf=Format.fprintf(* We (only) need to parenthesize function types in certain contexts
* on the lhs of a function type: - -> t
* as the argument to a single-argument type constructor: - t
*)typearrow_parens=ArrowParens|NoArrowParens(* We (only) need to parenthesize application expressions in certain contexts
* in a projection expression: -.l
* in a dereference expression: !@ -
* as an argument in an application: e -
*)typeappl_parens=ApplParens|NoApplParensletident=format_pathletrecml_typearrow_parensfmtt=matcharrow_parens,twith|_,`Identi->identfmti|_,`Appl(t,[])->identfmtt|_,`Appl(t,[t'])->fprintffmt"@[%a@ %a@]"(ml_typeArrowParens)t'identt|_,`Appl(t,ts)->letnargs=List.lengthtsinfprintffmt"(";List.iteri(funiarg->ifi=nargs-1then(ml_typeNoArrowParens)fmtargelsefprintffmt"%a,@ "(ml_typeNoArrowParens)arg)ts;fprintffmt")@ %a"identt;|ArrowParens,`Fn(t,t')->fprintffmt"@[(%a@ ->@ %a)@]"(ml_typeArrowParens)t(ml_typeNoArrowParens)t'|NoArrowParens,`Fn(t,t')->fprintffmt"@[%a@ ->@]@ %a"(ml_typeArrowParens)t(ml_typeNoArrowParens)t'|_,`Pair(t,t')->fprintffmt"@[(%a@ *@ %a)@]"(ml_typeNoArrowParens)t(ml_typeNoArrowParens)t'letml_external_typefmt(`Prim(args,ret):ml_external_type)=List.iter(fprintffmt"@[%a@ ->@]@ "(ml_typeArrowParens))args;ml_typeArrowParensfmtretletprimname_optfmt=function|None->()|Someprimname->fprintffmt"%S@ "primnameletattrsfmt{float;noalloc}=begin(* TODO: float support not yet implemented *)(* if float then pp_print_string fmt "\"float\""; *)(* TODO: fix this. The may_allocate function determines whether any of
the functions in the generated C cause OCaml heap allocations.
However, it doesn't currently account for callbacks: if we pass a
handle to an OCaml function into C, calling the function can trigger an
allocation. We need some way in the interface of the library for the
client to indicate whether it is safe to assume that a C function
cannot call back into OCaml. *)(* if noalloc then pp_print_string fmt "\"noalloc\"" *)endletargsfmtxs=List.iter(fprintffmt"%s@ ")xsletrecml_expappl_parensfmt(e:ml_exp)=matchappl_parens,ewith|_,`Unit->fprintffmt"()"|_,`Identx->identfmtx|_,`Project(e,l)->fprintffmt"%a.%a"(ml_expApplParens)eidentl|ApplParens,`Appl(f,p)->fprintffmt"@[(%a@;<1 2>%a)@]"(ml_expNoApplParens)f(ml_expApplParens)p|NoApplParens,`Appl(f,p)->fprintffmt"@[%a@ %a@]"(ml_expNoApplParens)f(ml_expApplParens)p|ApplParens,`MakePtr(t,e)->fprintffmt"(@[<hov 2>CI.make_ptr@ %a@ %a)@]"(ml_expApplParens)t(ml_expApplParens)e|NoApplParens,`MakePtr(t,e)->fprintffmt"@[<hov 2>CI.make_ptr@ %a@ %a@]"(ml_expApplParens)t(ml_expApplParens)e|ApplParens,`MakeFunPtr(t,e)->fprintffmt"(@[<hov 2>CI.make_fun_ptr@ %a@ %a)@]"(ml_expApplParens)t(ml_expApplParens)e|NoApplParens,`MakeFunPtr(t,e)->fprintffmt"@[<hov 2>CI.make_fun_ptr@ %a@ %a@]"(ml_expApplParens)t(ml_expApplParens)e|ApplParens,`MakeStructured(t,e)->fprintffmt"(@[<hov 2>CI.make_structured@ %a@ %a)@]"(ml_expApplParens)t(ml_expApplParens)e|NoApplParens,`MakeStructured(t,e)->fprintffmt"@[<hov 2>CI.make_structured@ %a@ %a@]"(ml_expApplParens)t(ml_expApplParens)e|_,`Fun(xs,e)->fprintffmt"(@[<1>fun@ %a->@ %a)@]"argsxs(ml_expNoApplParens)e|_,`Tuplees->fprintffmt"(@[%a)@]"tuple_elementses|_,`Seq(e1,e2)->fprintffmt"(@[%a;@ %a)@]"(ml_expNoApplParens)e1(ml_expNoApplParens)e2|ApplParens,`Let(p,e1,e2)->fprintffmt"(@[let@ %a@ = %a@ in@ %a)@]"(ml_patNoApplParens)p(ml_expNoApplParens)e1(ml_expNoApplParens)e2|NoApplParens,`Let(p,e1,e2)->fprintffmt"@[let@ %a@ = %a@ in@ %a@]"(ml_patNoApplParens)p(ml_expNoApplParens)e1(ml_expNoApplParens)e2andtuple_elementsfmt:ml_explist->unit=funxs->letlast=List.lengthxs-1inList.iteri(funi->ifi<>lastthenfprintffmt"%a,@ "(ml_expNoApplParens)elsefprintffmt"%a"(ml_expNoApplParens))xsandml_patappl_parensfmtpat=matchappl_parens,patwith|_,`Varx->fprintffmt"%s"x|_,`Record(fs,`Etc)->fprintffmt"{@[%a_}@]"pat_fieldsfs|_,`Record(fs,`Complete)->fprintffmt"{@[%a}@]"pat_fieldsfs|_,`As(p,x)->fprintffmt"@[(%a@ as@ %s)@]"(ml_patNoApplParens)px|_,`Underscore->fprintffmt"_"|_,`Con(c,[])->fprintffmt"%a"format_pathc|NoApplParens,`Con(c,[p])->fprintffmt"@[<2>%a@ @[%a@]@]"format_pathc(ml_patApplParens)p|ApplParens,`Con(c,[p])->fprintffmt"(@[<2>%a@ @[%a@])@]"format_pathc(ml_patApplParens)p|ApplParens,`Con(c,ps)->fprintffmt"(@[<2>%a@ (@[%a)@])@]"format_pathcpat_argsps|NoApplParens,`Con(c,ps)->fprintffmt"@[<2>%a@ (@[%a)@]@]"format_pathcpat_argspsandpat_fieldsfmt:(path*ml_pat)list->unit=List.iter(fun(l,p)->fprintffmt"@[%a@ =@ %a;@]@ "format_pathl(ml_patNoApplParens)p)andpat_argsfmt:ml_patlist->unit=funxs->letlast=List.lengthxs-1inList.iteri(funi->ifi<>lastthenfprintffmt"%a,@ "(ml_patNoApplParens)elsefprintffmt"%a"(ml_patNoApplParens))xsletexternfmt{ident;typ;primname;primname_byte;attributes}=fprintffmt"@[<hov 2>@[external@ %s@]@ @[<h 1>:@ @[%a@]@]@ "identml_external_typetyp;fprintffmt"@[=@ @[@[%a@]@[%S@]@ %a@]@]@]@."primname_optprimname_byteprimnameattrsattributesendletarity:ml_external_type->int=fun(`Prim(args,_))->List.lengthargsletmax_byte_args=5letbyte_stub_name:string->ml_external_type->stringoption=funnamet->letarity=aritytinifarity>max_byte_argsthenSome(Printf.sprintf"%s_byte%d"namearity)elseNoneletattributes:typea.afn->attributes=letopenCstubs_analysisinfunfn->{float=floatfn;noalloc=not(may_allocatefn)}letmanaged_buffer=`Ident(path_of_string"CI.managed_buffer")letvoidp=`Ident(path_of_string"CI.voidp")letfatptr=`Appl(path_of_string"CI.fatptr",[`Ident(path_of_string"_")])letfatfunptr=`Appl(path_of_string"CI.fatfunptr",[`Ident(path_of_string"_")])(* These functions determine the type that should appear in the extern
signature *)letrecml_typ_of_return_typ:typea.atyp->ml_type=function|Void->`Ident(path_of_string"unit")|Primitivep->`Ident(Cstubs_public_name.ident_of_ml_prim(Ctypes_primitive_types.ml_primp))|Struct_->managed_buffer|Union_->managed_buffer|Abstract_->managed_buffer|Pointer_->voidp|Funptr_->voidp|View{ty}->ml_typ_of_return_typty|Qualified(_,ty)->ml_typ_of_return_typty|Array_asa->internal_error"Unexpected array type in the return type: %s"(Ctypes.string_of_typa)|Bigarray_asa->internal_error"Unexpected bigarray type in the return type: %s"(Ctypes.string_of_typa)|OCamlString->Ctypes_static.unsupported"cstubs does not support OCaml strings as return values"|OCamlBytes->Ctypes_static.unsupported"cstubs does not support OCaml bytes values as return values"|OCamlFloatArray->Ctypes_static.unsupported"cstubs does not support OCaml float arrays as return values"letrecml_typ_of_arg_typ:typea.atyp->ml_type=function|Void->`Ident(path_of_string"unit")|Primitivep->`Ident(Cstubs_public_name.ident_of_ml_prim(Ctypes_primitive_types.ml_primp))|Pointer_->fatptr|Funptr_->fatfunptr|Struct_->fatptr|Union_->fatptr|Abstract_->fatptr|View{ty}->ml_typ_of_arg_typty|Qualified(_,ty)->ml_typ_of_arg_typty|Array_asa->internal_error"Unexpected array in an argument type: %s"(Ctypes.string_of_typa)|Bigarray_asa->internal_error"Unexpected bigarray in an argument type: %s"(Ctypes.string_of_typa)|OCamlString->`Appl(path_of_string"CI.ocaml",[`Ident(path_of_string"string")])|OCamlBytes->`Appl(path_of_string"CI.ocaml",[`Ident(path_of_string"bytes")])|OCamlFloatArray->`Appl(path_of_string"CI.ocaml",[`Appl(path_of_string"array",[`Ident(path_of_string"float")])])typepolarity=In|Outletflip=function|In->Out|Out->Inletml_typ_of_typ=functionIn->ml_typ_of_arg_typ|Out->ml_typ_of_return_typletlwt_job_type=Ctypes_path.path_of_string"Lwt_unix.job"letint_type=`Ident(Ctypes_path.path_of_string"Signed.sint")letrecml_external_type_of_fn:typea.concurrency:concurrency_policy->errno:errno_policy->afn->polarity->ml_external_type=fun~concurrency~errnofnpolarity->matchfn,concurrency,errnowith|Returnst,(#non_lwt|`Lwt_preemptive),`Ignore_errno->`Prim([],ml_typ_of_typpolarityt)|Returnst,(#non_lwt|`Lwt_preemptive),`Return_errno->`Prim([],`Pair(ml_typ_of_typpolarityt,int_type))|Returnst,`Lwt_jobs,`Ignore_errno->`Prim([],`Appl(lwt_job_type,[ml_typ_of_typpolarityt]))|Returnst,`Lwt_jobs,`Return_errno->`Prim([],`Appl(lwt_job_type,[`Pair(ml_typ_of_typpolarityt,int_type)]))|Function(f,t),_,_->let`Prim(l,t)=ml_external_type_of_fn~concurrency~errnotpolarityin`Prim(ml_typ_of_typ(flippolarity)f::l,t)letvar_counter=ref0letfresh_var()=incrvar_counter;Printf.sprintf"x%d"!var_counterletextern~concurrency~errno~stub_name~external_namefmtfn=letext=lettyp=ml_external_type_of_fn~concurrency~errnofnOutin({ident=external_name;typ=typ;primname=stub_name;primname_byte=byte_stub_namestub_nametyp;attributes=attributesfn;})inFormat.fprintffmt"%a@."Emit_ML.externextletstatic_concargs=`Con(Ctypes_path.path_of_string("CI."^c),args)letlocal_concargs=`Con(Ctypes_path.path_of_stringc,args)letmap_result_id=Ctypes_path.path_of_string"map_result"letmake_ptr=Ctypes_path.path_of_string"CI.make_ptr"letmake_fun_ptr=Ctypes_path.path_of_string"CI.make_fun_ptr"letmake_structured=Ctypes_path.path_of_string"CI.make_structured"letmap_result~concurrency~errnofe=letmap_resultfx=`Appl(`Appl(`Identmap_result_id,f),x)inmatchconcurrency,errno,fwith#non_lwt,`Ignore_errno,`MakePtrx->`MakePtr(`Ident(path_of_stringx),e)|#non_lwt,`Ignore_errno,`MakeFunPtrx->`MakeFunPtr(`Ident(path_of_stringx),e)|#non_lwt,`Ignore_errno,`MakeStructuredx->`MakeStructured(`Ident(path_of_stringx),e)|#non_lwt,`Ignore_errno,`Applx->`Appl(`Ident(path_of_stringx),e)|_,_,`MakePtrx->map_result(`Appl(`Identmake_ptr,`Ident(path_of_stringx)))e|_,_,`MakeFunPtrx->map_result(`Appl(`Identmake_fun_ptr,`Ident(path_of_stringx)))e|_,_,`MakeStructuredx->map_result(`Appl(`Identmake_structured,`Ident(path_of_stringx)))e|_,_,`Applx->map_result(`Ident(path_of_stringx))etypepattern_exp_return=ml_pat*ml_expoption*(ml_pat*ml_exp)listletrecpattern_and_exp_of_typ:typea.concurrency:concurrency_policy->errno:errno_policy->atyp->ml_exp->polarity->(ml_pat*ml_exp)list->pattern_exp_return=fun~concurrency~errnotypepolbinds->matchtypwith|Void->(static_con"Void"[],None,binds)|Primitivep->letid=Cstubs_public_name.constructor_cident_of_prim~module_name:"CI"pin(static_con"Primitive"[`Con(id,[])],None,binds)|Pointer_->beginmatchpolwith|In->letpat=static_con"Pointer"[`Underscore]inletx=fresh_var()in(pat,Some(`Ident(path_of_stringx)),binds@[static_con"CPointer"[`Varx],e])|Out->letx=fresh_var()inletpat=static_con"Pointer"[`Varx]in(pat,Some(map_result~concurrency~errno(`MakePtrx)e),binds)end|Funptr_->beginmatchpolwith|In->letpat=static_con"Funptr"[`Underscore]inletx=fresh_var()in(pat,Some(`Ident(path_of_stringx)),binds@[static_con"Static_funptr"[`Varx],e])|Out->letx=fresh_var()inletpat=static_con"Funptr"[`Varx]in(pat,Some(map_result~concurrency~errno(`MakeFunPtrx)e),binds)end|Struct_->beginmatchpolwith|In->letpat=static_con"Struct"[`Underscore]inletx=fresh_var()in(pat,Some(`Ident(path_of_stringx)),binds@[static_con"CPointer"[`Varx],`Appl(`Ident(path_of_string"Ctypes.addr"),e)])|Out->letx=fresh_var()inletpat=`As(static_con"Struct"[`Underscore],x)in(pat,Some(map_result~concurrency~errno(`MakeStructuredx)e),binds)end|Union_->beginmatchpolwith|In->letpat=static_con"Union"[`Underscore]inletx=fresh_var()in(pat,Some(`Ident(path_of_stringx)),binds@[static_con"CPointer"[`Varx],`Appl(`Ident(path_of_string"Ctypes.addr"),e)])|Out->letx=fresh_var()inletpat=`As(static_con"Union"[`Underscore],x)in(pat,Some(map_result~concurrency~errno(`MakeStructuredx)e),binds)end|View{ty}->beginmatchpolwith|In->letx=fresh_var()inlety=fresh_var()inlete=`Appl(`Ident(path_of_stringx),e)inlet(p,None,binds),e|(p,Somee,binds),_=pattern_and_exp_of_typ~concurrency~errnotyepolbinds,einletpat=static_con"View"[`Record([path_of_string"CI.ty",p;path_of_string"write",`Varx],`Etc)]in(pat,Some(`Ident(Ctypes_path.path_of_stringy)),(`Vary,e)::binds)|Out->let(p,None,binds),e|(p,Somee,binds),_=pattern_and_exp_of_typ~concurrency~errnotyepolbinds,einletx=fresh_var()inletpat=static_con"View"[`Record([path_of_string"CI.ty",p;path_of_string"read",`Varx],`Etc)]in(pat,Some(map_result~concurrency~errno(`Applx)e),binds)end|Qualified(_,ty)->pattern_and_exp_of_typ~concurrency~errnotyepolbinds|OCamlty->beginmatchpol,tywith|In,String->(static_con"OCaml"[static_con"String"[]],None,binds)|In,Bytes->(static_con"OCaml"[static_con"Bytes"[]],None,binds)|In,FloatArray->(static_con"OCaml"[static_con"FloatArray"[]],None,binds)|Out,String->Ctypes_static.unsupported"cstubs does not support OCaml strings as return values"|Out,Bytes->Ctypes_static.unsupported"cstubs does not support OCaml bytes values as return values"|Out,FloatArray->Ctypes_static.unsupported"cstubs does not support OCaml float arrays as return values"end|Abstract_asty->internal_error"Unexpected abstract type encountered during ML code generation: %s"(Ctypes.string_of_typty)|Array_asty->internal_error"Unexpected array type encountered during ML code generation: %s"(Ctypes.string_of_typty)|Bigarray_asty->internal_error"Unexpected bigarray type encountered during ML code generation: %s"(Ctypes.string_of_typty)(* Build a pattern (without variables) that matches the argument *)letrecpattern_of_typ:typea.atyp->ml_pat=functionVoid->static_con"Void"[]|Primitivep->letid=Cstubs_public_name.constructor_cident_of_prim~module_name:"CI"pinstatic_con"Primitive"[`Con(id,[])]|Pointer_->static_con"Pointer"[`Underscore]|Funptr_->static_con"Funptr"[`Underscore]|Struct_->static_con"Struct"[`Underscore]|Union_->static_con"Union"[`Underscore]|View{ty}->static_con"View"[`Record([path_of_string"CI.ty",pattern_of_typty],`Etc)]|Qualified(_,ty)->static_con"Qualified"[`Underscore;pattern_of_typty]|Array(_,_)->static_con"Array"[`Underscore;`Underscore]|Bigarray_->static_con"Bigarray"[`Underscore]|OCamlString->Ctypes_static.unsupported"cstubs does not support OCaml strings as global values"|OCamlBytes->Ctypes_static.unsupported"cstubs does not support OCaml bytes values as global values"|OCamlFloatArray->Ctypes_static.unsupported"cstubs does not support OCaml float arrays as global values"|Abstract_asty->internal_error"Unexpected abstract type encountered during ML code generation: %s"(Ctypes.string_of_typty)typewrapper_state={pat:ml_pat;exp:ml_exp;args:lidentlist;trivial:bool;binds:(ml_pat*ml_exp)list;}letlwt_unix_run_job=Ctypes_path.path_of_string"Lwt_unix.run_job"letlwt_preemptive_detach=Ctypes_path.path_of_string"Lwt_preemptive.detach"letrun_exp~concurrencyexp=matchconcurrencywith#non_lwt->exp|`Lwt_jobs->`Appl(`Identlwt_unix_run_job,exp)|`Lwt_preemptive->`Appl(`Appl(`Identlwt_preemptive_detach,`Fun(["_"],exp)),`Unit)letlet_bind:(ml_pat*ml_exp)list->ml_exp->ml_exp=funbindse->ListLabels.fold_left~init:ebinds~f:(fune'(x,e)->`Let(x,e,e'))letrecwrapper_body:typea.concurrency:concurrency_policy->errno:errno_policy->afn->ml_exp->polarity->(ml_pat*ml_exp)list->wrapper_state=fun~concurrency~errnofnexppolbinds->matchfnwith|Returnst->letexp=run_exp~concurrencyexpinbeginmatchpattern_and_exp_of_typ~concurrency~errnotexp(flippol)bindswithpat,None,binds->{exp;args=[];trivial=true;binds;pat=local_con"Returns"[pat]}|pat,Someexp,binds->{exp;args=[];trivial=false;binds;pat=local_con"Returns"[pat]}end|Function(f,t)->letx=fresh_var()inbeginmatchpattern_and_exp_of_typ~concurrency~errnof(`Ident(path_of_stringx))polbindswith|fpat,None,binds->let{exp;args;trivial;pat=tpat;binds}=wrapper_body~concurrency~errnot(`Appl(exp,`Ident(path_of_stringx)))polbindsin{exp;args=x::args;trivial;binds;pat=local_con"Function"[fpat;tpat]}|fpat,Someexp',binds->let{exp;args=xs;trivial;pat=tpat;binds}=wrapper_body~concurrency~errnot(`Appl(exp,exp'))polbindsin{exp;args=x::xs;trivial=false;binds;pat=local_con"Function"[fpat;tpat]}endletlwt_bind=Ctypes_path.path_of_string"Lwt.bind"letlwt_return=Ctypes_path.path_of_string"Lwt.return"letbox_lwt=Ctypes_path.path_of_string"box_lwt"letuse_value=Ctypes_path.path_of_string"CI.use_value"letreturn_result:args:lidentlist->ml_exp=fun~args->letx=fresh_var()in(* fun v -> CI.use_value (x1,x2,....xn); Lwt.return v *)`Fun([x],`Seq(`Appl(`Identuse_value,`Tuple(ListLabels.mapargs~f:(funx->`Ident(Ctypes_path.path_of_stringx)))),`Appl(`Identlwt_return,`Ident(Ctypes_path.path_of_stringx))))(** Returns the variables bound in a pattern, in no particular order *)letrecpat_bound_vars:ml_pat->lidentlist=function|`Varx->[x]|`Record(args,_)->pats_bound_vars(List.mapsndargs)|`As(p,x)->x::pat_bound_varsp|`Underscore->[]|`Con(_,ps)->pats_bound_varspsandpats_bound_vars:ml_patlist->lidentlist=funps->List.fold_left(funxsp->pat_bound_varsp@xs)[]psletwrapper:typea.concurrency:concurrency_policy->errno:errno_policy->path->afn->string->polarity->ml_pat*ml_exp=fun~concurrency~errnoidfnfpol->letp=wrapper_body~concurrency~errnofn(`Ident(path_of_stringf))pol[]inmatchp,concurrencywith{trivial=true;pat;binds},#non_lwt->(pat,let_bindbinds(run_exp~concurrency(`Identid)))|{exp;args;pat;binds},#non_lwt->(pat,`Fun(args,let_bindbindsexp))|{trivial=true;pat;args;binds},#lwt->letexp:ml_exp=List.fold_left(funfp->`Appl(f,`Ident(path_of_stringp)))(`Identid)argsin(pat,`Fun(args,let_bindbinds(`Appl(`Identbox_lwt,`Appl(`Appl(`Identlwt_bind,run_exp~concurrencyexp),return_result~args:(args@pats_bound_vars(List.mapfstbinds)))))))|{exp;args;pat;binds},#lwt->(pat,`Fun(args,let_bindbinds(`Appl(`Identbox_lwt,`Appl(`Appl(`Identlwt_bind,exp),return_result~args:(args@pats_bound_vars(List.mapfstbinds)))))))letcase~concurrency~errno~stub_name~external_namefmtfn=letp,e=wrapper~concurrency~errno(path_of_stringexternal_name)fnexternal_nameIninFormat.fprintffmt"@[<hov 2>@[<h 2>|@ @[@[%a@],@ %S@]@ ->@]@ "Emit_ML.(ml_patNoApplParens)pstub_name;Format.fprintffmt"@[<hov 2>@[%a@]@]@]@."Emit_ML.(ml_expApplParens)eletval_case~stub_name~external_namefmttyp=letx=fresh_var()inletp=`As(pattern_of_typtyp,x)inletapp=`Appl(`Ident(path_of_stringexternal_name),`Unit)inletrhs=`MakePtr(`Ident(path_of_stringx),app)inFormat.fprintffmt"@[<hov 2>@[<h 2>|@ @[@[%a@],@ %S@]@ ->@]@ "Emit_ML.(ml_patNoApplParens)pstub_name;Format.fprintffmt"@[<hov 2>@[%a@]@]@]@."Emit_ML.(ml_exp(ApplParens))rhsletconstructor_decl:typea.concurrency:concurrency_policy->errno:errno_policy->string->afn->Format.formatter->unit=fun~concurrency~errnonamefnfmt->Format.fprintffmt"@[|@ %s@ : (@[%a@])@ name@]@\n"nameEmit_ML.ml_external_type(ml_external_type_of_fn~concurrency~errnofnIn)letinverse_case~register_name~constructornamefmtfn:unit=letp,e=wrapper~concurrency:`Sequential~errno:`Ignore_errno(path_of_string"f")fn"f"OutinFormat.fprintffmt"|@[ @[%a, %S@] -> %s %s (%a)@]@\n"Emit_ML.(ml_patNoApplParens)pnameregister_nameconstructorEmit_ML.(ml_expApplParens)e