123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510(* Generated code should depend on the environment in scope as little as possible.
E.g. rather than [foo = []] do [match foo with [] ->], to eliminate the use of [=]. It
is especially important to not use polymorphic comparisons, since we are moving more
and more to code that doesn't have them in scope. *)openBaseopenPpxlibopenAst_builder.Defaultletraise_unsupportedloc=Location.raise_errorf~loc"Unsupported use of variants (you can only use it on variant types)."moduleCreate=structletlambdalocxsbody=List.fold_rightxs~init:body~f:(fun(label,p)e->pexp_fun~loclabelNonepe);;letlambda_siglocarg_tysbody_ty=List.fold_rightarg_tys~init:body_ty~f:(fun(label,arg_ty)acc->ptyp_arrow~loclabelarg_tyacc);;endmoduleVariant_constructor=structtypet={name:string;loc:Location.t;kind:[`Normalofcore_typelist|`Normal_inline_recordoflabel_declarationlist|`Polymorphicofcore_typeoption]}letargst=matcht.kindwith|`Normalpcd_args->List.mapipcd_args~f:(funi_->Nolabel,"v"^Int.to_stringi)|`Normal_inline_recordfields->List.mapifields~f:(funif->Labelledf.pld_name.txt,"v"^Int.to_stringi)|`PolymorphicNone->[]|`Polymorphic(Some_)->[Nolabel,"v0"]letpattern_without_binding{name;loc;kind}=matchkindwith|`Normal[]->ppat_construct~loc(Located.lident~locname)None|`Normal(_::_)|`Normal_inline_record_->ppat_construct~loc(Located.lident~locname)(Some(ppat_any~loc))|`PolymorphicNone->ppat_variant~locnameNone|`Polymorphic(Some_)->ppat_variant~locname(Some(ppat_any~loc))letto_fun_typet~rhs:body_ty=letarg_types=matcht.kindwith|`PolymorphicNone->[]|`Polymorphic(Somev)->[(Nolabel,v)]|`Normalargs->List.mapargs~f:(funtyp->Nolabel,typ)|`Normal_inline_recordfields->List.mapfields~f:(funcd->Labelledcd.pld_name.txt,cd.pld_type)inCreate.lambda_sigt.locarg_typesbody_tyendletvariant_name_to_stringv=lets=String.lowercasevinifKeyword.is_keywordsthens^"_"elsesmoduleInspect=structletrow_fieldlocrf:Variant_constructor.t=matchrf.prf_descwith|Rtag({txt=name;_},true,_)|Rtag({txt=name;_},_,[])->{name;loc;kind=`PolymorphicNone}|Rtag({txt=name;_},false,tp::_)->{name;loc;kind=`Polymorphic(Sometp)}|Rinherit_->Location.raise_errorf~loc"ppx_variants_conv: polymorphic variant inclusion is not supported"letconstructorcd:Variant_constructor.t=ifOption.is_somecd.pcd_resthenLocation.raise_errorf~loc:cd.pcd_loc"GADTs are not supported by variantslib";letkind=matchcd.pcd_argswith|Pcstr_tuplepcd_args->`Normalpcd_args|Pcstr_recordfields->`Normal_inline_recordfieldsin{name=cd.pcd_name.txt;loc=cd.pcd_name.loc;kind}lettype_decltd=letloc=td.ptype_locinmatchtd.ptype_kindwith|Ptype_variantcds->letcds=List.mapcds~f:constructorinletnames_as_string=Hashtbl.create(moduleString)inList.itercds~f:(fun{name;loc;_}->lets=variant_name_to_stringnameinmatchHashtbl.findnames_as_stringswith|None->Hashtbl.add_exnnames_as_string~key:s~data:name|Somename'->Location.raise_errorf~loc"ppx_variants_conv: constructors %S and %S both get mapped to value %S"namename's);cds|Ptype_record_|Ptype_open->raise_unsupportedloc|Ptype_abstract->matchtd.ptype_manifestwith|Some{ptyp_desc=Ptyp_variant(row_fields,Closed,None);_}->List.maprow_fields~f:(row_fieldloc)|Some{ptyp_desc=Ptyp_variant_;ptyp_loc=loc;_}->Location.raise_errorf~loc"ppx_variants_conv: polymorphic variants with a row variable are not supported"|_->raise_unsupportedlocendletvariants_module=function|"t"->"Variants"|type_name->"Variants_of_"^type_name;;moduleGen_sig=structletapply_typeloc~ty_name~tps=ptyp_constr~loc(Located.lident~locty_name)tpsletlabel_arg_locnamety=(Asttypes.Labelled(variant_name_to_stringname),ty);;letval_~locnametype_=psig_value~loc(value_description~loc~name:(Located.mk~locname)~type_~prim:[]);;letvariant_argf~variant_type(v:Variant_constructor.t)=letloc=v.locinletvariant=[%type:[%tVariant_constructor.to_fun_typev~rhs:variant_type]Variantslib.Variant.t]inlabel_arglocv.Variant_constructor.name(f~variant);;letv_fold_fun~variant_typelocvariants=letf=variant_arg~variant_type(fun~variant->[%type:'acc__->[%tvariant]->'acc__])inlettypes=List.mapvariants~finletinit_ty=label_argloc"init"[%type:'acc__]inlett=Create.lambda_sigloc(init_ty::types)[%type:'acc__]inval_~loc"fold"t;;letv_iter_fun~variant_typelocvariants=letf=variant_arg~variant_type(fun~variant->[%type:[%tvariant]->unit])inlettypes=List.mapvariants~finlett=Create.lambda_sigloctypes[%type:unit]inval_~loc"iter"t;;letv_map_fun~variant_typelocvariants=letmoduleV=Variant_constructorinletresult_type=[%type:'result__]inletfv=letvariant=letconstructor_type=V.to_fun_typev~rhs:variant_typeinCreate.lambda_sigloc[Nolabel,[%type:[%tconstructor_type]Variantslib.Variant.t]](V.to_fun_typev~rhs:result_type)inlabel_arglocv.V.namevariantinlettypes=List.mapvariants~finlett=Create.lambda_sigloc((Nolabel,variant_type)::types)result_typeinval_~loc"map"t;;letv_make_matcher_fun~variant_typelocvariants=letresult_type=[%type:'result__]inletacci=ptyp_var~loc("acc__"^Int.to_stringi)inletfiv=letvariant=[%type:[%tVariant_constructor.to_fun_typev~rhs:variant_type]Variantslib.Variant.t]inletfun_type=matchVariant_constructor.argsvwith|[]->[%type:unit->[%tresult_type]]|(_::_)->Variant_constructor.to_fun_typev~rhs:result_typeinlabel_arglocv.name[%type:[%tvariant]->[%tacci]->[%tfun_type]*[%tacc(i+1)]]inlettypes=List.mapivariants~finlett=Create.lambda_sigloc(types@[Nolabel,acc0])[%type:([%tvariant_type]->[%tresult_type])*[%t(acc(List.lengthvariants))]]inval_~loc"make_matcher"t;;letv_descriptions~variant_type:_loc_=val_~loc"descriptions"[%type:(string*int)list]letv_to_rank_fun~variant_typeloc_=val_~loc"to_rank"[%type:[%tvariant_type]->int];;letv_to_name_fun~variant_typeloc_=val_~loc"to_name"[%type:[%tvariant_type]->string];;letvariant~variant_type~ty_namelocvariants=letconstructors,variant_defs=List.unzip(List.mapvariants~f:(funv->letmoduleV=Variant_constructorinletconstructor_type=V.to_fun_typev~rhs:variant_typeinletname=variant_name_to_stringv.V.namein(val_~locnameconstructor_type,val_~locname[%type:[%tconstructor_type]Variantslib.Variant.t])))inconstructors@[psig_module~loc(module_declaration~loc~name:(Located.mk~loc(Some(variants_modulety_name)))~type_:(pmty_signature~loc(variant_defs@[v_fold_fun~variant_typelocvariants;v_iter_fun~variant_typelocvariants;v_map_fun~variant_typelocvariants;v_make_matcher_fun~variant_typelocvariants;v_to_rank_fun~variant_typelocvariants;v_to_name_fun~variant_typelocvariants;v_descriptions~variant_typelocvariants])))];;letvariants_of_tdtd=letty_name=td.ptype_name.txtinletloc=td.ptype_locinletvariant_type=apply_typeloc~ty_name~tps:(List.maptd.ptype_params~f:fst)invariant~variant_type~ty_nameloc(Inspect.type_decltd)letgenerate~loc~path:_(rec_flag,tds)=(matchrec_flagwith|Nonrecursive->Location.raise_errorf~loc"nonrec is not compatible with the `ppx_variants_conv' preprocessor"|_->());matchtdswith|[td]->variants_of_tdtd|_->Location.raise_errorf~loc"ppx_variants_conv: not supported"endmoduleGen_str=structletconstructors_and_variantslocvariants=letmoduleV=Variant_constructorinList.unzip(List.mapivariants~f:(funrankv->letuncapitalized=variant_name_to_stringv.V.nameinletconstructor=letconstructed_value=matchv.V.kindwith|`Normal_->letarg=pexp_tuple_opt~loc(List.map(V.argsv)~f:(fun(_,v)->evar~locv))inpexp_construct~loc(Located.lident~locv.V.name)arg|`Polymorphic_->letarg=pexp_tuple_opt~loc(List.map(V.argsv)~f:(fun(_,v)->evar~locv))inpexp_variant~locv.V.namearg|`Normal_inline_recordfields->letarg=pexp_record~loc(List.map2_exnfields(V.argsv)~f:(funf(_,name)->Located.lident~locf.pld_name.txt,evar~locname))Noneinpexp_construct~loc(Located.lident~locv.V.name)(Somearg)inpstr_value~locNonrecursive[value_binding~loc~pat:(pvar~locuncapitalized)~expr:(List.fold_right(V.argsv)~init:constructed_value~f:(fun(label,v)e->pexp_fun~loclabelNone(pvar~locv)e))]inletvariant=[%strilet[%ppvar~locuncapitalized]={Variantslib.Variant.name=[%eestring~locv.V.name];rank=[%eeint~locrank];constructor=[%eevar~locuncapitalized]}]inconstructor,variant));;letlabel_arg?labellocname=letl=matchlabelwith|None->name|Somen->nin(Asttypes.Labelledl,pvar~locname);;letlabel_arg_funlocname=label_arg~label:nameloc(name^"_fun__");;letv_fold_funlocvariants=letmoduleV=Variant_constructorinletvariant_foldacc_exprvariant=letvariant_name=variant_name_to_stringvariant.V.namein[%expr[%eevar~loc(variant_name^"_fun__")][%eacc_expr][%eevar~locvariant_name]]inletbody=List.fold_leftvariants~init:[%exprinit__]~f:variant_foldinletpatterns=List.mapvariants~f:(funvariant->label_arg_funloc(variant_name_to_stringvariant.V.name))inletinit=label_arg~label:"init"loc"init__"inletlambda=Create.lambdaloc(init::patterns)bodyin[%striletfold=[%elambda]];;letv_descriptionslocvariants=letmoduleV=Variant_constructorinletfv=[%expr([%eestring~locv.V.name],[%eeint~loc(List.length(V.argsv))])]inletvariant_names=List.map~fvariantsin[%striletdescriptions=[%eelist~locvariant_names]];;letv_map_funlocvariants=letmoduleV=Variant_constructorinletvariant_match_casevariant=letpattern=matchvariant.V.kindwith|`Polymorphic_->letarg=ppat_tuple_opt~loc(List.map(V.argsvariant)~f:(fun(_,v)->pvar~locv))inppat_variant~locvariant.V.namearg|`Normal_->letarg=ppat_tuple_opt~loc(List.map(V.argsvariant)~f:(fun(_,v)->pvar~locv))inppat_construct~loc(Located.lident~locvariant.V.name)arg|`Normal_inline_recordfields->letarg=ppat_record~loc(List.map2_exnfields(V.argsvariant)~f:(funf(_,v)->Located.lident~locf.pld_name.txt,pvar~locv))Closedinppat_construct~loc(Located.lident~locvariant.V.name)(Somearg)inletuncapitalized=variant_name_to_stringvariant.V.nameinletvalue=List.fold_left(V.argsvariant)~init:(eapply~loc(evar~loc(uncapitalized^"_fun__"))[evar~locuncapitalized])~f:(funacc_expr(label,var)->pexp_apply~locacc_expr[label,evar~locvar])incase~guard:None~lhs:pattern~rhs:valueinletbody=pexp_match~loc[%exprt__](List.mapvariants~f:variant_match_case)inletpatterns=List.mapvariants~f:(funvariant->label_arg_funloc(variant_name_to_stringvariant.V.name))inletlambda=Create.lambdaloc((Nolabel,[%pat?t__])::patterns)bodyin[%striletmap=[%elambda]];;letv_iter_funlocvariants=letmoduleV=Variant_constructorinletnames=List.mapvariants~f:(funv->variant_name_to_stringv.V.name)inletvariant_itervariant=letvariant_name=variant_name_to_stringvariant.V.namein[%expr([%eevar~loc(variant_name^"_fun__")][%eevar~locvariant_name]:unit)]inletbody=esequence~loc(List.mapvariants~f:variant_iter)inletpatterns=List.mapnames~f:(label_arg_funloc)inletlambda=Create.lambdalocpatternsbodyin[%striletiter=[%elambda]];;letv_make_matcher_funlocvariants=letmoduleV=Variant_constructorinletresult=letmap=List.fold_leftvariants~init:[%exprmap]~f:(funaccvariant->letvariant_name=variant_name_to_stringvariant.V.nameinpexp_apply~locacc[Labelledvariant_name,matchV.argsvariantwith|[]->[%exprfun_->[%eevar~loc(variant_name^"_gen__")]()]|(_::_)->[%exprfun_->[%eevar~loc(variant_name^"_gen__")]]])in[%expr[%emap],compile_acc__]inletbody=List.fold_rightvariants~init:result~f:(funvariantacc->letvariant_name=variant_name_to_stringvariant.V.nameinpexp_let~locNonrecursive[value_binding~loc~pat:(ppat_tuple~loc[[%pat?[%ppvar~loc(variant_name^"_gen__")]];[%pat?compile_acc__];])~expr:[%expr[%eevar~loc(variant_name^"_fun__")][%eevar~locvariant_name]compile_acc__]]acc)inletpatterns=List.mapvariants~f:(funv->label_arg_funloc(variant_name_to_stringv.V.name))inletlambda=Create.lambdaloc(patterns@[Nolabel,[%pat?compile_acc__]])bodyin[%striletmake_matcher=[%elambda]];;letcase_analysis_ignoring_valuesvariants~f=letpattern_and_rhs=List.mapivariants~f:(funrankv->Variant_constructor.pattern_without_bindingv,f~rank~name:v.name)inList.mappattern_and_rhs~f:(fun(pattern,rhs)->case~guard:None~lhs:pattern~rhs);;letv_to_ranklocty=letcases=case_analysis_ignoring_valuesty~f:(fun~rank~name:_->eint~locrank)in[%striletto_rank=[%epexp_function~loccases]];;letv_to_namelocty=letcases=case_analysis_ignoring_valuesty~f:(fun~rank:_~name->estring~locname)in[%striletto_name=[%epexp_function~loccases]];;letvariant~variant_namelocty=letconstructors,variants=constructors_and_variantsloctyinconstructors@[pstr_module~loc(module_binding~loc~name:(Located.mk~loc(Some(variants_modulevariant_name)))~expr:(pmod_structure~loc(variants@[v_fold_funlocty;v_iter_funlocty;v_map_funlocty;v_make_matcher_funlocty;v_to_ranklocty;v_to_namelocty;v_descriptionslocty])))];;letvariants_of_tdtd=letvariant_name=td.ptype_name.txtinletloc=td.ptype_locinvariant~variant_nameloc(Inspect.type_decltd)letgenerate~loc~path:_(rec_flag,tds)=(matchrec_flagwith|Nonrecursive->Location.raise_errorf~loc"nonrec is not compatible with the `ppx_variants_conv' preprocessor"|_->());matchtdswith|[td]->variants_of_tdtd|_->Location.raise_errorf~loc"ppx_variants_conv: not supported"endletvariants=Deriving.add"variants"~str_type_decl:(Deriving.Generator.make_noargGen_str.generate)~sig_type_decl:(Deriving.Generator.make_noargGen_sig.generate);;