123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062(*
* Generic Transformers PPX syntax extension.
* Copyright (C) 2016-2019
* Dmitrii Kosarev aka Kakadu
* St.Petersburg State University, JetBrains Research
*)openBaseopenPpxlibopenPpxlib.Ast_builder.DefaultopenHelpersBaseopenPrintfopenNaminglet(@@)=Caml.(@@)typeconfig_plugin=Skip|UseofPlugin_intf.plugin_argsletregistered_plugins:(string*(modulePlugin_intf.MAKE))listref=ref[]letget_registered_plugins()=List.map~f:fst!registered_pluginsletregister_pluginnamem=letp=(name,m)inregistered_plugins:=p::!registered_plugins;()moduleMake(AstHelpers:GTHELPERS_sig.S)=structopenAstHelpersletprepare_patt_match~loc?else_casewhatconstructorsmake_rhs=leton_algcdts=letkcs=Exp.match_~locwhatcsink@@List.mapcdts~f:(funcd->matchcd.pcd_argswith|Pcstr_recordls->letnames=List.mapls~f:(fun_->gen_symbol())incase~lhs:(Pat.constr_record~loccd.pcd_name.txt@@List.map2_exnlsnames~f:(funls->(l.pld_name.txt,Pat.var~locs)))~rhs:(make_rhscdnames)|Pcstr_tupleargs->letnames=List.mapargs~f:(fun_->gen_symbol())incase~lhs:(Pat.constr~loccd.pcd_name.txt@@List.map~f:(Pat.var~loc)names)~rhs:(make_rhscdnames))@(matchelse_casewith|None->[]|Somef->letname=gen_symbol~prefix:"else"()in[case~lhs:(Pat.sprintf~loc"%s"name)~rhs:(fname)])inleton_polycs=assertfalseinmatchconstructorswith|`Algebraiccdts->on_algcdts|`PolyVarcs->on_polycsletprepare_patt_match_poly~locwhatrowslabels~onrow~onlabel~oninherit=letkcs=Exp.match_~locwhatcsinletrs=List.maprows~f:(function|Rtag(lab,_,args)->letargs=matchargswith|[t]->unfold_tuplet|[]->[]|_->failwith"we don't support conjunction types"inletnames=List.mapargs~f:(fun_->gen_symbol~prefix:"_"())inletlhs=Pat.variant~loclab.txt@@List.map~f:(funs->Pat.var~locs)namesincase~lhs~rhs:(onrowlab@@List.zip_exnnamesargs)|Rinherittyp->matchtyp.ptyp_descwith|Ptyp_constr({txt;_},ts)->letnewname="subj"inletlhs=Pat.alias~loc(Pat.type_~loctxt)newnameincase~lhs~rhs:(oninherittstxtnewname)|_->failwith"this inherit field isn't supported")inletls=matchlabelswith|None->[]|Somels->List.mapls~f:(funlab->letnewname="subj"inletlhs=Pat.alias~loc(Pat.type_~loc(Lidentlab))newnameincase~lhs~rhs:(onlabellabnewname))ink@@rs@lsletparams_of_interface_class~locparams=(* actual params depend on sort of type.
2 + 3*params_count + 1 (for polyvar subtyping)
*)(List.concat@@map_type_param_namesparams~f:(funs->[named_type_arg~loc("i"^s);named_type_arg~locs;named_type_arg~loc("s"^s)]))@[named_type_arg~loc"inh";named_type_arg~locNaming.extra_param_name;named_type_arg~loc"syn"]letmake_interface_class_sig~loctdecl=letname=tdecl.ptype_nameinletkfields=[Sig.class_~loc~virt:true~name:(class_name_for_typname.txt)~params:(params_of_interface_class~loctdecl.ptype_params)fields]inleton_constructorpcd_argspcd_name=letmethname=Naming.meth_name_for_constructorpcd_name.txtinlettyps=matchpcd_argswith|Pcstr_recordls->List.mapls~f:(funx->x.pld_type)|Pcstr_tuplets->tsinCtf.method_~locmethname~virt:true@@Typ.chain_arrow~loc@@[Typ.var~loc"inh";Typ.var~loc"extra"]@(List.maptyps~f:Typ.from_caml)@[Typ.var~loc"syn"]invisit_typedecl~loctdecl~onrecord:(fun_labels->(* almost the same as plugin#get_class_sig*)k[Ctf.method_~loc(Naming.meth_name_for_recordtdecl)~virt:true@@Typ.chain_arrow~loc@@letopenTypin[var~loc"inh";use_tdecltdecl;var~loc"syn"]])~onabstract:(fun()->(* For purely abstract type we can only generate interface
(we don't know methods) *)[])~onvariant:(funcds->k@@List.mapcds~f:(funcd->on_constructorcd.pcd_argscd.pcd_name))~onmanifest:(funtyp->letwrapnameparams=letinh_params=List.concat_mapparams~f:(funtyp->[map_core_typetyp~onvar:(funn->Some(ptyp_var~loc:typ.ptyp_loc("i"^n)));typ;map_core_typetyp~onvar:(funn->Some(ptyp_var~loc:typ.ptyp_loc("s"^n)))])|>List.map~f:Typ.from_camlinletinh_params=inh_params@[Typ.var~loc"inh";Typ.var~locNaming.extra_param_name;Typ.var~loc"syn"]in[Ctf.inherit_~loc@@Cty.constr~loc(map_longident~f:class_name_for_typname)inh_params]inletrechelpertyp=matchtyp.ptyp_descwith|Ptyp_constr({txt;loc},params)->(* a type alias on toplevel *)k@@wraptxtparams|Ptyp_varname->letnew_lident=Ldot(Lident"GT","free")inletopenPpxlib.Ast_builder.Defaultinletloc=typ.ptyp_locinhelper@@ptyp_constr~loc(Located.mk~locnew_lident)[ptyp_var~locname]|Ptyp_tuplets->(* let's say we have predefined aliases for now *)letnew_lident=Ldot(Lident"GT",sprintf"tuple%d"@@List.lengthts)inletopenPpxlib.Ast_builder.Defaultinletloc=typ.ptyp_locinhelper@@ptyp_constr~loc(Located.mk~locnew_lident)ts|Ptyp_alias(typ,new_name)->letloc=typ.ptyp_locinmap_core_typetyp~onvar:(funas_->letparams=List.map~f:fsttdecl.ptype_paramsinletopenPpxlib.Ast_builder.DefaultinifString.equalas_new_namethenSome(ptyp_constr~loc(Located.lident~locname.txt)params)elseSome(ptyp_var~locas_))|>helper|Ptyp_variant(rows,_,labels)->(* rows go to virtual methods. label goes to inherit fields *)letmeths=List.concat_maprows~f:(funrf->matchrf.prf_descwith|Rtag(lab,_,args)->letargs=matchargswith|[]->[]|[{ptyp_desc=Ptyp_tuplets;_}]->ts|[t]->[t]|_->failwith"conjective not supported"inletmethname=Naming.meth_of_constrlab.txtinletts=letopenTypin[var~loc"inh";var~loc"extra"]@(List.map~f:from_camlargs)@[var~loc"syn"]|>chain_arrow~locin[Ctf.method_~loc~virt:truemethnamets]|Rinherittyp->matchtyp.ptyp_descwith|Ptyp_constr({txt;loc},params)->wraptxtparams|_->assertfalse)inkmeths|Ptyp_extension_->not_implemented"extensions in types not implemented: %s"(string_of_core_typetyp)|_->failwith" not implemented"inlettopleveltyp=matchtyp.ptyp_descwith|Ptyp_tuple_|Ptyp_var_->k@@[on_constructor(Pcstr_tuple[])@@Located.mk~loc:typ.ptyp_loc@@String.uppercasetdecl.ptype_name.txt]|_->helpertypintopleveltyp)letinherit_iface_class~locnameparams=letinh_params=List.concat_mapparams~f:(funtyp->[map_core_typetyp~onvar:(funn->Some(ptyp_var~loc:typ.ptyp_loc("i"^n)));typ;map_core_typetyp~onvar:(funn->Some(ptyp_var~loc:typ.ptyp_loc("s"^n)))])|>List.map~f:Typ.from_camlinletinh_params=inh_params@[Typ.var~loc"inh";Typ.var~loc"extra";Typ.var~loc"syn"]inCf.inherit_~loc@@Cl.constr~loc(map_longident~f:class_name_for_typname)inh_paramsletmake_interface_class~loctdecl=letparams=List.map~f:fsttdecl.ptype_paramsinletname=tdecl.ptype_nameinletans?(is_poly=false)fields=class_declaration~loc~name:(class_name_for_typname.txt)fields~virt:true~params:(params_of_interface_class~loctdecl.ptype_params)inleton_constructorpcd_argspcd_name=letmethname=Naming.meth_of_constrpcd_name.txtinlettyps=matchpcd_argswith|Pcstr_recordls->List.mapls~f:(funx->x.pld_type)|Pcstr_tuplets->tsinCf.method_virtual~locmethname@@Typ.(List.fold_righttyps~init:(var~loc"syn")~f:(funt->arrow~loc(from_camlt))|>(arrow~loc(var~loc"extra"))|>(arrow~loc(var~loc"inh")))invisit_typedecl~loctdecl~onopen:(fun()->ans[])~onrecord:(fun_->ans[Cf.method_virtual~loc(sprintf"do_%s"tdecl.ptype_name.txt)@@Typ.(arrow~loc(var~loc"inh")@@arrow~loc(use_tdecltdecl)(var~loc"syn"))])~onvariant:(funcds->ans@@List.mapcds~f:(funcd->on_constructorcd.pcd_argscd.pcd_name))~onmanifest:(funtyp->letwrap?(is_poly=false)nameparams=[inherit_iface_class~locnameparams]inletrechelpertyp=matchtypwith|_->matchtyp.ptyp_descwith|Ptyp_varname->letnew_lident=Ldot(Lident"GT","free")inletopenPpxlib.Ast_builder.Defaultinletloc=typ.ptyp_locinhelper@@ptyp_constr~loc(Located.mk~locnew_lident)[ptyp_var~locname]|Ptyp_constr({txt;loc},params)->(* a type alias on toplevel *)ans@@wraptxtparams|Ptyp_tuplets->(* let's say we have predefined aliases for now *)letnew_lident=Ldot(Lident"GT",sprintf"tuple%d"@@List.lengthts)inletopenPpxlib.Ast_builder.Defaultinletloc=typ.ptyp_locinhelper@@ptyp_constr~loc(Located.mk~locnew_lident)ts|Ptyp_alias(typ,new_name)->letloc=typ.ptyp_locinmap_core_typetyp~onvar:(funas_->letopenPpxlib.Ast_builder.DefaultinifString.equalas_new_namethenSome(ptyp_constr~loc(Located.lident~locname.txt)params)elseSome(ptyp_var~locas_))|>helper|Ptyp_variant(rows,_,labels)->(* rows go to virtual methods. label goes to inherit fields *)ans~is_poly:true@@List.concat_maprows~f:(funrf->matchrf.prf_descwith|Rtag(lab,_,[])->letmethname=sprintf"c_%s"lab.txtin[Cf.method_virtual~locmethname@@Typ.(var~loc"syn"|>(arrow~loc@@var~loc"extra")|>arrow~loc(var~loc"inh"))]|Rtag(lab,_,[typ])->(* print_endline "HERE"; *)letargs=matchtyp.ptyp_descwith|Ptyp_tuplets->ts|_->[typ]inletmethname=sprintf"c_%s"lab.txtin[Cf.method_virtual~locmethname@@letopenTypin(List.fold_rightargs~init:(var~loc"syn")~f:(funt->arrow~loc(from_camlt))|>(arrow~loc@@var~loc"extra")|>(arrow~loc(var~loc"inh")))]|Rtag(_,_,_)->failwith"Can't deal with conjunctive types"|Rinherittyp->matchtyp.ptyp_descwith|Ptyp_constr({txt;loc},params)->wrap~is_poly:truetxtparams|_->assertfalse)|Ptyp_extension_->not_implemented"extensions in types `%s`"(string_of_core_typetyp)|_->failwith"not implemented "inlettopleveltyp=matchtyp.ptyp_descwith|Ptyp_tuple_|Ptyp_var_->ans@@[on_constructor(Pcstr_tuple[])@@Located.mk~loc:typ.ptyp_loc@@String.uppercasetdecl.ptype_name.txt]|_->helpertypintopleveltyp)letwildcard_tdecltd=letloc=loc_from_camltd.ptype_locinTyp.constr~loc(Lidenttd.ptype_name.txt)@@List.maptd.ptype_params~f:(fun_->Typ.any~loc)letmake_gcata_typ~loctdecl=leton_alias_or_abstract()=letargs=map_type_param_namestdecl.ptype_params~f:(funname->[Typ.any~loc;Typ.var~locname;Typ.var~loc@@"s"^name])|>List.concatinletargs=args@[Typ.var~loc"inh";Typ.use_tdecltdecl;Typ.var~loc"syn"]inTyp.class_~loc(Lident(class_name_for_typtdecl.ptype_name.txt))argsinlettr_t=visit_typedecl~loctdecl~onabstract:(fun()->on_alias_or_abstract())~onrecord:(fun_->Typ.object_~locOpen@@[sprintf"do_%s"tdecl.ptype_name.txt,Typ.(chain_arrow~loc[var~loc"inh";use_tdecltdecl;var~loc"syn"])])~onvariant:(funcds->Typ.object_~locOpen@@List.mapcds~f:(funcd->lettyps=matchcd.pcd_argswith|Pcstr_recordls->List.mapls~f:(funx->x.pld_type)|Pcstr_tuplets->tsinletnew_ts=letopenTypin[var~loc"inh";use_tdecltdecl]@(List.maptyps~f:Typ.from_caml)@[Typ.var~loc"syn"]in(Naming.meth_of_constrcd.pcd_name.txt,Typ.chain_arrow~locnew_ts)))~onmanifest:(funt->letrechelpertyp=matchtyp.ptyp_descwith|Ptyp_constr(_,_)->on_alias_or_abstract()|Ptyp_varname->letnew_lident=Ldot(Lident"GT","free")inletopenPpxlib.Ast_builder.Defaultinletloc=typ.ptyp_locinhelper@@ptyp_constr~loc(Located.mk~locnew_lident)[ptyp_var~locname]|Ptyp_variant(rows,_flg,_)->letparams=map_type_param_namestdecl.ptype_params~f:(funs->[Typ.any~loc;Typ.var~locs;Typ.var~loc@@"s"^s])inTyp.class_~loc(Lident(class_name_for_typtdecl.ptype_name.txt))(List.concatparams@Typ.[var~loc"inh";openize_poly~loc@@Typ.constr~loc(Lidenttdecl.ptype_name.txt)@@map_type_param_namestdecl.ptype_params~f:(Typ.var~loc);var~loc"syn"])|Ptyp_tuplets->helper@@constr_of_tuple~loc:t.ptyp_locts|_->failwith"Unsupported case during generate of the type of gcata"inhelpert)inletsubj_t=Typ.use_tdecltdeclinTyp.(chain_arrow~loc[tr_t;var~loc"inh";subj_t;var~loc"syn"])letmake_gcata_sig~loc?(shortname=false)tdecl=letwrap()=lettype_=make_gcata_typ~loctdeclinletname=ifshortnamethen"gcata"elsePrintf.sprintf"gcata_%s"tdecl.ptype_name.txtin[Sig.value~loc~nametype_]invisit_typedecl~loctdecl~onrecord:(fun_->wrap())~onvariant:(fun_->wrap())~onmanifest:(fun_->wrap())~onabstract:(fun()->[])letmake_gcata_str~loctdecl=letgcata_pat=Pat.var~loc(sprintf"gcata_%s"tdecl.ptype_name.txt)inletansk=lettr=letwrapt=ifis_polyvariant_tdecltdeclthenopenize_poly~loctelsetin(* let tr = Pat.var ~loc "tr" in
* if not (is_polyvariant_tdecl tdecl)
* then tr
* else *)Pat.constraint_~loc(Pat.var~loc"tr")@@Typ.class_~loc(Lident(Naming.class_name_for_typtdecl.ptype_name.txt))(letparam_names=List.mapitdecl.ptype_params~f:(funi_->gen_symbol~prefix:(sprintf"typ%d"i)())inlettyp_self=Typ.constr~loc(Lidenttdecl.ptype_name.txt)@@List.mapparam_names~f:(Typ.var~loc)inList.concat_mapparam_names~f:(funname->Typ.[any~loc;var~locname;any~loc])@[Typ.any~loc;wrap@@typ_self;Typ.any~loc])inStr.single_value~locgcata_pat(Exp.fun_list~locPat.[tr;var~loc"inh";var~loc"subj"]k)inletmatch_and_openize~locidenttype_lident=letnew_name="foo"inExp.match_~locident[case~lhs:(Pat.alias~loc(Pat.type_~loctype_lident)new_name)~rhs:(Exp.ident~locnew_name)]inletonvariantcds=ans@@prepare_patt_match~loc(Exp.ident~loc"subj")(`Algebraiccds)(funcdnames->(* TODO: Subj ident has to be passed as an argument *)letsubj="subj"inList.fold_left("inh"::subj::names)~init:(Exp.send~loc(Exp.ident~loc"tr")(Naming.meth_of_constrcd.pcd_name.txt))~f:(funaccarg->Exp.app~locacc(Exp.ident~locarg)))invisit_typedecl~loctdecl~onopen:(fun()->ans@@Exp.failwith_~loc"Extensible types not yet supported")~onrecord:(fun_labels->letmethname=sprintf"do_%s"tdecl.ptype_name.txtinans@@Exp.(app_list~loc(send~loc(ident~loc"tr")methname)[ident~loc"inh";ident~loc"subj"]))~onmanifest:(funtyp->letrechelpert=matcht.ptyp_descwith|Ptyp_alias(t,_)->helpert|Ptyp_varname->letnew_lident=Ldot(Lident"GT","free")inletopenPpxlib.Ast_builder.Defaultinletloc=typ.ptyp_locinhelper@@ptyp_constr~loc(Located.mk~locnew_lident)[ptyp_var~locname]|Ptyp_constr({txt},_)->Str.single_value~locgcata_pat(Exp.of_longident~loc@@map_longidenttxt~f:Naming.gcata_name_for_typ)|Ptyp_tuplets->(* let's say we have predefined aliases for now *)helper@@constr_of_tuple~loc:t.ptyp_locts|Ptyp_variant(rows,_,maybe_labels)->letsubj_s="subj"inans@@prepare_patt_match_poly~loc(Exp.ident~locsubj_s)(List.maprows~f:(fun{prf_desc}->prf_desc))maybe_labels~onrow:(funcnamenames->List.fold_left~init:(Exp.send~loc(Exp.ident~loc"tr")("c_"^cname.txt))~f:(Exp.app~loc)((Exp.ident~loc"inh")::(match_and_openize~loc(Exp.ident~locsubj_s)(Lidenttdecl.ptype_name.txt))::(List.map~f:(fun(s,_)->Exp.ident~locs)names)))~onlabel:(funlabelpatname->failwith"not implemented")~oninherit:(funparamscidentpatname->Exp.app_list~loc(Exp.of_longident~loc@@map_longidentcident~f:(gcata_name_for_typ))(List.map["tr";"inh";patname]~f:(Exp.sprintf~loc"%s")))|Ptyp_object(_,_)->failwith"not implemented: object types"|Ptyp_class(_,_)->failwith"not implemented: class types"|Ptyp_package_->failwith"not implemented: package types"|Ptyp_extension_->failwith"not implemented: extension types"|Ptyp_arrow_->failwith"not implemented: arrow types"|Ptyp_any->failwith"not implemented: wildcard types (but it should be easy to rewrite)"|Ptyp_poly(_,_)->failwith"not implemented: existential types"inlettoplevelt=matcht.ptyp_descwith|Ptyp_var_|Ptyp_tuple_->ans@@Exp.app_list~loc(Exp.send~loc(Exp.ident~loc"tr")(Naming.meth_of_constr(String.uppercasetdecl.ptype_name.txt)))(List.map~f:(Exp.ident~loc)["inh";"subj"])|_->helpertintopleveltyp)~onvariant(* create opened renaming for polymorphic variant *)(* seems that we don't need it no more *)letmake_heading_gen~locwraptdecl=[]letcollect_plugins_str~loctdeclall_tdeclsplugins:Str.tlist=letwrapptdecl=p#eta_and_exp~center:(Exp.sprintf~loc"%s_%s"p#trait_nametdecl.ptype_name.txt)tdeclinletplugin_fields=List.mapplugins~f:(funp->Cf.method_concrete~locp#trait_name@@ifp#need_inh_attrthenExp.sprintf~loc"%s"@@Naming.trf_functionp#trait_nametdecl.ptype_name.txtelsewrapptdecl)inlettname=tdecl.ptype_name.txtin(* The pack itself *)letgcata_ident=Exp.sprintf~loc"gcata_%s"tnamein(Str.single_value~loc(Pat.sprintf~loc"%s"tname)@@Exp.record~loc[Ldot(lident"GT","gcata"),gcata_ident;Ldot(lident"GT","fix"),ifList.lengthall_tdecls>1thenExp.sprintf~loc"%s"@@Naming.make_fix_nameall_tdeclselseExp.fun_~loc(Pat.var~loc"eta")@@Exp.app_list~loc(Exp.of_longident~loc(Ldot(Lident"GT","transform_gc")))[gcata_ident;Exp.sprintf~loc"eta"];Ldot(lident"GT","plugins"),Exp.object_~loc@@class_structure~self:(Pat.any~loc)~fields:plugin_fields])::(List.filter_mapplugins~f:(funp->(* also we generate transformation function with unit preapplied
Because we seems to need them in case of abstract type in the interface
*)ifp#need_inh_attrthenNoneelseletfname=Naming.trf_functionp#trait_nametdecl.ptype_name.txtinOption.some@@Str.single_value~loc(Pat.sprintf~loc"%s"fname)(wrapptdecl)))letrename_paramstdecl=letloc=tdecl.ptype_locinvisit_typedecl~loctdecl~onmanifest:(funtyp->letnames=(map_type_param_namestdecl.ptype_params~f:id)inlet(r_names,new_manifest)=List.fold_left~init:([],typ)names~f:(fun(ns,acc)name->ifString.equalnameNaming.self_typ_param_namethenletn_new=Naming.self_typ_param_name^"__new"inlett2=map_core_typeacc~onvar:(funs->(* Caml.Printf.printf "cmp '%s' and '%s' = %b\n%!" s name (String.equal s name ); *)ifString.equalsnamethenSome(ptyp_var~locn_new)elseNone)in(n_new::ns,t2)else(name::ns,acc))in{tdeclwithptype_params=List.map2_exntdecl.ptype_params(List.revr_names)~f:(fun(_,v)s->(ptyp_var~locs,v));ptype_manifest=Somenew_manifest})~onvariant:(fun_->tdecl)~onabstract:(fun_->tdecl)~onrecord:(fun_->tdecl)(* TODO: Implement general case about renaming of paramters *)moduleG=Graph.Persistent.Digraph.Concrete(String)moduleT=Graph.Topological.Make(G)moduleSM=Caml.Map.Make(String)lettopsort_tdeclstdecls=(* TODO: we need topological sorting because in case
* type y = int x
* type 'a x = ....
* we need to declare class for x before class for y
* due to inheritance
*)letname_map=List.fold_left~init:SM.emptytdecls~f:(funacctdecl->matchtdeclwith|{ptype_name}->SM.addptype_name.txttdeclacc)inletg=List.fold_left~init:G.emptytdecls~f:(funacctdecl->letacc=G.add_vertexacctdecl.ptype_name.txtinletinfo=visit_typedecl~loc:tdecl.ptype_loctdecl~onrecord:(fun_->None)~onvariant:(fun_->None)~onabstract:(fun_->None)~onopen:(fun_->None)~onmanifest:(funtyp->matchtyp.ptyp_descwith|Ptyp_constr({txt=Lidents},_)->Somes|_->None)inmatchinfowith|None->acc|Somes->beginmatchSM.findsname_mapwith|exceptionCaml.Not_found->acc|_->G.add_edgeaccstdecl.ptype_name.txtend)inlettdecls_new=T.fold(funsacc->(SM.findsname_map)::acc)g[]|>List.revinassert(List.lengthtdecls=List.lengthtdecls_new);tdecls_new(* for structures *)letdo_typ~locsispluginsis_rectdecl=let(_:bool)=is_recinlettdecl=rename_paramstdeclinletintf_class=Str.of_class_declarations~loc[make_interface_class~loctdecl]inletgcata=make_gcata_str~loctdeclinletplugins=List.mapplugins~f:(funp->p[tdecl])inList.concat[sis;[intf_class;gcata](* ; indexes_str ~loc plugins [tdecl] *);List.concat_mapplugins~f:(fung->g#do_single~loc~is_rectdecl);collect_plugins_str~loctdecl[tdecl]plugins]letfix_typ~loctdecls=letidx=ref(0)inletnext()=Int.incridx;!idxinletarr3abc=Typ.arrow~loca(Typ.arrow~locbc)inlettup~locxs=matchxswith|[]->failwith"bad arguemnt"|[x]->x|xs->Typ.tuple~locxsinletys=List.maptdecls~f:(funtdecl->letps=List.maptdecl.ptype_params~f:(fun_->sprintf"a%d"(next()))inletsubj_t=Typ.constr~loc(Lidenttdecl.ptype_name.txt)@@(List.mapps~f:(Typ.var~loc))inletinhs=List.mapps~f:(sprintf"%s_i")inletsyns=List.mapps~f:(sprintf"%s_s")inletmain_inh=Typ.var~loc@@sprintf"inh%d"(next())inletmain_syn=Typ.var~loc@@sprintf"syn%d"(next())inletcls=letargs=List.map3_exninhspssyns~f:(funips->[i;p;s])|>List.concat|>List.map~f:(Typ.var~loc)|>(funxs->xs@[main_inh;(ifis_polyvariant_tdecltdeclthenopenize_poly~locelseid)subj_t;main_syn])inTyp.class_~loc(Lident(Naming.class_name_for_typtdecl.ptype_name.txt))argsinlettrf=arr3main_inhsubj_tmain_synin(trf,cls))inletmutuals=tup~loc@@List.mapys~f:fstinList.fold_right~init:(tup~loc@@List.mapys~f:fst)ys~f:(fun(_trf,cls)acc->Typ.arrow~loc(Typ.arrow~locmutualscls)acc)letfix_sig~loctdecls=Sig.value~loc~name:(sprintf"%s"@@Naming.make_fix_nametdecls)(fix_typ~loctdecls)letfix_str~loctdecls=value_binding~loc~pat:(Pat.sprintf~loc"%s"@@Naming.make_fix_nametdecls)~expr:Exp.(fun_list~loc(List.maptdecls~f:(fun{ptype_name}->Pat.sprintf~loc"%s0"ptype_name.txt))@@Exp.let_~loc~rec_:true(List.maptdecls~f:(funtdecl->letek=Exp.fun_list~loc(map_type_param_namestdecl.ptype_params~f:(funtxt->Pat.sprintf~loc"f%s"txt))kinletinhsubjk=Exp.fun_list~loc[Pat.var~loc"inh";Pat.var~loc"subj"]kinletgc=Exp.app_list~loc(Exp.sprintf~loc"gcata_%s"tdecl.ptype_name.txt)[Exp.app_list~loc(Exp.sprintf~loc"%s0"tdecl.ptype_name.txt)((Exp.tuple~loc@@List.maptdecls~f:(fun{ptype_name={txt}}->Exp.sprintf~loc"trait%s"txt))::(map_type_param_namestdecl.ptype_params~f:(funtxt->Exp.sprintf~loc"f%s"txt))(* @
* [Exp.app_list ~loc
* (Exp.sprintf ~loc "trait%s" tdecl.ptype_name.txt)
* (map_type_param_names tdecl.ptype_params
* ~f:(fun txt -> Exp.sprintf ~loc "f%s" txt))
* ] *));Exp.ident~loc"inh";Exp.ident~loc"subj"]in(Pat.sprintf~loc"trait%s"tdecl.ptype_name.txt,e@@inhsubj@@gc)))@@Exp.tuple~loc(List.maptdecls~f:(fun{ptype_name}->Exp.sprintf~loc"trait%s"ptype_name.txt)))|>Str.of_vb~loc~rec_flag:Nonrecursive|>List.returnletcollect_plugins_sig~loctdeclsplugins=List.concat_maptdecls~f:(funtdecl->letwrap()=[Sig.value~loc~name:tdecl.ptype_name.txt@@Typ.constr~loc(Ldot(lident"GT","t"))[make_gcata_typ~loctdecl;Typ.object_~locClosed@@List.mapplugins~f:(funp->(p#trait_name,p#make_final_trans_function_typ~loctdecl))(* ; make_gcata_typ ~loc tdecl *);fix_typ~loctdecls]]invisit_typedecl~loctdecl~onabstract:(fun_->[])~onmanifest:(fun_->wrap())~onvariant:(fun_->wrap())~onrecord:(fun_->wrap()))letdo_mutual_types~locsispluginstdecls=lettdecls=topsort_tdeclstdeclsinletclasses,catas=letall=List.maptdecls~f:(funtdecl->(make_interface_class~loctdecl,make_gcata_str~loctdecl))in(List.map~f:fstall,List.map~f:sndall)inletplugins=List.mapplugins~f:(funp->ptdecls)inList.concat[sis;List.mapclasses~f:(func->Str.of_class_declarations~loc[c]);catas;fix_str~loctdecls;List.concat_mapplugins~f:(fung->g#do_mutuals~loc~is_rec:truetdecls);List.concat_maptdecls~f:(funtdecl->collect_plugins_str~loctdecltdeclsplugins)](* for signatures *)letdo_typ_sig~locsispluginsis_rectdecl=letplugins=List.mapplugins~f:(funp->p[tdecl])inletintf_class=make_interface_class_sig~loctdeclinletgcata=make_gcata_sig~loctdeclin(* Pprintast.signature_item Format.std_formatter @@
* psig_type ~loc:tdecl.ptype_loc Nonrecursive [tdecl]; *)List.concat[sis;intf_class;gcata;List.concat_mapplugins~f:(fung->g#do_single_sig~loc~is_rectdecl);collect_plugins_sig~loc[tdecl]plugins]letdo_mutual_types_sig~locsispluginstdecls=(* TODO: it could be a bug with topological sorting here *)sis@List.concat_maptdecls~f:(funtdecl->List.concat[make_interface_class_sig~loctdecl;make_gcata_sig~loctdecl])@[fix_sig~loctdecls]@List.concat_mapplugins~f:(funp->(ptdecls)#do_mutuals_sigs~loc~is_rec:true)@(* (List.concat_map tdecls ~f:(fun tdecl ->
* List.concat_map plugins ~f:(fun p ->
* collect_plugins_sig ~loc tdecl (p tdecls))
* )
* ) @ *)(collect_plugins_sig~loctdecls(List.mapplugins~f:(funp->ptdecls)))@[](* TODO: collect plugins for mutual types *)(* List.concat_map ~f:(do_typ_sig ~loc [] plugins true) tdecls *)letwrap_pluginname=function|Skip->id|Useargs->matchList.Assoc.find!registered_pluginsname~equal:String.equalwith|Somem->letmoduleF=(valm:Plugin_intf.MAKE)inletmoduleP=F(AstHelpers)inList.cons@@P.createargs|None->failwithf"Plugin '%s' is not registered"name()(* let sig_type_decl ~loc ~path si
* ?(use_show=skip) ?(use_gmap=skip) ?(use_foldl=skip) ?(use_show_type=skip)
* ?(use_compare=skip) ?(use_eq=skip)
* (rec_flag, tdls) =
* let plugins =
* wrap_plugin "show" use_show @@
* wrap_plugin "compare" use_compare @@
* wrap_plugin "gmap" use_gmap @@
* wrap_plugin "foldl" use_foldl @@
* wrap_plugin "show_typed" use_show_type @@
* wrap_plugin "eq" use_eq @@
* []
* in
* match rec_flag, tdls with
* | recursive, [] -> []
* | recursive, [tdecl] -> do_typ_sig si ~loc plugins true tdecl
* | recursive, ts -> do_mutal_types_sig ~loc plugins ts
* | nonrecursive, tdls ->
* list.concat_map ~f:(do_typ_sig ~loc si plugins false) tdls *)letsig_type_decl_many_plugins~locsiplugins_infodeclaration=letplugins=List.fold_leftplugins_info~init:[]~f:(funacc(name,args)->wrap_pluginnameargsacc)inletdeclaration=(fstdeclaration,List.map~f:rename_params(snddeclaration))inmatchdeclarationwith|Recursive,[]->[]|Recursive,[tdecl]->do_typ_sigsi~locpluginstruetdecl|Recursive,ts->(* Stdio.printf "Got %d declarations\n%!" (List.length ts); *)do_mutual_types_sig~locsipluginsts|Nonrecursive,tdls->List.concat_map~f:(do_typ_sig~locsipluginsfalse)tdlsletstr_type_decl_many_plugins~locsiplugins_infodeclaration=letplugins=List.fold_leftplugins_info~init:[]~f:(funacc(name,args)->wrap_pluginnameargsacc)inmatchdeclarationwith|Recursive,[]->[]|Recursive,[tdecl]->do_typ~locsipluginstruetdecl|Recursive,ts->do_mutual_types~locsipluginsts|Nonrecursive,decls->List.concat_map~f:(do_typ~locsipluginsfalse)declsletstr_type_ext_many_plugins~locsiplugins_infoextension=[]end(* part of old implementation where we are trying to collect all values in t
* first-class module. but we decided to roll back because we can't write
* generic function to access it *)letname_fcm_mttdecl=sprintf"mt_%s"tdecl.ptype_name.txt(* let gather_module_str tdecl plugins =
* let loc = tdecl.ptype_loc in
*
* let body = [%stri let gcata =
* [%e exp.sprintf "gcata_%s" tdecl.ptype_name.txt] ] ::[]
* in
* let body = list.fold_left ~init:body plugins
* ~f:(fun acc p ->
* let expr = exp.sprintf ~loc "%s" @@ p#make_trans_function_name tdecl in
* str.single_value ~loc (pat.of_string ~loc p#plugin_name) expr
* :: acc
* )
* in
* let expr = exp.pack_with_constraint ~loc
* (mod.structure ~loc @@ list.rev body)
* (located.lident ~loc (name_fcm_mt tdecl))
* in
* str.single_value ~loc (pat.sprintf "%s" tdecl.ptype_name.txt) expr *)(* let make_fcm_sig ~loc tdecl plugins =
* let fields = list.concat_map plugins ~f:(fun p ->
* let name = p#plugin_name in
* let type_ = p#make_trans_function_typ tdecl in
* [sig.value ~loc ~name type_ ]
* )
* in
* mty.signature ~loc ((make_gcata_sig ~shortname:true ~loc tdecl) :: fields )
*
* let prepare_mt ~loc tdecl plugins =
* let name = located.mk ~loc @@ sprintf "mt_%s" tdecl.ptype_name.txt in
* let type_ = some (make_fcm_sig ~loc tdecl plugins) in
* str.modtype ~loc (module_type_declaration ~loc ~name ~type_) *)