1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570(*
* Generic Transformers PPX syntax extension.
* Copyright (C) 2016-2021
* Dmitrii Kosarev aka Kakadu
* St.Petersburg State University, JetBrains Research
*)(** A few base classes for plugins with virtual methods to be implemented.
See {!Plugin_intf} for complete description of all valuable methods
*)openBaseopenPpxlibopenPrintfopenAsttypesopenHelpersBasemoduleMake(AstHelpers:GTHELPERS_sig.S)=structopenAstHelpersmoduleIntf=Plugin_intf.Make(AstHelpers)typeplugin_constructor=Plugin_intf.plugin_args->bool*Ppxlib.type_declarationlist->(loc,Exp.t,Typ.t,type_arg,Ctf.t,Cf.t,Str.t,Sig.t)Plugin_intf.typ_gletprepare_patt_match_poly~locwhatrowslabels~onrow~onlabel~oninherit=letrs=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:(Pat.var~loc)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")inletfor_labels=matchlabelswith|None->[]|Somels->List.mapls~f:(funlab->letnewname="subj"inletlhs=Pat.alias~loc(Pat.type_~loc(Lidentlab))newnameincase~lhs~rhs:(onlabellabnewname))inExp.match_~locwhat(rs@for_labels)(** Base class for all plugins. Implements {!Plugin_intf.typ_g} interface
Is subclassed by {!with_inherited_attr} and {!no_inherite_arg}. Use them for
convenience.
*)classvirtualgeneratorinitial_args(is_rec,tdecls)=object(self)inheritIntf.gmethodtdecls=tdeclsmethodis_rec=is_recmethodplugin_name=self#trait_name(* parse arguments like { _1=<expr>; ...; _N=<expr>; ...} *)valreinterpreted_args=letcheck_names=tryCaml.Scanf.sscanfs"_%d"Option.somewithCaml.Scanf.Scan_failure_->NoneinList.fold_leftinitial_args~init:[]~f:(funacc(lident,expr)->matchlidentwith|Lidents->Option.value_map(check_names)~default:acc~f:(funn->(n,expr)::acc)|_->acc)methodextra_class_sig_memberstdecl=letloc=loc_from_camltdecl.ptype_locinletwrap=ifis_polyvariant_tdecltdeclthenTyp.openize~locelse(fun?as_x->x)in[Ctf.constraint_~loc(Typ.var~loc@@Naming.make_extra_paramtdecl.ptype_name.txt)(wrap@@Typ.constr~loc(Lidenttdecl.ptype_name.txt)@@map_type_param_namestdecl.ptype_params~f:(funs->Typ.var~locs))]methodextra_class_str_memberstdecl=letloc=loc_from_camltdecl.ptype_locinletwrap=ifis_polyvariant_tdecltdeclthenTyp.openize~locelse(fun?as_x->x)in[Cf.constraint_~loc(Typ.var~loc@@Naming.make_extra_paramtdecl.ptype_name.txt)(wrap@@Typ.constr~loc(Lidenttdecl.ptype_name.txt)@@map_type_param_namestdecl.ptype_params~f:(funs->Typ.var~locs))]methodcur_nametdecl=tdecl.ptype_name.txt(* preparing class of transformation for [tdecl] *)methodmake_class~loc~is_rectdecl=letcur_name=self#cur_nametdeclinletmutual_decls=List.filterself#tdecls~f:(fun{ptype_name={txt}}->String.(<>)txttdecl.ptype_name.txt)inletkfields=letinh_params=prepare_param_triples~loc~inh:(self#inh_of_paramtdecl)~syn:self#syn_of_param~default_syn:(self#syn_of_main~loc~in_class:truetdecl)~default_inh:(self#inh_of_main~loctdecl)~extra:(Typ.var~loc@@sprintf"%s_%s"Naming.extra_param_nametdecl.ptype_name.txt)(map_type_param_namestdecl.ptype_params~f:id)inself#wrap_class_definition~locmutual_declstdecl~inh_paramsfieldsinletis_self_rect=ifnotis_recthen`Nonrecursiveelsematcht.ptyp_descwith|Ptyp_constr({txt=Lidents},params)whenString.equalscur_name&&List.lengthparams=List.lengthtdecl.ptype_params->letwrapoldnext=matchold,nextwith|`Nonregular,_->`Nonregular|_,`Nonregular->`Nonregular|`Regular,`Regular->`Regularin((List.fold2_exnparamstdecl.ptype_params~init:`Regular~f:(funaccinst_par(formal_par,_)->matchinst_par.ptyp_desc,formal_par.ptyp_descwith|(Ptyp_vars1,Ptyp_vars2)whenString.equals1s2->wrapacc`Regular|(_,Ptyp_var_)->`Nonregular|(_,Ptyp_any)->`Nonregular(* TODO: think again about this *)|_when0=compare_core_typeinst_parformal_par->wrapacc`Regular|_->`Nonregular)):>[`Regular|`Nonregular|`Nonrecursive])|_->`Nonrecursiveinself#got_typedecl~loc~is_self_rec~mutual_declstdeclkmethodprepare_fa_args~loctdecl=map_type_param_namestdecl.ptype_params~f:(Pat.sprintf~loc"f%s")methodwrap_class_definition~loc~inh_paramsmutual_declstdeclfields=letcur_name=self#cur_nametdeclin(* inherit class_t and prepare to put other members *)letmutual_decls=self#tdeclsinletis_mutal=(List.lengthmutual_decls>1)inStr.class_single~loc~params:(self#plugin_class_params_tdecltdecl)~name:(self#make_class_name~is_mutaltdecl)~virt:false~wrap:(funbody->(* constructor arguments are *)letnames=(ifis_mutalthen[]else[Pat.var~loc@@self#self_arg_nametdecl.ptype_name.txt])|>(funtl->self#prepare_fa_args~loctdecl@tl)|>(funps->matchmutual_declswith|[]->failwith"Should not happen"|[_]->ps|tdecls->(* we don't need self transformation for *)(Pat.alias~loc(Pat.tuple~loc@@List.mapself#tdecls~f:(fun{ptype_name={txt=name}}->Pat.var~loc@@ifString.equalnametdecl.ptype_name.txtthenself#self_arg_namenameelseNaming.for_self#trait_namename))Naming.mutuals_pack)::ps)inCl.fun_list~locnamesbody)@@[letparent_name=Naming.class_name_for_typcur_nameinCf.inherit_~loc(Cl.constr~loc(Lidentparent_name)inh_params)]@(self#extra_class_str_memberstdecl)@fieldsmethodvirtualmake_typ_of_class_argument:'a.loc:loc->type_declaration->(Typ.t->'a->'a)->string->(('a->'a)->'a->'a)->'a->'a(* next method should be synchronized with prepare_fa_args *)(* method prepare_fa_arg_types ~loc tdecl =
* let names = map_type_param_names tdecl.ptype_params ~f:id in
* List.map names
* ~f:(fun name ->
* self#make_typ_of_class_argument
* ~loc
* tdecl
* name
* (fun x -> x)
* ) *)methodclass_constructor_sig~loc?(a_stub=false)tdecl:Typ.t=lettl=Typ.arrow~loc(self#make_typ_of_self_trf~loc~in_class:truetdecl)@@Typ.constr~loc(Lident(self#make_class_name~is_mutal:a_stubtdecl))(List.map(self#plugin_class_params_tdecltdecl)~f:(Typ.of_type_arg~loc))inletfuncs_for_args=letnames=map_type_param_namestdecl.ptype_params~f:idinList.fold_leftnames~init:id~f:(funaccname->self#make_typ_of_class_argument~loctdecl(Typ.arrow~loc)name(funfarg->acc@@farg))tlinletans=ifnota_stubthenfuncs_for_argselseTyp.arrow~loc(Typ.tuple~loc@@List.mapself#tdecls~f:(funtdecl->self#long_trans_function_typ~loctdecl(* TODO: rename *)))tlinans(* signature for a plugin class *)methodmake_class_sig~loc?(a_stub=false)~is_rectdecl=letkfields=[Sig.class_~loc~params:(self#plugin_class_params_tdecltdecl)~name:(self#make_class_name~is_mutal:a_stubtdecl)~virt:false~wrap:(funsign->letfuncs_for_args=letnames=map_type_param_namestdecl.ptype_params~f:idinList.fold_leftnames~init:id~f:(funaccname->self#make_typ_of_class_argument~loctdecl(Cty.arrow~loc)name(funfarg->acc@@farg))(ifa_stubthensignelseletfor_self=self#make_typ_of_self_trf~loc~in_class:truetdeclinCty.arrow~locfor_selfsign)infuncs_for_args|>(funtl->ifnota_stubthentlelseCty.arrow~loc(Typ.tuple~loc@@List.mapself#tdecls~f:(funtdecl->self#long_trans_function_typ~loctdecl(* TODO: rename *)))tl))((self#extra_class_sig_memberstdecl)@fields)]inleton_constructorcd=letmethname=Naming.meth_name_for_constructorcd.pcd_attributescd.pcd_name.txtinlettyps=matchcd.pcd_argswith|Pcstr_recordls->List.mapls~f:(funx->x.pld_type)|Pcstr_tuplets->tsinletnew_ts=letopenTypin[self#inh_of_main~loctdecl;var~loc@@Printf.sprintf"extra_%s"tdecl.ptype_name.txt]@(List.maptyps~f:Typ.from_caml)@[self#syn_of_main~loc~in_class:truetdecl](* There changing default_syn to 'extra can introduce problems *)inCtf.method_~loc~virt:falsemethname@@Typ.chain_arrow~locnew_tsinvisit_typedecl~loctdecl~onabstract:(fun()->[])~onrecord:(fun_fields->k[Ctf.method_~loc(Naming.meth_name_for_recordtdecl)~virt:false@@Typ.chain_arrow~loc@@letopenTypin[self#inh_of_main~loctdecl;var~loc@@Printf.sprintf"extra_%s"tdecl.ptype_name.txt]@[self#syn_of_main~loctdecl]])~onvariant:(funcds->k@@List.mapcds~f:(funcd->on_constructorcd(* cd.pcd_args
(Ast_builder.Default.Located.map
(Naming.meth_name_for_constructor cd.pcd_attributes) cd.pcd_name) *)))~onmanifest:(funtyp->letrechelpertyp=matchtyp.ptyp_descwith|Ptyp_varname->(* antiphantom types *)letnew_lident=Ldot(Lident"GT","free")inletopenPpxlib.Ast_builder.Defaultinletloc=typ.ptyp_locinhelper@@ptyp_constr~loc(Located.mk~locnew_lident)[ptyp_var~locname]|Ptyp_alias(t,aname)->letloc=t.ptyp_locinmap_core_typet~onvar:(funas_->letopenPpxlib.Ast_builder.DefaultinifString.equalas_anamethenOption.some@@ptyp_constr~loc(Located.lident~loctdecl.ptype_name.txt)@@List.maptdecl.ptype_params~f:(fun(t,_)->t)elseOption.some@@ptyp_var~locas_)|>helper|Ptyp_constr(cid,params)->(* there for type 'a list = ('a,'a list) alist
* we inherit plugin class for base type, for example (gmap):
* inherit ('a,'a2,'a list,'a2 list) gmap_alist
**)k[Ctf.inherit_~loc@@Cty.constr~loc(map_longidentcid.txt~f:(Naming.trait_class_name_for_typ~trait:self#trait_name))(self#final_typ_params_for_alias~loctdeclparams)]|Ptyp_tuplets->(* let's say we have predefined aliases for now *)helper@@constr_of_tuple~loc:typ.ptyp_locts|Ptyp_variant(rows,_,_)->letrr=List.maprows~f:(funrf->matchrf.prf_descwith|Rinherittyp->with_constr_typtyp~ok:(funcidparams->Ctf.inherit_~loc@@Cty.constr~loc(map_longidentcid.txt~f:(Naming.trait_class_name_for_typ~trait:self#plugin_name))(self#final_typ_params_for_alias~loctdeclparams))~fail:(fun()->assertfalse)|Rtag(lab,_,typs)->beginCtf.method_~loc(sprintf"c_%s"lab.txt)~virt:false@@matchtypswith|[]->Typ.(chain_arrow~loc[self#inh_of_main~loctdecl;var~loc@@Printf.sprintf"extra_%s"tdecl.ptype_name.txt;self#syn_of_main~loc~in_class:truetdecl])|[t]->Typ.(chain_arrow~loc@@[self#inh_of_main~loctdecl;var~loc@@Printf.sprintf"extra_%s"tdecl.ptype_name.txt]@(List.map~f:Typ.from_caml@@unfold_tuplet)@[self#syn_of_main~loc~in_class:truetdecl])|typs->Typ.(chain_arrow~loc@@[self#inh_of_main~loctdecl;var~loc@@Printf.sprintf"extra_%s"tdecl.ptype_name.txt]@(List.map~f:Typ.from_camltyps)@[self#syn_of_main~loc~in_class:truetdecl])end)ink@@rr|_->assertfalseinlettopleveltyp=matchtyp.ptyp_descwith|Ptyp_tuple_->letnew_ts=letopenTypin[self#inh_of_main~loctdecl;var~loc@@Printf.sprintf"extra_%s"tdecl.ptype_name.txt]@[self#syn_of_main~loc~in_class:truetdecl]ink@@[Ctf.method_~loc~virt:false(Naming.meth_name_for_constructor[](String.uppercasetdecl.ptype_name.txt))(Typ.chain_arrow~locnew_ts)]|Ptyp_var_->letopenPpxlib.Ast_builder.Defaultink@@[on_constructor@@Ppxlib.Ast_builder.Default.constructor_declaration~loc:typ.ptyp_loc~name:(Located.mapString.uppercasetdecl.ptype_name)~args:(Pcstr_tuple[])~res:None]|_->helpertypintopleveltyp)methodmake_inherit_args_for_alias~loc~is_self_rectdecldo_typcidcparams=letargs=List.mapicparams~f:(funit->(* Stdio.printf "checking for arg with index (%d+1)\n%!" i; *)matchList.Assoc.findreinterpreted_args~equal:Int.equal(i+1)with|Somee->Exp.from_camle|None->do_typ~loct)in(* for typ aliases we can cheat because first argument of constructor of type
on rhs is self transformer function *)args(* When we got declaration of type alias via type application *)methodgot_constr~loc~is_self_rec?(fix_self_app=id)tdeclmutual_declsdo_typcidcparamsk=(* It seems that we can't filter mutal decls because we need to preserve an order *)letmutal_names=List.mapmutual_decls~f:(funt->t.ptype_name.txt)inletansargs:Cf.tlist=[lettyp_params=self#final_typ_params_for_alias~loctdeclcparamsinletargs=(matchcid.txtwith|LidentswhenList.memmutal_namess~equal:String.equal->(* Only Lident because we ignore types with same name but from another module *)[Exp.sprintf~loc"%s"Naming.mutuals_pack]|_->[](* [Exp.of_longident ~loc @@
* map_longident ~f:(fun for_ -> self#fix_func_name ~for_ ()) cid.txt] *))@argsinmatchcid.txtwith|LidentswhenList.memmutal_namess~equal:String.equal->Cf.inherit_~loc@@Cl.apply~loc(Cl.constr~loc(lident@@Naming.make_stub_class_name~plugin:self#plugin_names)typ_params)[Exp.ident~locNaming.mutuals_pack]|_->Cf.inherit_~loc@@Cl.apply~loc(Cl.constr~loc(map_longidentcid.txt~f:(funs->Naming.trait_class_name_for_typ~trait:self#plugin_names))typ_params)args]inletclass_args=(self#make_inherit_args_for_alias~loc~is_self_rectdecldo_typcidcparams)@[fix_self_app@@Exp.ident~loc(self#self_arg_nametdecl.ptype_name.txt)]ink@@ansclass_argsmethodmake_inh~loc=letinhname=gen_symbol~prefix:"inh_"()in(Pat.var~locinhname,Exp.ident~locinhname)methodgot_polyvar~loc~is_self_rec~mutual_declstdecldo_typrowsk=List.concat_maprows~f:(function|Rinherittyp->with_constr_typtyp~fail:(fun()->failwith"type is not a constructor")~ok:(funcidparams->(* Hypothesis: it's almost a type alias *)self#got_constr~loc~is_self_rectdeclmutual_declsdo_typcidparamsk~fix_self_app:(funeself->self#abstract_trf~loc(funeinhesubj->matchtyp.ptyp_descwith|Ptyp_constr({txt},_)->(* TODO: refactoring. we inented special function for this *)Exp.match_~locesubj[case~lhs:(Pat.alias~loc(Pat.type_~loctxt)"subj")~rhs:(self#app_transformation_expr~loceselfeinh(Exp.ident~loc"subj"))]|_->failwith"should not happen")))(* TODO: Do something with copy paste. *)(* tag by default have 1 argument which is a tuple instead of many arguments *)|Rtag(constr_name,_,[])->k[let(inhp,inhe)=self#make_inh~locinCf.method_concrete~loc(Naming.meth_name_for_constructor[]constr_name.txt)@@Exp.fun_~locinhp@@Exp.fun_~loc(Pat.any~loc)@@self#on_tuple_constr~loc~is_self_rec~mutual_decls~inhetdecl(Option.some@@`Polyconstr_name.txt)[]]|Rtag(constr_name,_,[arg])->k[let(inhp,inhe)=self#make_inh~locinletbindings=List.map(unfold_tuplearg)~f:(funts->gen_symbol(),ts)inCf.method_concrete~loc(Naming.meth_name_for_constructor[]constr_name.txt)@@Exp.fun_~locinhp@@Exp.fun_~loc(Pat.any~loc)@@Exp.fun_list~loc(List.mapbindings~f:(fun(s,_)->Pat.var~locs))@@self#on_tuple_constr~loc~is_self_rec~mutual_decls~inhetdecl(Option.some@@`Polyconstr_name.txt)bindings]|Rtag(constr_name,_,args)->(* Hypothesis: it's almost the same as constructor with a tuple of types *)failwith"conjunction types are not supported but")methodgot_typedecl~loc~is_self_rec~mutual_declstdecl(k:Cf.tlist->_)=k@@visit_typedecl~loctdecl~onmanifest:(funtyp->letrechelpertyp=matchtyp.ptyp_descwith|Ptyp_varname->(* antiphantom types *)letnew_lident=Ldot(Lident"GT","free")inletopenPpxlib.Ast_builder.Defaultinletloc=typ.ptyp_locinhelper@@ptyp_constr~loc(Located.mk~locnew_lident)[ptyp_var~locname]|Ptyp_alias(t,aname)->letopenPpxlib.Ast_builder.Defaultinletloc=tdecl.ptype_locinmap_core_typet~onvar:(funas_->ifString.equalas_anamethenOption.some@@ptyp_constr~loc:t.ptyp_loc(Located.lident~loctdecl.ptype_name.txt)(List.maptdecl.ptype_params~f:fst)elseOption.some@@ptyp_var~locas_)|>helper|Ptyp_constr(cid,params)->self#got_constr~loc~is_self_rectdeclmutual_decls(self#do_typ_gen~mutual_decls~is_self_rectdecl)cidparams(funx->x)|Ptyp_tuplets->(* let's say we have predefined aliases for now *)helper@@constr_of_tuple~loc:typ.ptyp_locts|Ptyp_variant(rows,_,_)->self#got_polyvar~loctdecl(self#do_typ_gen~mutual_decls~is_self_rectdecl)~is_self_rec~mutual_decls(List.maprows~f:(fun{prf_desc}->prf_desc))(funx->x)|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"inlettopleveltyp=matchtyp.ptyp_descwith|Ptyp_varname->(* antiphantom types *)[Cf.method_concrete~loc(Naming.meth_name_for_constructor[](String.uppercasetdecl.ptype_name.txt))@@(self#do_typ_gen~loc~mutual_decls~is_self_rectdecltyp)]|Ptyp_tuplets->beginletloc=loc_from_camltdecl.ptype_locinletinhp,inhe=self#make_inh~locinletbindings=List.mapts~f:(funts->gen_symbol(),ts)inletbind_pats=List.mapbindings~f:(fun(s,_)->Pat.var~locs)in(* We don't need bind_pats, we cat patternmatch original value which is wildcarded for now *)[Cf.method_concrete~loc(Naming.meth_name_for_constructortyp.ptyp_attributes(String.uppercasetdecl.ptype_name.txt))@@Exp.fun_~locinhp@@Exp.fun_~loc(Pat.tuple~loc@@bind_pats)@@self#on_tuple_constr~loc~mutual_decls~is_self_rec~inhetdeclNonebindings]end|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"|_->helpertypintopleveltyp)~onvariant:(funcds->self#on_variant~loc~mutual_decls~is_self_rectdeclcdsid)~onrecord:(self#on_record_declaration~loc~is_self_rec~mutual_declstdecl)~onopen:(fun()->[])methodvirtualon_record_declaration:loc:loc->is_self_rec:(core_type->[`Nonrecursive|`Nonregular|`Regular])->mutual_decls:(type_declarationlist)->type_declaration->label_declarationlist->Cf.tlistmethodmake_typ_of_mutal_trf~locmutal_tdecl(k:Typ.t->_):Typ.t=letsubj_t=Typ.use_tdeclmutal_tdeclinkTyp.(arrow~locsubj_t(self#syn_of_main~locmutal_tdecl))(* k @@ Typ.from_caml [%type: ([%t subj_t] -> [%t self#syn_of_main ~loc mutal_tdecl]) ] *)(* val name : <typeof fa> -> ... -> <typeof fz> ->
<this type we are generating here>
*)(* method make_RHS_typ_of_transformation ~loc ?subj_t ?syn_t tdecl =
* let subj_t = Option.value subj_t
* ~default:(Typ.use_tdecl tdecl) in
* let syn_t = Option.value syn_t ~default:(self#syn_of_main ~loc tdecl) in
* Typ.arrow ~loc subj_t syn_t *)(* method chain_inh_syn ~loc ~inh_t ~syn_t subj_t =
* [%type: [%t inh_t] -> [%t subj_t] -> [%t syn_t] ] *)methodwrap_tr_function_typ(typ:core_type)=typmethodvirtuallong_trans_function_typ:loc:loc->type_declaration->Typ.tmethodmake_trans_function_typ~loctdecl=lettype_=self#make_RHS_typ_of_transformation~loctdeclinletnames=map_type_param_namestdecl.ptype_params~f:idinList.fold_leftnames~init:id~f:(funaccname->self#make_typ_of_class_argument~loctdecl(Typ.arrow~loc)name(funfarg->acc@@farg))type_methodmake_trans_function_nametdecl=sprintf"%s_%s"self#plugin_nametdecl.ptype_name.txt(* method make_trf_init_typ ~loc tdecl =
* Typ.arrow ~loc (Typ.access2 ~loc (sprintf "For_%s" self#trait_name) "fn") @@
* self#make_trans_function_typ ~loc tdecl *)(* generate obly for this type *)methodmake_trans_functions_sig:loc:loc->is_rec:bool->type_declaration->Sig.tlist=fun~loc~is_rectdecl->(* we skip initial functions in the interface *)List.concat[[Sig.value~loc~name:(Naming.trf_functionself#trait_nametdecl.ptype_name.txt)(self#make_final_trans_function_typ~loctdecl)]]methodmake_class_name?(is_mutal=false)tdecl=sprintf"%s%s"(Naming.trait_class_name_for_typ~trait:self#plugin_nametdecl.ptype_name.txt)(ifis_mutalthen"_stub"else"")methodapply_fas_in_new_object~loctdecl=(* very similar to self#make_inherit_args_for_alias but the latter
* applies `fself` by default. Need to refactor and remove this function *)map_type_param_namestdecl.ptype_params~f:(Exp.sprintf~loc"f%s")(* only for non-recursive types *)methodvirtualmake_trans_function_body:loc:loc->?rec_typenames:stringlist->string->type_declaration->Exp.tmethodis_combinatorialtdecl=(* We are allowed to use combinatorial interface for types which are type abbreviations *)(* let cmb_attr = List.find tdecl.ptype_attributes
~f:(fun {attr_name={txt}} -> String.equal txt "combinatorial")
in *)if(* Option.is_some cmb_attr &&*)Caml.(=)tdecl.ptype_kindPtype_abstract&¬(is_polyvariant_tdecltdecl)&¬(is_tuple_tdecltdecl)thenmatchtdecl.ptype_manifestwith|Somet->Somet|None->NoneelseNonemethodguess_recursivitytdecl=(* if the type references it's own name, then it could be recurisve.
The `nonrec` keyword can override that *)letexceptionIsRecinletexpected_name=tdecl.ptype_name.txtinletrechelpert=matcht.ptyp_descwith|Ptyp_var_|Ptyp_object_|Ptyp_package_|Ptyp_extension_|Ptyp_alias_|Ptyp_any->()|Ptyp_poly(_,_)|Ptyp_class(_,_)->failwith"not implemented"|Ptyp_tuplets->List.iterts~f:helper|Ptyp_constr({txt=Lidenttname},cargs)whenString.equaltnameexpected_name&&(List.lengthcargs=List.lengthtdecl.ptype_params)->raiseIsRec|Ptyp_constr(_,args)->List.iter~f:helperargs|Ptyp_arrow(_,l,r)->helperl;helperr|Ptyp_variant(rows,_,_)->List.iterrows~f:(function|{prf_desc=Rinheritt}->helpert|{prf_desc=Rtag(_,_,ts)}->List.iter~f:helperts)intrylet()=matchtdecl.ptype_kindwith|Ptype_recordlabs->List.iterlabs~f:(funld->helperld.pld_type)|Ptype_variantcds->List.itercds~f:(funcd->matchcd.pcd_argswith|Pcstr_tuplets->List.iter~f:helperts|Pcstr_recordlabs->List.iterlabs~f:(funld->helperld.pld_type))|Ptype_open->()|Ptype_abstract->Option.itertdecl.ptype_manifest~f:helperinfalsewithIsRec->truemethodmake_trans_functions:loc:loc->is_rec:bool->Str.tlist=fun~loc~is_rec->(* we will generate mutally recursive showers here
(* n functions like *)
let show0_typ1 = ...
let show_typ1 = #5 (fix ....)
*)letmutual_names=List.mapself#tdecls~f:(fun{ptype_name={txt}}->txt)inletis_mutual_pack=List.lengthself#tdecls>1inletintials=ifis_mutual_packthenList.mapself#tdecls~f:(funtdecl->value_binding~loc~pat:(Pat.sprintf~loc"%s"@@Naming.init_trf_functionself#trait_nametdecl.ptype_name.txt)~expr:(letclass_name=self#make_class_name~is_mutal:(not(List.is_emptymutual_names))tdeclinExp.new_~loc(Lidentclass_name)))else[]inlet(need_rec,knots)=matchself#tdeclswith|[]->(false,[])|[tdecl]->let(need_rec,body)=matchself#is_combinatorialtdeclwith|Sometyp->((ifself#guess_recursivitytdeclthenself#is_recelsefalse),self#do_typ_gen~loc~mutual_decls:[tdecl]~is_self_rec:(fun_->`Nonrecursive)tdecltyp)|None->(false,self#make_trans_function_body~loc(self#make_class_name~is_mutal:falsetdecl)tdecl)in(need_rec,[value_binding~loc~pat:(Pat.sprintf~loc"%s"@@Naming.trf_functionself#trait_nametdecl.ptype_name.txt)~expr:(Exp.fun_list~loc(map_type_param_namestdecl.ptype_params~f:(funtxt->Pat.sprintf~loc"f%s"txt))body)])|tdecls->true,List.mapitdecls~f:(funn{ptype_name={txt}}->value_binding~loc~pat:(Pat.sprintf~loc"%s"@@Naming.trf_functionself#trait_nametxt)~expr:(leteta=gen_symbol~prefix:"eta"()inExp.fun_~loc(Pat.var~loceta)@@Exp.let_~loc~rec_:false[Pat.tuple~loc@@List.mapitdecls~f:(funi_->ifi=nthenPat.var~loc"f"elsePat.any~loc),Exp.app_list~loc(Exp.ident~loc@@Naming.make_fix_nametdecls)(List.maptdecls~f:(fun{ptype_name={txt}}->Exp.sprintf~loc"%s"@@Naming.init_trf_functionself#trait_nametxt))]Exp.(app~loc(sprintf~loc"f")(sprintf~loc"%s"eta))))inList.concat[List.map~f:(Str.of_vb~loc~rec_flag:Nonrecursive)intials;letrec_flag=ifneed_rec&¬is_mutual_packthenRecursiveelseNonrecursiveinList.map~f:(Str.of_vb~loc~rec_flag)knots]methodfix_func_name?for_()=matchfor_with|None->Naming.fix_func_name_tdeclsself#plugin_nameself#tdecls|Somefor_->Naming.fix_func_name~for_self#plugin_namemethoddo_single_sig~loc~is_rectdecl=List.concat[self#make_class_sig~loc~is_rectdecl(* Need to fix drawing a signature by specializing for show|gmap case *);self#make_trans_functions_sig~loc~is_rectdecl]methoddo_single~loc~is_rectdecl=List.concat[[((self#make_class~loc~is_rectdecl):Str.t)];self#make_trans_functions~loc~is_rec]methodfinal_typ_params_for_alias~loctdeclrhs=self#alias_inherit_type_params~loctdeclrhsmethodalias_inherit_type_params~loctdeclrhs_args=self#plugin_class_params~locrhs_args~typname:tdecl.ptype_name.txtmethoddo_mutuals_sigs~loc~is_rec=List.concat[List.concat_mapself#tdecls~f:(funtdecl->List.concat[self#make_class_sig~loc~is_rec~a_stub:truetdecl;self#make_class_sig~loc~is_rectdecl]);List.concat_mapself#tdecls~f:(funtdecl->(* Need to fix drawing a signature by specializing for show|gmap case *)self#make_trans_functions_sig~loc~is_rectdecl)]methoddo_mutuals~loc~is_rectdecls:Str.tlist=(* for mutal recursion we need to generate two classes, one transformation
function many structures, fixpoint, etc. *)List.concat[List.maptdecls~f:(self#make_class~loc~is_rec:true);self#make_trans_functions~loc~is_rec;self#make_shortend_class~loctdecls]methodsimple_trf_funcs~loctdecl:Typ.t->Typ.t=letnames=map_type_param_namestdecl.ptype_params~f:idinList.fold_leftnames~init:id~f:(funaccname->self#make_typ_of_class_argument~loctdecl(Typ.arrow~loc)name(funfarg->acc@@farg))methodplugin_class_params_tdecltdecl=letparams_typs=self#plugin_class_params~loc:(loc_from_camltdecl.ptype_loc)~typname:tdecl.ptype_name.txt(List.map~f:fsttdecl.ptype_params)in(* FIXME: dirty hacks *)List.mapparams_typs~f:Typ.to_type_arg_exnmethodmake_shortend_class_sig~loc=List.mapself#tdecls~f:(funtdecl->lettypname=tdecl.ptype_name.txtinletclass_name=Naming.trait_class_name_for_typ~trait:self#plugin_nametypnameinletparams=self#plugin_class_params_tdecltdeclinletstub_name="asdf"inSig.class_~loc~name:class_name~params[Ctf.inherit_~loc@@Cty.arrow~loc(Typ.unit~loc)(Cty.constr~loc(Lidentstub_name)@@List.map~f:(Typ.of_type_arg~loc)params)])(* shortened class only used for mutally recursive declarations *)methodmake_shortend_class~loctdecls=List.maptdecls~f:(funtdecl->lettypname=tdecl.ptype_name.txtinletclass_name=Naming.trait_class_name_for_typ~trait:self#plugin_nametypnameinletstub_name=Naming.stub_class_name~plugin:self#plugin_nametdeclin(* maybe it should be called proto *)letmut_funcs=Exp.tuple~loc@@List.maptdecls~f:(fun{ptype_name={txt}}->Exp.ident~loc@@Naming.trf_functionself#plugin_nametxt)inletparams=self#plugin_class_params_tdecltdeclinStr.class_single~loc~name:class_name~wrap:(funcl->Cl.fun_~loc(* (Pat.var ~loc @@ self#self_arg_name tdecl.ptype_name.txt) @@ *)(Pat.any~loc)@@Cl.fun_list~loc(self#prepare_fa_args~loctdecl)cl)~params[Cf.inherit_~loc@@Cl.apply~loc(Cl.constr~loc(Lidentstub_name)@@List.map~f:(Typ.of_type_arg~loc)params)(mut_funcs::(self#apply_fas_in_new_object~loctdecl))])methodvirtualon_record_constr:loc:loc->is_self_rec:(core_type->[`Nonrecursive|`Nonregular|`Regular])->mutual_decls:type_declarationlist->inhe:Exp.t->type_declaration->[`Normalofstring|`Polyofstring]->(* pattern variable, label name, typ of label *)(* TODO: Replace next to arguments by single of type (string * label_declaration) list *)(string*string*core_type)list->label_declarationlist->Exp.tmethodvirtualon_tuple_constr:loc:loc->is_self_rec:(core_type->[`Nonrecursive|`Nonregular|`Regular])->mutual_decls:type_declarationlist->inhe:Exp.t->type_declaration->[`Normalofstring|`Polyofstring]option->(string*core_type)list->Exp.tmethodon_variant~loctdecl~mutual_decls~is_self_reccdsk=k@@List.mapcds~f:(funcd->letgood_constr_name=Naming.meth_name_for_constructorcd.pcd_attributescd.pcd_name.txtinmatchcd.pcd_argswith|Pcstr_tuplets->letloc=loc_from_camlcd.pcd_locinletinhp,inhe=self#make_inh~locinletbindings=List.mapts~f:(funts->gen_symbol(),ts)inletbind_pats=List.mapbindings~f:(fun(s,_)->Pat.var~locs)inCf.method_concrete~locgood_constr_name@@Exp.fun_~locinhp@@Exp.fun_~loc(Pat.any~loc)@@Exp.fun_list~locbind_pats@@self#on_tuple_constr~loc~mutual_decls~is_self_rec~inhetdecl(Option.some@@`Normalcd.pcd_name.txt)bindings|Pcstr_recordls->letloc=loc_from_camlcd.pcd_locinletinhp,inhe=self#make_inh~locinletbindings=List.mapls~f:(funl->gen_symbol(),l.pld_name.txt,l.pld_type)inletbind_pats=List.mapbindings~f:(fun(s,_,_)->Pat.var~locs)inCf.method_concrete~locgood_constr_name@@Exp.fun_~locinhp@@Exp.fun_~loc(Pat.any~loc)@@Exp.fun_list~locbind_pats@@self#on_record_constr~loc~mutual_decls~is_self_rec~inhetdecl(`Normalcd.pcd_name.txt)bindingsls)(* should be overriden in show_typed *)methodgenerate_for_variable~locvarname=Exp.sprintf~loc"f%s"varname(* required only for show_typed true *)methodeta_and_exp~centertdecl=letloc=loc_from_camltdecl.ptype_locinletfs=map_type_param_namestdecl.ptype_params~f:(sprintf"f%s")inletans=List.fold_leftfs~init:center~f:(funaccname->Exp.app~locacc(Exp.app~loc(Exp.of_longident~loc(Ldot(Lident"GT","lift")))(Exp.ident~locname)))in(* extra unit instead of inherited attribute *)letans=Exp.app_list~locans[Exp.unit~loc;Exp.ident~loc"subj"]inletans=Exp.fun_~loc(Pat.var~loc"subj")ansinList.fold_rightfs~init:ans~f:(funnameacc->Exp.fun_~loc(Pat.var~locname)acc)(* method do_typext_str ~loc ({ptyext_path } as extension) =
* let clas =
* let is_self_rec _ = false in
* let cds = List.map extension.ptyext_constructors
* ~f:(fun ec ->
* match ec.pext_kind with
* | Pext_rebind _ -> failwith ""
* | Pext_decl (args, _) ->
* Ast_builder.Default.constructor_declaration
* ~loc:extension.ptyext_path.loc ~res:None
* ~name:(ec.pext_name) ~args
* )
* in
* let tdecl =
* let open Ast_builder.Default in
* type_declaration ~loc:extension.ptyext_path.loc
* ~name:(Located.map Longident.last_exn extension.ptyext_path)
* ~params:extension.ptyext_params
* ~private_:Public ~manifest:None ~cstrs:[]
* ~kind:(Ptype_variant cds)
* in
* let fields = self#on_variant ~loc ~is_self_rec ~mutual_decls:[]
* tdecl
* cds
* id
* in
* let extra_path s = map_longident extension.ptyext_path.txt ~f:(fun _ -> s) in
* let inh_params =
* prepare_param_triples ~loc
* ~inh:(fun ~loc -> self#inh_of_param tdecl)
* ~syn:self#syn_of_param
* ~default_syn:(self#syn_of_main ~loc ~extra_path tdecl)
* ~default_inh:(self#inh_of_main ~loc tdecl)
* ~extra:(Typ.var ~loc @@
* sprintf "%s_%s" Naming.extra_param_name tdecl.ptype_name.txt)
* (map_type_param_names tdecl.ptype_params ~f:id)
* in
* let parent_plugin_impl =
* let params =
* self# final_typ_params_for_alias ~loc tdecl
* (List.map ~f:fst tdecl.ptype_params)
* in
* Cf.inherit_ ~loc @@
* Cl.apply ~loc
* (Cl.constr ~loc (extra_path (self#make_class_name tdecl)) params)
* (Exp.sprintf ~loc "%s" Naming.self_arg_name :: (self#apply_fas_in_new_object ~loc tdecl))
* (\* TODO: check that apply_fas_... is what we need *\)
* in
* (\* TODO: It seems that we don't need to inherit interface class for extensible types
* * because type parameters are no changing but it require some work to disable this
* * generation. So it is postponed *\)
* self#wrap_class_definition ~loc [] tdecl ~inh_params
* ((self#extra_class_str_members tdecl) @ parent_plugin_impl :: fields)
* in
* [ clas ] *)methodself_arg_namecname=sprintf"_%s_%s"Naming.self_arg_namecname(* TODO: maybe we can bubble from the botton not whole already applied expression
but either 1) full expression or 2) expression not yet applied
to a) attribute and b) subject. That will allow to implement sprintf effectively *)(* TODO: decide expression of which type should be returned here *)(* do_type_gen will return an expression which after being applied
* to inherited attribute and subject will return synthetized one
*)methoddo_typ_gen~loc~mutual_decls~is_self_rectdeclt:Exp.t=letmutual_names=List.mapmutual_decls~f:(funt->t.ptype_name.txt)inleton_constrparamshelpertypname=self#abstract_trf~loc(funeinhesubj->self#fancy_app~loc(List.fold_leftparams~init:(Exp.(app~loc(access~loc"GT"self#plugin_name)(access~loc"GT"typname)))~f:(funlefttyp->(* TODO: copy-paste with polyvariants *)letarg=helper~loctypinletarg=ifself#need_inh_attrthenargelseExp.app~locarg(Exp.unit~loc)inself#compose_apply_transformations~loc~leftargtyp))einhesubj)inletrechelper~loct=matcht.ptyp_descwith|Ptyp_vars->self#generate_for_variable~locs|Ptyp_arrow(_,t1,t2)->on_constr[t1;t2]helper"arrow"|Ptyp_tuplets->letinh_name=gen_symbol()inletinhe=Exp.ident~locinh_nameinletbindings=List.mapts~f:(funts->gen_symbol(),ts)inExp.fun_~loc(Pat.var~locinh_name)@@Exp.fun_~loc(Pat.tuple~loc@@List.mapbindings~f:(fun(name,_)->Pat.var~locname))@@self#on_tuple_constr~loc~is_self_rec~mutual_decls~inhetdeclNone@@bindings(* self#abstract_trf ~loc (fun einh esubj ->
self#fancy_app ~loc
(List.fold_left params
~init:(
Exp.(app ~loc
(of_longident ~loc @@ Ldot (Lident "GT", self#plugin_name))
(of_longident ~loc @@
Ldot (Lident "GT", Printf.sprintf "tuple%d" (List.length params)))
)
)
~f:(fun left typ ->
(* TODO: copy-paste with polyvariants *)
let arg = helper ~loc typ in
let arg =
if self#need_inh_attr
then arg
else Exp.app ~loc arg (Exp.unit ~loc)
in
self#compose_apply_transformations ~loc ~left arg typ
)
)
einh esubj
) *)|Ptyp_constr({txt},params)->beginmatchis_self_rectwith|`Regular->letcname=lethelper=functionLidents->s|Ldot(_,s)->s|_->assertfalseinhelpertxtinExp.ident~loc(self#self_arg_namecname)|`Nonregular->failwith"non-regular types are not supported"|`Nonrecursive->begin(* it is not a recursion but it can be a mutual recursion *)matchtxtwith|LidentswhenList.memmutual_namess~equal:String.equal->(* we should use local trf object *)letargs=List.mapparams~f:(self#do_typ_gen~loc~is_self_rec~mutual_declstdecl)inExp.(app_list~loc(ident~loc@@Naming.for_self#trait_names)args)|_->letinit=Exp.(app~loc(access~loc"GT"self#plugin_name)(of_longident~loctxt))inself#abstract_trf~loc(funeinhesubj->self#fancy_app~loc(List.fold_leftparams~init~f:(funlefttyp->(* TODO: copy-paste with constructors *)letarg=helper~loctypinletarg=ifself#need_inh_attrthenargelseExp.app~locarg(Exp.unit~loc)inself#compose_apply_transformations~loc~leftargtyp))einhesubj)endend|Ptyp_variant(rows,_,maybe_labels)->beginletoninherit~loceinhesubjtypscidentvarname=self#fancy_app~loc(Exp.app_list~locExp.(app~loc(Exp.access~loc"GT"self#plugin_name)(of_longident~loccident))(List.maptyps~f:(funtyp->letarg=helper~loctypinifself#need_inh_attrthenargelseExp.app~locarg(Exp.unit~loc))))einh(Exp.ident~locvarname)inletonrow~inhelabbindings=(* let inh_name = gen_symbol ~prefix:"inh_" () in *)(* (if self#need_inh_attr then Exp.fun_ ~loc (Pat.var ~loc inh_name)
else Fn.id) @@
Exp.fun_list ~loc (List.map bindings ~f:(fun (s,_) -> Pat.var ~loc s)) @@ *)Exp.app_list~loc(self#on_tuple_constr~loc~is_self_rec~mutual_decls:mutual_decls~inhetdecl(Option.some@@`Polylab.txt)bindings)@@[](* List.map bindings ~f:(fun (s,_) -> Exp.ident ~loc s) *)inself#abstract_trf~loc(funeinhesubj->prepare_patt_match_poly~locesubj(List.maprows~f:(fun{prf_desc}->prf_desc))maybe_labels~onrow:(onrow~inhe:einh)~onlabel:(fun__->Exp.assert_false~loc)~oninherit:(oninherit~loceinhesubj))end|_->failwith"unsupported case in do_typ_gen"inmatchself#treat_type_speciallytwith|None->helper~loct|Somee->e(* should be used only in concrete plugins *)methodtreat_type_speciallyt=None(* may be the same as fancy_app *)methodvirtualapp_transformation_expr:loc:loc->Exp.t->Exp.t->Exp.t->Exp.tmethodvirtualabstract_trf:loc:loc->(Exp.t->Exp.t->Exp.t)->Exp.t(* [fancy_app ~loc e inh subj] will either apply twice or skip application
* of inherited attribute *)methodvirtualfancy_app:loc:loc->Exp.t->Exp.t->Exp.t->Exp.tmethodvirtualapp_gcata:loc:loc->Exp.t->Exp.tmethodvirtualmake_typ_of_self_trf:loc:loc->?in_class:bool->type_declaration->Typ.t(* method virtual inh_of_main : loc:loc -> Ppxlib.type_declaration -> Typ.t *)methodvirtualmake_RHS_typ_of_transformation:loc:AstHelpers.loc->?subj_t:Typ.t->?syn_t:Typ.t->type_declaration->Typ.tmethodcompose_apply_transformations~loc~leftrighttyp:Exp.t=Exp.app~locleftright(* Is not very composable but this is olny difference between plugins now *)methodvirtualneed_inh_attr:boolend(* ******************************************************************************* *)(** Base plugin class where transformation functions doesn't use inherited
attribute.
See {!Show} and {!Gmap} plugin for examples.
*)classvirtualno_inherit_arg0args_tdecls=object(self:'self)inheritgeneratorargs_tdeclsmethodvirtualplugin_name:stringmethodvirtualsyn_of_main:loc:loc->?in_class:bool->Ppxlib.type_declaration->Typ.tmethodvirtualinh_of_main:loc:loc->Ppxlib.type_declaration->Typ.tmethodvirtualsyn_of_param:loc:loc->string->Typ.tmethodvirtualinh_of_param:loc:loc->type_declaration->string->Typ.tmethodvirtualmake_trans_function_typ:loc:loc->type_declaration->Typ.tmethoduse_tdecl=Typ.use_tdeclmethodneed_inh_attr=false(* almost the same as `make_typ_of_class_argument` *)methodmake_typ_of_self_trf~loc?(in_class=false)tdecl=letopenize_polytyp=Typ.from_camltypinletsubj_t=openize_poly@@using_type~typename:tdecl.ptype_name.txttdeclinletsyn_t=self#syn_of_main~loc~in_classtdeclinletans=Typ.(arrow~locsubj_t@@syn_t)inifself#need_inh_attrthenTyp.arrow~loc(self#inh_of_main~loctdecl)anselseTyp.arrow~loc(Typ.unit~loc)ans(* val name: <fa> -> <fb> -> ... -> <fz> -> <_not_ this>
* fot a type ('a,'b,....'z) being generated
**)(* method make_typ_of_class_argument: 'a . loc:loc -> type_declaration ->
* (Typ.t -> 'a -> 'a) ->
* string -> (('a -> 'a) -> 'a -> 'a) -> 'a -> 'a =
* fun ~loc tdecl chain name k ->
* let subj_t = Typ.var ~loc name in
* let syn_t = self#syn_of_param ~loc name in
* k @@ (fun arg -> chain (Typ.arrow ~loc subj_t syn_t) arg) *)methodmake_typ_of_class_argument:'a.loc:loc->type_declaration->(Typ.t->'a->'a)->string->(('a->'a)->'a->'a)->'a->'a=fun~loctdeclchainnamek->letinh_t=self#inh_of_param~loctdeclnameinletsubj_t=Typ.var~locnameinletsyn_t=self#syn_of_param~locnameink@@(funarg->chain(Typ.arrow~locinh_t@@Typ.arrow~locsubj_tsyn_t)arg)methodmake_RHS_typ_of_transformation~loc?subj_t?syn_ttdecl=letsubj_t=Option.valuesubj_t~default:(Typ.use_tdecltdecl)inletsyn_t=Option.valuesyn_t~default:(self#syn_of_main~loctdecl)inTyp.arrow~locsubj_tsyn_tmethodapp_gcata~locegcata=Exp.app~locegcata(Exp.unit~loc)methodon_record_constr:loc:loc->is_self_rec:(core_type->[`Nonrecursive|`Nonregular|`Regular])->mutual_decls:type_declarationlist->inhe:Exp.t->type_declaration->[`Normalofstring|`Polyofstring]->(string*string*core_type)list->label_declarationlist->Exp.t=fun~loc~is_self_rec~mutual_decls~inhe___->failwithf"handling record constructors in plugin `%s`"self#plugin_name()methodwrap_tr_function_str~loc(tdecl:type_declaration)make_gcata_of_class=(* [%expr fun the_init subj -> GT.fix0 (fun self -> [%e body]) the_init subj] *)letbody=make_gcata_of_classinExp.fun_list~loc[Pat.sprintf~loc"inh0";Pat.sprintf~loc"subj"]@@Exp.app_list~loc(Exp.of_longident~loc(Ldot(Lident"GT","transform_gc")))[Exp.sprintf~loc"gcata_%s"tdecl.ptype_name.txt(* TODO: name *);body;Exp.sprintf~loc"inh0";Exp.sprintf~loc"subj"]end(** Base plugin class where transformation functions receive inherited attribute for
type parameter *)classvirtualwith_inherited_attrargs_tdecls=object(self:'self)inheritno_inherit_arg0args_tdeclsassupermethod!need_inh_attr=true(* method! make_typ_of_self_trf ~loc tdecl =
* Typ.arrow ~loc (self#inh_of_main ~loc tdecl) (super#make_typ_of_self_trf ~loc tdecl) *)(* method long_typ_of_self_trf ~loc tdecl = self#make_typ_of_self_trf ~loc tdecl *)(* val name: <fa> -> <fb> -> ... -> <fz> -> <_not_ this>
* fot a type ('a,'b,....'z) being generated
**)method!make_typ_of_class_argument:'a.loc:loc->type_declaration->(Typ.t->'a->'a)->string->(('a->'a)->'a->'a)->'a->'a=fun~loctdeclchainnamek->letinh_t=self#inh_of_param~loctdeclnameinletsubj_t=Typ.var~locnameinletsyn_t=self#syn_of_param~locnameink@@(funarg->chain(Typ.arrow~locinh_t@@Typ.arrow~locsubj_tsyn_t)arg)method!make_RHS_typ_of_transformation~loc?subj_t?syn_ttdecl=letsubj_t=Option.valuesubj_t~default:(Typ.use_tdecltdecl)inletsyn_t=Option.valuesyn_t~default:(self#syn_of_main~loctdecl)inTyp.arrow~loc(self#inh_of_main~loctdecl)(super#make_RHS_typ_of_transformation~loc~subj_t~syn_ttdecl)methodabstract_trf~lock=letinh=gen_symbol~prefix:"inh_"()inletsubj=gen_symbol~prefix:"subj_"()inExp.fun_list~loc[Pat.var~locinh;Pat.var~locsubj]@@k(Exp.ident~locinh)(Exp.ident~locsubj)(* method fancy_abstract_trf ~loc k =
* Exp.fun_list ~loc [ Pat.sprintf ~loc "inh"; Pat.sprintf ~loc "subj" ] @@
* k (Exp.ident ~loc "inh") (Exp.ident ~loc "subj") *)methodapp_transformation_expr~loctrfinhsubj=(* we ignore inherited argument by default *)Exp.app_list~loctrf[inh;subj]methodfancy_app~loctrf(inh:Exp.t)subj=Exp.app_list~loctrf[inh;subj]method!app_gcata~locegcata=egcata(* let <plugin-name> fa ... fz = <this body> *)methodmake_trans_function_body~loc?(rec_typenames=[])class_nametdecl=self#wrap_tr_function_str~loctdecl(Exp.app_list~loc(Exp.new_~loc@@Lidentclass_name)@@((* (Exp.sprintf ~loc "%s" "call")
* :: *)(self#apply_fas_in_new_object~loctdecl)))methodapp_extra_unit~(loc:loc)(e:Exp.t)=emethodlong_trans_function_typ~(loc:loc)(tdecl:type_declaration):Typ.t=self#make_trans_function_typ~loctdeclmethodmake_final_trans_function_typ~loctdecl=self#make_trans_function_typ~loctdeclend(** Base plugin class where transformation functions doesn't use inherited
attribute.
See {!Show} and {!Gmap} plugin for examples.
*)classvirtualno_inherit_argargs_tdecls=object(self:'self)inheritno_inherit_arg0args_tdeclsmethod!need_inh_attr=false(* method long_typ_of_self_trf ~loc tdecl =
* (\* almost copy-paste of inherit_arg0 class*\)
* let openize_poly typ = Typ.from_caml typ in
* let subj_t = openize_poly @@ using_type ~typename:tdecl.ptype_name.txt tdecl in
* let syn_t = self#syn_of_main ~loc tdecl in
* Typ.(arrow ~loc subj_t @@ syn_t) *)(* let <plugin-name> fa ... fz = <this body> *)methodmake_trans_function_body~loc?(rec_typenames=[])class_nametdecl=self#wrap_tr_function_str~loctdecl(Exp.app_list~loc(Exp.new_~loc@@Lidentclass_name)@@((* ((Exp.sprintf ~loc "%s" "call")) :: *)List.maprec_typenames~f:(funname->Exp.fun_~loc(Pat.unit~loc)@@Exp.sprintf~loc"%s_%s"self#plugin_namename)@(self#apply_fas_in_new_object~loctdecl)))methodfancy_app~loctrf(inh:Exp.t)subj=Exp.app~loctrfsubjmethodabstract_trf~lock=Exp.fun_list~loc[Pat.unit~loc;Pat.sprintf~loc"subj"]@@k(Exp.unit~loc)(Exp.ident~loc"subj")method!make_RHS_typ_of_transformation~loc?subj_t?syn_ttdecl=letsubj_t=Option.valuesubj_t~default:(Typ.use_tdecltdecl)inletsyn_t=Option.valuesyn_t~default:(self#syn_of_main~loctdecl)inTyp.arrow~locsubj_tsyn_t(* method compose_apply_transformations ~loc ~left right (typ:core_type) =
* (\* Exp.app ~loc left (Exp.fun_ ~loc (Pat.unit ~loc) right) *\)
* (\* Exp.app ~loc (Exp.app ~loc left @@ Exp.unit ~loc) right *\)
* Exp.app ~loc left (Exp.app ~loc right @@ Exp.unit ~loc) *)methodapp_extra_unit~loce=Exp.app~loce(Exp.unit~loc)methodlong_trans_function_typ~loctdecl=lettype_=self#make_RHS_typ_of_transformation~loctdeclinlettype_=Typ.arrow~loc(Typ.ident~loc"unit")type_inletnames=map_type_param_namestdecl.ptype_params~f:idinList.fold_rightnames~init:type_~f:(funnameacc->letfor_arg=Typ.(arrow~loc(ident~loc"unit")@@arrow~loc(var~locname)(self#syn_of_param~locname))inTyp.arrow~locfor_argacc)(* (\* val name: <fa> -> <fb> -> ... -> <fz> -> <_not_ this>
* * fot a type ('a,'b,....'z) being generated
* **\)
* method! make_typ_of_class_argument: 'a . loc:loc -> type_declaration ->
* (Typ.t -> 'a -> 'a) ->
* string -> (('a -> 'a) -> 'a -> 'a) -> 'a -> 'a =
* fun ~loc tdecl chain name k ->
* let subj_t = Typ.var ~loc name in
* let syn_t = self#syn_of_param ~loc name in
* k @@ (fun arg -> chain (Typ.arrow ~loc subj_t syn_t) arg) *)methodmake_final_trans_function_typ~loctdecl=letmake_arg~loctdchainnamek=letsubj_t=Typ.var~locnameinletsyn_t=self#syn_of_param~locnameink@@(funarg->chain(Typ.arrow~locsubj_tsyn_t)arg)inlettype_=self#make_RHS_typ_of_transformation~loctdeclinletnames=map_type_param_namestdecl.ptype_params~f:idinList.fold_leftnames~init:id~f:(funaccname->make_arg~loctdecl(Typ.arrow~loc)name(funfarg->acc@@farg))type_methodapp_transformation_expr~loctrf(inh:Exp.t)subj=(* we ignore inherited argument by default *)Exp.app_list~loctrf[inh;subj](* method wrap_tr_function_str ~loc tdecl make_new_obj =
* Exp.fun_ ~loc (Pat.sprintf ~loc "subj") @@
* Exp.app_list ~loc
* (Exp.of_longident ~loc (Ldot (Lident "GT", "transform0_gc")) )
* [ Exp.sprintf ~loc "gcata_%s" tdecl.ptype_name.txt (\* TODO: name *\)
* ; make_new_obj
* ; Exp.sprintf ~loc "subj"
* ] *)end(*
class index_result = object
method index_functor tdecls =
assert (List.length tdecls > 0);
let name = (List.hd_exn tdecls).ptype_name.txt in
sprintf "Index_%s" name
method index_modtyp_name tdecls =
assert (List.length tdecls > 0);
let name = (List.hd_exn tdecls).ptype_name.txt in
sprintf "IndexResult_%s" name
end
class index_result2 = object
method index_functor tdecls =
assert (List.length tdecls > 0);
let name = (List.hd_exn tdecls).ptype_name.txt in
sprintf "Index2_%s" name
method index_modtyp_name tdecls =
assert (List.length tdecls > 0);
let name = (List.hd_exn tdecls).ptype_name.txt in
sprintf "IndexResult2_%s" name
end
*)end