123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980openBaseopenPpxlibopenPpxlib.Ast_builder.Defaultletderiver="hardcaml"letraise_errorf=Location.raise_errorf(*
* Option parsing
*)typeoptions_t={rtlprefix:expressionoption;rtlsuffix:expressionoption;rtlmangle:expressionoption;ast:bool}letparse_rtlmangleexpr~loc=matchexprwith|[%exprtrue]->Some[%expr"_"]|[%exprfalse]->None|e->Somee;;(*
* Attribute definition and parsing
*)moduleAttribute:sigtypetvalfind:t->label_declaration->expressionoptionvalexists:tvalbits:tvallength:tvalrtlmangle:tvalrtlname:tvalrtlprefix:tvalrtlsuffix:tvaldoc:tend=structtypet=(label_declaration,expression)Attribute.tletfindtlabel_declaration=Attribute.gettlabel_declarationletcreatename=Attribute.declarenameLabel_declarationAst_pattern.(pstr(pstr_eval__nil^::nil))(funx->x);;letexists=create"exists"letbits=create"bits"letlength=create"length"letrtlmangle=create"rtlmangle"letrtlname=create"rtlname"letrtlprefix=create"rtlprefix"letrtlsuffix=create"rtlsuffix"(* This represents the [ocaml.doc] attribute, which maps to documentation comments. The
leading [hardcaml.] token is required to bypass some compiler (or ppx) related
checks. I mention it because it's an undocumented hack. *)letdoc=create"hardcaml.ocaml.doc"endletget_bits~loclabel_declaration=matchAttribute.(findbits)label_declarationwith|Someexpr->expr|None->pexp_constant~loc(Pconst_integer("1",None));;letget_length~loclabel_declaration=matchAttribute.(findlength)label_declarationwith|Someexpr->expr|None->raise_errorf~loc"[%s] length attribute must be set"deriver;;letfield_name~loctxt=pexp_constant~loc(Pconst_string(txt,loc,None))letget_rtlname~loctxtlabel_declaration=matchAttribute.(findrtlname)label_declarationwith|Someexpr->expr|None->field_name~loctxt;;letget_rtlprefix~loc:_optslabel_declaration=matchAttribute.(findrtlprefix)label_declarationwith|Someexpr->Someexpr|None->opts.rtlprefix;;letget_rtlsuffix~loc:_optslabel_declaration=matchAttribute.(findrtlsuffix)label_declarationwith|Someexpr->Someexpr|None->opts.rtlsuffix;;letget_rtlmangle~locoptslabel_declaration=matchAttribute.(findrtlmangle)label_declarationwith|Someexpr->parse_rtlmangleexpr~loc|None->opts.rtlmangle;;letget_doc~loclabel_declaration=matchAttribute.(finddoc)label_declarationwith|Someexpr->(matchexpr.pexp_descwith|Pexp_constant(Pconst_string(str,_,_))->Somestr|_->raise_errorf~loc"[%s] doc atttribute must be a string"deriver)|None->None;;(*
* Identifier manipulation
*)letmk_rtlident~locnameprefixsuffix=matchprefix,suffixwith|None,None->[%expr[%ename]]|Somepre,None->[%exprPpx_hardcaml_runtime.concat[[%epre];[%ename]]]|None,Somesuf->[%exprPpx_hardcaml_runtime.concat[[%ename];[%esuf]]]|Somepre,Somesuf->[%exprPpx_hardcaml_runtime.concat[[%epre];[%ename];[%esuf]]][@metalocloc];;letmangle_name~locnamemangle=matchmanglewith|Someseparator->[%exprPpx_hardcaml_runtime.concat[[%ename];[%eseparator];_n]]|None->[%expr_n];;(*
* Code generation utility functions
*)letexpand_array_init~locvnamelabel_declaration=letnbits=get_bits~loclabel_declarationinletlength=get_length~loclabel_declarationin[%exprPpx_hardcaml_runtime.Array.init[%elength]~f:(fun_i->(Ppx_hardcaml_runtime.concat[[%evname];Ppx_hardcaml_runtime.Int.to_string_i],[%enbits]))];;letexpand_array_init_str~locvnamemapidmidlabel_declaration=letlength=get_length~loclabel_declarationin[%exprPpx_hardcaml_runtime.Array.init[%elength]~f:(fun_i->[%emapid][%epexp_ident~locmid]~f:(fun(_n,_b)->[%evname],_b))];;(*
* Expand t label
*)letexpand_port_names_and_widths_label_arrayvarloclabel_declarationnameprefixsuffixmangle=function(* 'a *)|Ptyp_varvwhenString.equalvvar->letrtlident=mk_rtlident~locnameprefixsuffixinexpand_array_init~locrtlidentlabel_declaration(* 'a Module.t *)|Ptyp_constr({txt=Ldot(mname,_);loc},[{ptyp_desc=Ptyp_varv;_}])whenString.equalvvar->letmid={txt=Ldot(mname,"port_names_and_widths");loc}inletmangled=[%exprPpx_hardcaml_runtime.concat[[%emangle_name~locnamemangle];Ppx_hardcaml_runtime.Int.to_string_i]]inletrtlident=mk_rtlident~locmangledprefixsuffixinletmapid=pexp_ident~loc(Located.mk~loc(Ldot(mname,"map")))inexpand_array_init_str~locrtlidentmapidmidlabel_declaration(* Default *)|_->raise_errorf~loc"[%s] expand_port_names_and_widths_label_array: only supports abstract record \
labels"deriver;;letexpand_port_names_and_widths_label_listvarloclabel_declarationnameprefixsuffixmangledesc=letainit=expand_port_names_and_widths_label_arrayvarloclabel_declarationnameprefixsuffixmangledescin[%exprPpx_hardcaml_runtime.Array.to_list[%eainit]];;letexpand_port_names_and_widths_expresionoptsvar({pld_name={txt;loc;_};_}aslabel_declaration)ptyp_desc=letrtlname=get_rtlname~loctxtlabel_declarationandrtlprefix=get_rtlprefix~locoptslabel_declarationandrtlsuffix=get_rtlsuffix~locoptslabel_declarationandrtlmangle=get_rtlmangle~locoptslabel_declarationinmatchptyp_descwith(* 'a *)|Ptyp_varvwhenString.equalvvar->letnbits=get_bits~loclabel_declarationandrtlident=mk_rtlident~locrtlnamertlprefixrtlsuffixinpexp_tuple~loc[rtlident;nbits](* 'a Module.t *)|Ptyp_constr({txt=Ldot(mname,_);loc},[{ptyp_desc=Ptyp_varv;_}])whenString.equalvvar->letmid={txt=Ldot(mname,"port_names_and_widths");loc}inletmangled=mangle_name~locrtlnamertlmangleinletrtlident=mk_rtlident~locmangledrtlprefixrtlsuffixinletmapid=pexp_ident~loc(Located.mk~loc(Ldot(mname,"map")))in[%expr[%emapid][%epexp_ident~locmid]~f:(fun(_n,_b)->[%ertlident],_b)](* 'a list, 'a Module.t list *)|Ptyp_constr({txt=Lident"list";_},[{ptyp_desc;_}])->expand_port_names_and_widths_label_listvarloclabel_declarationrtlnamertlprefixrtlsuffixrtlmangleptyp_desc(* 'a array, 'a Module.t array *)|Ptyp_constr({txt=Lident"array";_},[{ptyp_desc;_}])->expand_port_names_and_widths_label_arrayvarloclabel_declarationrtlnamertlprefixrtlsuffixrtlmangleptyp_desc(* Default *)|_->raise_errorf~loc"[%s] expand_port_names_and_widths_label: only supports abstract record labels"deriver;;letexpand_port_names_and_widths_labeloptsvar({pld_name={txt;loc};_}aslabel_declaration)=letexpand_inner_expressionptyp_desc=expand_port_names_and_widths_expresionoptsvarlabel_declarationptyp_descinletexpr=matchlabel_declaration.pld_type.ptyp_descwith|Ptyp_constr({txt=Lident"option";_},[{ptyp_desc;_}])->letexists=matchAttribute.(findexists)label_declarationwith|Someexists->exists|None->raise_errorf~loc"[%s] exists attribute must be in [option]"deriverin[%exprif[%eexists]thenSome[%eexpand_inner_expressionptyp_desc]elseNone]|ptyp_desc->expand_inner_expressionptyp_descinLocated.mk~loc(Lidenttxt),expr;;(*
* Expand map label
*)letmkfieldvarmemb=letloc=Location.noneinpexp_field~loc(pexp_ident~loc(Located.mk~loc(Lidentvar)))(Located.mk~loc(Lidentmemb));;moduleIter_or_map=structtypet=|Iter|Mapletname=function|Iter->"iter"|Map->"map";;letname2=function|Iter->"iter2"|Map->"map2";;letoption_maptloc=matchtwith|Iter->[%exprBase.Option.iter]|Map->[%exprBase.Option.map];;letoption_map2_exntloc=matchtwith|Iter->[%exprPpx_hardcaml_runtime.option_iter2_exn]|Map->[%exprPpx_hardcaml_runtime.option_map2_exn];;letarray_maptloc=matchtwith|Iter->[%exprPpx_hardcaml_runtime.Array.iter]|Map->[%exprPpx_hardcaml_runtime.Array.map];;letarray_inittloc=matchtwith|Iter->[%exprPpx_hardcaml_runtime.Array.for_]|Map->[%exprPpx_hardcaml_runtime.Array.init];;letlist_maptloc=matchtwith|Iter->[%exprPpx_hardcaml_runtime.List.iter]|Map->[%exprPpx_hardcaml_runtime.List.map];;letlist_map2_exntloc=matchtwith|Iter->[%exprPpx_hardcaml_runtime.List.iter2_exn]|Map->[%exprPpx_hardcaml_runtime.List.map2_exn];;endletexpand_map_label_listiter_or_mapvarlocident=function(* 'a *)|Ptyp_varvwhenString.equalvvar->[%expr[%eIter_or_map.list_mapiter_or_maploc][%eident]~f](* 'a Module.t *)|Ptyp_constr({txt=Ldot(mname,_);_},[{ptyp_desc=Ptyp_varv;_}])whenString.equalvvar->letmapid=pexp_ident~loc(Located.mk~loc(Ldot(mname,Iter_or_map.nameiter_or_map)))in[%expr[%eIter_or_map.list_mapiter_or_maploc][%eident]~f:(fun_e->[%emapid]_e~f)](* Default *)|_->raise_errorf~loc"[%s] expand_map_label_list: only supports abstract record labels"deriver;;letexpand_map_label_arrayiter_or_mapvarlocident=function(* 'a *)|Ptyp_varvwhenString.equalvvar->[%expr[%eIter_or_map.array_mapiter_or_maploc][%eident]~f](* 'a Module.t *)|Ptyp_constr({txt=Ldot(mname,_);_},[{ptyp_desc=Ptyp_varv;_}])whenString.equalvvar->letmapid=pexp_ident~loc(Located.mk~loc(Ldot(mname,Iter_or_map.nameiter_or_map)))in[%expr[%eIter_or_map.array_mapiter_or_maploc][%eident]~f:(fun_e->[%emapid]_e~f)](* Default *)|_->raise_errorf~loc"[%s] expand_map_label_list: only supports abstract record labels"deriver;;moduleRecord_field=structtypet={label_declaration:label_declaration;expression:expression}letexpressiont=t.expressionletlabel_textt=t.label_declaration.pld_name.txtendletexpand_map_label_expression(iter_or_map:Iter_or_map.t)varlocptyp_descident=matchptyp_descwith(* 'a *)|Ptyp_varvwhenString.equalvvar->[%exprf[%eident]](* 'a Module.t *)|Ptyp_constr({txt=Ldot(mname,_);_},[{ptyp_desc=Ptyp_varv;_}])whenString.equalvvar->letmapid=pexp_ident~loc(Located.mk~loc(Ldot(mname,Iter_or_map.nameiter_or_map)))in[%expr[%emapid][%eident]~f](* 'a list, 'a Module.t list *)|Ptyp_constr({txt=Lident"list";_},[{ptyp_desc;_}])->expand_map_label_listiter_or_mapvarlocidentptyp_desc(* 'a array, 'a Module.t array *)|Ptyp_constr({txt=Lident"array";_},[{ptyp_desc;_}])->expand_map_label_arrayiter_or_mapvarlocidentptyp_desc(* Default *)|_->raise_errorf~loc"[%s] expand_map_label: only supports abstract record labels"deriver;;letexpand_map_labeliter_or_mapvar({pld_name={txt;loc};_}aslabel_declaration):Record_field.t=letexpand_inner_expressionptyp_descx=expand_map_label_expressioniter_or_mapvarlocptyp_descxinletident=mkfield"x"txtinletexpression=matchlabel_declaration.pld_type.ptyp_descwith|Ptyp_constr({txt=Lident"option";_},[{ptyp_desc;_}])->[%expr[%eIter_or_map.option_mapiter_or_maploc]~f:(funx->[%eexpand_inner_expressionptyp_desc[%exprx]])[%eident]]|ptyp_desc->expand_inner_expressionptyp_descidentin{label_declaration;expression};;(*
* Expand map2 label
*)letexpand_map2_label_listiter_or_mapvarlocident0ident1=function(* 'a *)|Ptyp_varvwhenString.equalvvar->[%expr[%eIter_or_map.list_map2_exniter_or_maploc][%eident0][%eident1]~f](* 'a Module.t *)|Ptyp_constr({txt=Ldot(mname,_);_},[{ptyp_desc=Ptyp_varv;_}])whenString.equalvvar->letmapid=pexp_ident~loc(Located.mk~loc(Ldot(mname,Iter_or_map.name2iter_or_map)))in[%expr[%eIter_or_map.list_map2_exniter_or_maploc][%eident0][%eident1]~f:(fun_e0_e1->[%emapid]_e0_e1~f)](* Default *)|_->raise_errorf~loc"[%s] expand_map_label_list: only supports abstract record labels"deriver;;letexpand_map2_label_arrayiter_or_mapvarlocident0ident1=function(* 'a *)|Ptyp_varvwhenString.equalvvar->[%expr[%eIter_or_map.array_inititer_or_maploc](Array.length[%eident0])~f:(fun_i->f(Ppx_hardcaml_runtime.Array.get[%eident0]_i)(Ppx_hardcaml_runtime.Array.get[%eident1]_i))](* 'a Module.t *)|Ptyp_constr({txt=Ldot(mname,_);_},[{ptyp_desc=Ptyp_varv;_}])whenString.equalvvar->letmapid=pexp_ident~loc(Located.mk~loc(Ldot(mname,Iter_or_map.name2iter_or_map)))in[%expr[%eIter_or_map.array_inititer_or_maploc](Array.length[%eident0])~f:(fun_i->[%emapid](Ppx_hardcaml_runtime.Array.get[%eident0]_i)(Ppx_hardcaml_runtime.Array.get[%eident1]_i)~f)](* Default *)|_->raise_errorf~loc"[%s] expand_map_label_list: only supports abstract record labels"deriver;;letexpand_map2_label_expression(iter_or_map:Iter_or_map.t)varloc(ptyp_desc:Ppxlib.core_type_desc)ident0ident1=matchptyp_descwith(* 'a *)|Ptyp_varvwhenString.equalvvar->[%exprf[%eident0][%eident1]](* 'a Module.t *)|Ptyp_constr({txt=Ldot(mname,_);_},[{ptyp_desc=Ptyp_varv;_}])whenString.equalvvar->letmapid=pexp_ident~loc(Located.mk~loc(Ldot(mname,Iter_or_map.name2iter_or_map)))in[%expr[%emapid][%eident0][%eident1]~f](* 'a list, 'a Module.t list *)|Ptyp_constr({txt=Lident"list";_},[{ptyp_desc;_}])->expand_map2_label_listiter_or_mapvarlocident0ident1ptyp_desc(* 'a array, 'a Module.t array *)|Ptyp_constr({txt=Lident"array";_},[{ptyp_desc;_}])->expand_map2_label_arrayiter_or_mapvarlocident0ident1ptyp_desc(* Default *)|_->raise_errorf~loc"[%s] expand_map2_label: only supports abstract record labels"deriver;;letexpand_map2_labeliter_or_mapvar({pld_name={txt;loc};_}aslabel_declaration):Record_field.t=letexpand_inner_expressionptyp_descx0x1=expand_map2_label_expressioniter_or_mapvarlocptyp_descx0x1inletident0=mkfield"x0"txtinletident1=mkfield"x1"txtinletexpression=matchlabel_declaration.pld_type.ptyp_descwith|Ptyp_constr({txt=Lident"option";_},[{ptyp_desc;_}])->[%expr[%eIter_or_map.option_map2_exniter_or_maploc]~f:(funx0x1->[%eexpand_inner_expressionptyp_desc[%exprx0][%exprx1]])[%eident0][%eident1]]|ptyp_desc->expand_inner_expressionptyp_descident0ident1in{label_declaration;expression};;(*
* Expand to_list label
*)letexpand_to_list_label_listvarlocident=function(* 'a *)|Ptyp_varvwhenString.equalvvar->ident(* 'a Module.t *)|Ptyp_constr({txt=Ldot(mname,_);_},[{ptyp_desc=Ptyp_varv;_}])whenString.equalvvar->letto_list_id=pexp_ident~loc(Located.mk~loc(Ldot(mname,"to_list")))in[%exprPpx_hardcaml_runtime.List.concat(Ppx_hardcaml_runtime.List.map[%eident]~f:(fun_e->[%eto_list_id]_e))](* Default *)|_->raise_errorf~loc"[%s] expand_map_label_list: only supports abstract record labels"deriver;;letexpand_to_list_label_arrayvarlocidentdesc=expand_to_list_label_listvarloc[%exprPpx_hardcaml_runtime.Array.to_list[%eident]]desc;;letexpand_to_list_label_expressionvarlocptyp_descident=matchptyp_descwith(* 'a *)|Ptyp_varvwhenString.equalvvar->[%expr[[%eident]]](* 'a *)|Ptyp_constr({txt=Lident"option";_},[{ptyp_desc=Ptyp_varv;_}])whenString.equalvvar->[%exprBase.Option.to_list[%eident]](* 'a Module.t *)|Ptyp_constr({txt=Ldot(mname,_);_},[{ptyp_desc=Ptyp_varv;_}])whenString.equalvvar->pexp_apply~loc(pexp_ident~loc(Located.mk~loc(Ldot(mname,"to_list"))))[Nolabel,ident](* 'a list, 'a Module.t list *)|Ptyp_constr({txt=Lident"list";_},[{ptyp_desc;_}])->expand_to_list_label_listvarlocidentptyp_desc(* 'a array, 'a Module.t array *)|Ptyp_constr({txt=Lident"array";_},[{ptyp_desc;_}])->expand_to_list_label_arrayvarlocidentptyp_desc(* Default *)|_->raise_errorf~loc"[%s] expand_to_list_label: only supports abstract record labels"deriver;;letexpand_to_list_labelvar({pld_name={txt;loc};_}aslabel_declaration)=letident=mkfield"x"txtinletexpand_inner_expressionptyp_descx=expand_to_list_label_expressionvarlocptyp_descxinmatchlabel_declaration.pld_type.ptyp_descwith|Ptyp_constr({txt=Lident"option";_},[{ptyp_desc;_}])->[%exprmatch[%eident]with|None->[]|Somex->[%eexpand_inner_expressionptyp_desc[%exprx]]]|ptyp_desc->expand_inner_expressionptyp_descident;;letbuild_expr_listlabels=letloc=Location.noneinList.fold_rightlabels~f:(funexpracc->pexp_construct~loc(Located.mk~loc(Lident"::"))(Some(pexp_tuple~loc[expr;acc])))~init:(pexp_construct~loc(Located.mk~loc(Lident"[]"))None);;(*
* Expand ast label
*)letexpand_ast_labeloptsvar({pld_name={txt;loc;_};pld_type;_}aslabel_declaration)=letexpand_exprptyp_desc=letrtlname=get_rtlname~loctxtlabel_declarationandrtlprefix=get_rtlprefix~locoptslabel_declarationandrtlsuffix=get_rtlsuffix~locoptslabel_declaration(* and rtlmangle = get_rtlmangle ~loc opts label_declaration *)inletsignal()=letrtlident=mk_rtlident~locrtlnamertlprefixrtlsuffixinletbits=get_bits~loclabel_declarationin[%exprSignal{bits=[%ebits];rtlname=[%ertlident]}]inletmodule_mname=letast=pexp_ident~loc(Located.mk~loc(Ldot(mname,"ast")))inletmname=letmname=Longident.flatten_exnmname|>String.concat~sep:"."inpexp_constant~loc(Pconst_string(mname,loc,None))in[%exprModule{name=[%emname];ast=[%east]}]inletsequencekind=letlength=get_length~loclabel_declarationin[%exprSome{kind=[%ekind];length=[%elength]}]inlettype_,sequence=matchptyp_descwith(* 'a *)|Ptyp_varvwhenString.equalvvar->signal(),[%exprNone](* 'a Module.t *)|Ptyp_constr({txt=Ldot(mname,_);_},[{ptyp_desc=Ptyp_varv;_}])whenString.equalvvar->module_mname,[%exprNone](* 'a list *)|Ptyp_constr({txt=Lident"list";_},[{ptyp_desc=Ptyp_varv;_}])whenString.equalvvar->signal(),sequence[%exprList](* 'a Module.t list *)|Ptyp_constr({txt=Lident"list";_},[{ptyp_desc=Ptyp_constr({txt=Ldot(mname,_);_},[{ptyp_desc=Ptyp_varv;_}]);_}])whenString.equalvvar->module_mname,sequence[%exprList](* 'a array *)|Ptyp_constr({txt=Lident"array";_},[{ptyp_desc=Ptyp_varv;_}])whenString.equalvvar->signal(),sequence[%exprArray](* 'a Module.t array *)|Ptyp_constr({txt=Lident"array";_},[{ptyp_desc=Ptyp_constr({txt=Ldot(mname,_);_},[{ptyp_desc=Ptyp_varv;_}]);_}])whenString.equalvvar->module_mname,sequence[%exprArray](* Default *)|_->raise_errorf~loc"[%s] expand_doc_label: only supports abstract record labels"deriverinletfield_name=field_name~loctxtinletdoc=matchget_doc~loclabel_declarationwith|None->[%exprNone]|Somedoc->[%exprSome[%epexp_constant~loc(Pconst_string(doc,loc,None))]]in[%expr{Ppx_hardcaml_runtime.Interface.Ast.Field.name=[%efield_name];type_=[%etype_];sequence=[%esequence];doc=[%edoc]}]inexpand_exprpld_type.ptyp_desc;;(*
* PPX deriving
*)letpexp_sequenceN~locexprs=matchList.revexprswith|[]->[%expr()]|[e]->e|last::es->List.foldes~init:last~f:(funace->pexp_sequence~loceac);;letrecord_fields(iter_or_map:Iter_or_map.t)~locfields=matchiter_or_mapwith|Iter->pexp_sequenceN~loc(List.mapfields~f:Record_field.expression)|Map->pexp_let~locNonrecursive(List.mapfields~f:(funrecord_field->value_binding~loc~pat:(pvar~loc(Record_field.label_textrecord_field))~expr:record_field.expression))(pexp_record~loc(List.mapfields~f:(funrecord_field->letid=Located.mk~loc(Lident(Record_field.label_textrecord_field))inid,pexp_ident~locid))None);;letstr_of_type~options({ptype_loc=loc;_}astype_decl)=matchtype_decl.ptype_kind,type_decl.ptype_paramswith|Ptype_recordlabels,[({ptyp_desc=Ptyp_varvar;_},_)]->letstr_port_names_and_widths_labels=List.maplabels~f:(expand_port_names_and_widths_labeloptionsvar)inletstr_port_names_and_widths=pexp_record~locstr_port_names_and_widths_labelsNoneinletstr_mapiter_or_map=letfields=List.maplabels~f:(expand_map_labeliter_or_mapvar)in[%exprfunx~f->[%erecord_fieldsiter_or_map~locfields]]inletstr_map2iter_or_map=letfields=List.maplabels~f:(expand_map2_labeliter_or_mapvar)in[%exprfunx0x1~f->[%erecord_fieldsiter_or_map~locfields]]inletstr_to_list_labels=List.maplabels~f:(expand_to_list_labelvar)inletstr_to_list_args=build_expr_liststr_to_list_labelsinletstr_to_list=[%exprfunx->Ppx_hardcaml_runtime.List.concat[%estr_to_list_args]]inletstr_ast_labels()=List.maplabels~f:(expand_ast_labeloptionsvar)inletstr_ast()=build_expr_list(str_ast_labels())in[pstr_value~locNonrecursive([value_binding~loc~pat:(pvar~loc"port_names_and_widths")~expr:str_port_names_and_widths;value_binding~loc~pat:(pvar~loc"iter")~expr:(str_mapIter);value_binding~loc~pat:(pvar~loc"iter2")~expr:(str_map2Iter);value_binding~loc~pat:(pvar~loc"map")~expr:(str_mapMap);value_binding~loc~pat:(pvar~loc"map2")~expr:(str_map2Map);value_binding~loc~pat:(pvar~loc"to_list")~expr:str_to_list]@ifoptions.astthen[value_binding~loc~pat:(pvar~loc"ast")~expr:(str_ast())]else[]);[%striincludePpx_hardcaml_runtime.Interface.Make(structtypenonrec'at='atletsexp_of_t=sexp_of_tletport_names_and_widths=port_names_and_widthsletiter=iterletiter2=iter2letmap=mapletmap2=map2letto_list=to_listend)]]|_->raise_errorf~loc"[%s] str_of_type: only supports record types"deriver;;letsig_of_type~ast({ptype_loc=loc;_}astype_decl)=matchtype_decl.ptype_kind,type_decl.ptype_paramswith|Ptype_record_,[({ptyp_desc=Ptyp_var_;_},_)]->letintf=[%sigi:includePpx_hardcaml_runtime.Interface.Swithtype'at:='at]inifastthen[intf;[%sigi:valast:Ppx_hardcaml_runtime.Interface.Ast.t]]else[intf]|_,_->raise_errorf~loc"[%s] sig_of_type: only supports record types"deriver;;letdeclare_let_binding_extension~name~generate_naming_function=letpattern=(* Matches let bindings. The __' also captures the location of the [rec] flag, if
present. The second __ captures the bindings, and the final __ captures the [rhs]
of the let binding. *)Ast_pattern.(single_expr_payload(pexp_let__'____))inExtension.declare_with_path_argnameExpressionpattern(fun~loc~path:_~argrecursive_flagbindingsrhs->(* We don't support recursive let bindings *)(matchrecursive_flag.txtwith|Recursive->Location.raise_errorf~loc:recursive_flag.loc"[let rec] not supported."|Nonrecursive->());(* Wrap all the bindings in a naming function. Turns:
{v
let x = 0
and y = 1
in rhs
v}
into:
{v
let x = (generated_naming_function) 0
and y = (generated_naming_function) 1
in rhs
v}
We only support simple bindings like the above right now. Bindings like:
let { x; y } = something in rhs
aren't supported. *)letbindings=List.mapbindings~f:(fun{pvb_pat;pvb_expr;pvb_attributes;pvb_loc;pvb_constraint}->(* The [pvb_pat] must be a simple assignment to a name right now. Maybe we
can add support for structure unpacking later. *)letloc={pvb_locwithloc_ghost=true}inmatchpvb_pat.ppat_descwith|Ppat_var{txt;loc=_}->{pvb_pat;pvb_expr=[%expr[%egenerate_naming_function~arg~loc~name:txt][%epvb_expr]];pvb_attributes;pvb_loc;pvb_constraint}|_->Location.raise_errorf~loc:pvb_pat.ppat_loc"This form of let binding is not currently supported")inpexp_let~locNonrecursivebindingsrhs);;lethardcaml_name()=declare_let_binding_extension~name:"hw"~generate_naming_function:(fun~arg~loc~name->matchargwith|None->[%exprfunsignal_to_name->Hardcaml.Scope.namingscopesignal_to_name[%eestring~locname]]|Some{loc=_;txt=module_of_type_of_expression_being_named}->letapply_names=String.concat~sep:"."(Longident.flatten_exnmodule_of_type_of_expression_being_named@["apply_names"])in[%exprfunintf_to_name->(* Ignore the result of 'apply_names'. Of_always.apply_names returns a unit,
but Of_signal.apply_names just returns a Signal that we want to ignore. It
is assumed that a scope named [scope] is present when calling this
fucntion. *)let(_:_)=[%eevar~locapply_names]~prefix:[%eestring~loc(name^"$")]~naming_op:(Hardcaml.Scope.namingscope)intf_to_nameinintf_to_name]);;lethardcaml_name_var()=declare_let_binding_extension~name:"hw_var"~generate_naming_function:(fun~arg~loc~name->matchargwith|None->[%exprfun(variable_to_name:Hardcaml.Always.Variable.t)->let(_:Hardcaml.Signal.t)=Hardcaml.Scope.namingscopevariable_to_name.value[%eestring~locname]invariable_to_name]|Some_->Location.raise_errorf~loc"[hw_var] does not take a module argument. It is only used with plain \
[Variable.t]s - use [let%%hw.Your_type_here.Of_always] instead");;let()=letget_bool_option~locoption=Option.bindoption~f:(parse_rtlmangle~loc)inlethardcaml_internal=Deriving.add"hardcaml_internal"~str_type_decl:(Deriving.Generator.makeDeriving.Args.(empty+>arg"rtlprefix"Ast_pattern.__+>arg"rtlsuffix"Ast_pattern.__+>arg"rtlmangle"Ast_pattern.__+>flag"ast")(fun~loc~path:_(_,type_declarations)rtlprefixrtlsuffixrtlmangleast->letoptions={rtlprefix;rtlsuffix;rtlmangle=get_bool_option~locrtlmangle;ast}inList.concat_maptype_declarations~f:(fundecl->str_of_type~optionsdecl)))~sig_type_decl:(Deriving.Generator.makeDeriving.Args.(empty+>flag"ast")(fun~loc:_~path:_(_,type_declarations)ast->List.concat_maptype_declarations~f:(sig_of_type~ast)))in(* Ordering of the derivers of the alias below matters. Empirically, the
derivers are expanded in reverse order of the list.
*)Deriving.add_aliasderiver[hardcaml_internal;Ppx_sexp_conv.sexp_of]|>Deriving.ignore;Driver.register_transformation"hardcaml_naming"~rules:[Context_free.Rule.extension(hardcaml_name());Context_free.Rule.extension(hardcaml_name_var())];;