123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117(*
* Generic transformers: plugins.
* Copyright (C) 2016-2022
* Dmitrii Kosarev aka Kakadu
* St.Petersburg State University, JetBrains Research
*)(** {i Enum} plugin: converts constructor name to integer.
Constructor arguments are not taken to account.
Synthetized attribute is [int].
Inherited attributes' type (both default and for type parameters) is [unit].
For type declaration [type ('a,'b,...) typ = ...] it will create transformation
function with type
[('a -> int) -> ('b -> int) -> ... -> ('a,'b,...) typ -> int]
See also: {!Compare} plugin.
*)openPpxlibopenGTCommonopenHelpersBaselettrait_name="enum"moduleMake(AstHelpers:GTHELPERS_sig.S)=structlettrait_name=trait_namemoduleP=Plugin.Make(AstHelpers)exceptionFoundofintopenAstHelpersletdefault_index=0classgargstdecls=object(self)inherit[loc,Exp.t,Typ.t,type_arg,Cl.t,Ctf.t,Cf.t,Str.t,Sig.t,Pat.t]Plugin_intf.typ_ginheritP.generatorargstdeclsinheritP.no_inherit_argargstdeclsmethodtrait_name=trait_namemethodinh_of_main~loc_tdecl=Typ.ident~loc"unit"methodsyn_of_main~loc?in_class_tdecl=Typ.ident~loc"int"methodsyn_of_param~loc_=Typ.ident~loc"int"methodinh_of_param~loctdecl_name=self#inh_of_main~loctdecl(* TODO: copy-paste from show. Maybe refactor to separate class? *)methodplugin_class_params~loctyps~typname=List.maptyps~f:Typ.from_caml@[Typ.var~loc@@Naming.make_extra_paramtypname]methodprivatefind_right_one~locconstr_infotdecl=matchtdecl.ptype_kind,constr_infowith|Ptype_open,_->failwith"Open types can't be enumerable"|Ptype_record_,_->Exp.int_const~locdefault_index|Ptype_abstract,Some(`Polys)->(matchtdecl.ptype_manifestwith|Some{ptyp_desc=Ptyp_variant(rows,_,labs)}->(try(* Format.printf "There are %d rows\n%!" (List.length rows); *)List.iterirows~f:(funi->function|{prf_desc=Rtag({txt},_,_)}whenStdlib.(txt=s)->raise(Found(HelpersBase.hash_variants))|_->());failwiths"Plugin passed a constructor `%s` that isn't present"swith|Foundi->Exp.int_const~loci)|_->assertfalse)|_,None|Ptype_abstract,Some(`Normal_)|Ptype_variant_,Some(`Poly_)->failwith"should not happen?"|Ptype_variantcds,Some(`Normals)->(tryList.itericds~f:(funi->function|{pcd_name={txt}}whenString.equaltxts->raise(Foundi)|_->());failwiths"Plugin passed a constructor `%s` that isn't present"swith|Foundi->Exp.int_const~loci)(* Adapted to generate only single method per constructor definition *)methodon_tuple_constr~loc~is_self_rec~mutual_decls~inhetdeclconstr_info_ts=self#find_right_one~locconstr_infotdeclmethod!on_record_constr~loc~is_self_rec~mutual_decls~inhetdeclconstr_infobindingslabs=assert(List.lengthlabs>0);self#find_right_one~loc(Someconstr_info)tdeclmethodon_record_declaration~loc~is_self_rec~mutual_declstdecllabs=[Cf.method_concrete~loc(Naming.meth_name_for_recordtdecl)@@Exp.fun_~loc(Pat.unit~loc)@@Exp.fun_~loc(Pat.any~loc)@@Exp.int_const~loc0]method!make_inh~loc=Pat.unit~loc,Exp.unit~locendletcreate=(newg:>P.plugin_constructor)endletregister()=Expander.register_plugintrait_name(moduleMake:Plugin_intf.MAKE)let()=register()