Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Source file ppxlib_traverse.ml
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542openStdppxopenPpxlibopenAst_builder.Defaultletalphabet=Array.init(Char.code'z'-Char.code'a'+1)~f:(funi->String.make1(Char.chr(i+Char.code'a')));;letvars_of_list~get_locl=List.mapil~f:(funix->{txt=alphabet.(i);loc=get_locx})letevar_of_var{txt;loc}=evar~loctxtletpvar_of_var{txt;loc}=pvar~loctxtlettvar_of_var{txt;loc}=ptyp_var~loctxtletevars_of_vars=List.map~f:evar_of_varletpvars_of_vars=List.map~f:pvar_of_varlettvars_of_vars=List.map~f:tvar_of_varmoduleBackends=structclassreconstructors=objectmethodrecord~locflds=pexp_record~locfldsNonemethodconstruct~locidargs=pexp_construct~locid(matchargswith|[]->None|_->Some(pexp_tuple~locargs))methodtuple~loces=pexp_tuple~locesendclasstypewhat=objectmethodname:stringinheritreconstructorsmethodclass_params:loc:Location.t->(core_type*variance)listmethodapply:loc:Location.t->expression->expressionlist->expressionmethodabstract:loc:Location.t->pattern->expression->expression(* Basic combinator type *)methodtyp:loc:Location.t->core_type->core_typemethodany:loc:Location.t->expressionmethodcombine:loc:Location.t->(stringloc*expression)list->reconstruct:expression->expressionendletmapper:what=objectmethodname="map"inheritreconstructorsmethodclass_params~loc:_=[]methodapply~locexprargs=eapply~locexprargsmethodabstract~locpattexpr=pexp_fun~locNolabelNonepattexprmethodtyp~locty=ptyp_arrow~locNolabeltytymethodany~loc=[%exprfunx->x]methodcombine~loccombinators~reconstruct=List.fold_rightcombinators~init:reconstruct~f:(fun(v,expr)acc->pexp_let~locNonrecursive[value_binding~loc~pat:(pvar_of_varv)~expr]acc)endletiterator:what=objectmethodname="iter"inheritreconstructorsmethodclass_params~loc:_=[]methodapply~locexprargs=eapply~locexprargsmethodabstract~locpattexpr=pexp_fun~locNolabelNonepattexprmethodtyp~locty=[%type:[%tty]->unit]methodany~loc=[%exprfun_->()]methodcombine~loccombinators~reconstruct:_=matchList.revcombinatorswith|[]->[%expr()]|(_,expr)::rest->List.fold_leftrest~init:expr~f:(funacc(_v,expr)->pexp_sequence~locexpracc)endletfolder:what=objectmethodname="fold"inheritreconstructorsmethodclass_params~loc=[(ptyp_var~loc"acc",Invariant)]methodapply~locexprargs=eapply~locexpr(args@[evar~loc"acc"])methodabstract~locpattexpr=eabstract~loc[patt;pvar~loc"acc"]exprmethodtyp~locty=[%type:[%tty]->'acc->'acc]methodany~loc=[%exprfun_acc->acc]methodcombine~loccombinators~reconstruct:_=matchcombinatorswith|[(_,expr)]->expr|_->List.fold_rightcombinators~init:[%expracc]~f:(fun(_v,expr)acc->[%exprletacc=[%eexpr]in[%eacc]])endletfold_mapper:what=objectmethodname="fold_map"inheritreconstructorsmethodclass_params~loc=[(ptyp_var~loc"acc",Invariant)]methodapply~locexprargs=eapply~locexpr(args@[evar~loc"acc"])methodabstract~locpattexpr=eabstract~loc[patt;pvar~loc"acc"]exprmethodtyp~locty=[%type:[%tty]->'acc->[%tty]*'acc]methodany~loc=[%exprfunxacc->(x,acc)]methodcombine~loccombinators~reconstruct=List.fold_rightcombinators~init:[%expr([%ereconstruct],acc)]~f:(fun(v,expr)acc->[%exprlet([%ppvar_of_varv],acc)=[%eexpr]in[%eacc]])endexceptionFoundletuses_varvar=letiter=objectinheritAst_traverse.iterassupermethod!expression_desc=function|Pexp_ident{txt=Lidentid;_}whenString.equalidvar->raise_notraceFound|e->super#expression_desceendinfune->tryiter#expressione;falsewithFound->true;;letmapper_with_context:what=letuses_ctx=uses_var"ctx"inobjectmethodname="map_with_context"inheritreconstructorsmethodclass_params~loc=[(ptyp_var~loc"ctx",Invariant)]methodapply~locexprargs=eapply~locexpr(evar~loc"ctx"::args)methodabstract~locpattexpr=ifuses_ctxexprtheneabstract~loc[pvar~loc"ctx";patt]exprelseeabstract~loc[pvar~loc"_ctx";patt]exprmethodtyp~locty=[%type:'ctx->[%tty]->[%tty]]methodany~loc=[%exprfun_ctxx->x]methodcombine~loccombinators~reconstruct=List.fold_rightcombinators~init:reconstruct~f:(fun(v,expr)acc->[%exprlet[%ppvar_of_varv]=[%eexpr]in[%eacc]])endletstring_of_lidid=String.concat~sep:"."(Longident.flatten_exnid)letlifter:what=objectmethodname="lift"methodclass_params~loc=[(ptyp_var~loc"res",Invariant)]methodapply~locexprargs=eapply~locexprargsmethodabstract~locpattexpr=pexp_fun~locNolabelNonepattexprmethodtyp~locty=[%type:[%tty]->'res]methodany~loc=[%exprself#other]methodcombine~loccombinators~reconstruct=List.fold_rightcombinators~init:reconstruct~f:(fun(v,expr)acc->pexp_let~locNonrecursive[value_binding~loc~pat:(pvar_of_varv)~expr]acc)methodrecord~locflds=letflds=elist~loc(List.mapflds~f:(fun(lab,e)->pexp_tuple~loc:{lab.locwithloc_end=e.pexp_loc.loc_end}[estring~loc:lab.loc(string_of_lidlab.txt);e]))in[%exprself#record[%eflds]]methodconstruct~locidargs=letargs=elist~locargsin[%exprself#constr[%eestring~loc:id.loc(string_of_lidid.txt)][%eargs]]methodtuple~loces=[%exprself#tuple[%eelist~loces]]endletall=[mapper;iterator;folder;fold_mapper;mapper_with_context;lifter]endtypewhat=Backends.whatletmapper_type~(what:what)~loctype_nameparams=letvars=vars_of_listparams~get_loc:(funt->t.ptyp_loc)inletparams=tvars_of_varsvarsinletty=ptyp_constr~loctype_nameparamsinletty=List.fold_rightparams~init:(what#typ~locty)~f:(funparamty->letloc=param.ptyp_locinptyp_arrow~locNolabel(what#typ~locparam)ty)inptyp_poly~locvarsty;;letconstrained_mapper~(what:what)?(is_gadt=false)mappertd=letvars=vars_of_listtd.ptype_params~get_loc:(fun(t,_)->t.ptyp_loc)inletmake_typeparams=letloc=td.ptype_locinletty=ptyp_constr~loc(Loc.maptd.ptype_name~f:lident)paramsinList.fold_rightparams~init:(what#typ~loc:td.ptype_locty)~f:(funparamty->letloc=param.ptyp_locinptyp_arrow~locNolabel(what#typ~locparam)ty)inlettyp=letloc=td.ptype_locinptyp_poly~locvars(make_type(tvars_of_varsvars))inletmapper=iffalse||is_gadtthenlettyps=List.mapvars~f:(funv->ptyp_constr~loc:v.loc(Loc.mapv~f:lident)[])inList.fold_rightvars~init:(pexp_constraint~loc:mapper.pexp_locmapper(make_typetyps))~f:(funve->pexp_newtype~loc:v.locve)elsemapperinpexp_poly~loc:mapper.pexp_locmapper(Sometyp);;letmangle_type_namelid=letrecmangled_partslid~suffix=matchlidwith|Lidents->String.lowercase_asciis::suffix|Ldot(lid,s)->mangled_partslid~suffix:("__"::String.lowercase_asciis::suffix)|Lapply(a,b)->mangled_partsa~suffix:("_'"::mangled_partsb~suffix:("'"::suffix))inmangled_partslid~suffix:[]|>String.concat~sep:""letrectype_expr_mapper~(what:what)te=letloc=te.ptyp_locinmatchte.ptyp_descwith|Ptyp_vars->evar~loc("_"^s)|Ptyp_tupletes->letvars=vars_of_listtes~get_loc:(funt->t.ptyp_loc)inletdeconstruct=ppat_tuple~loc(pvars_of_varsvars)inletreconstruct=what#tuple~loc(evars_of_varsvars)inletmappers=map_variables~whatvarstesinwhat#abstract~locdeconstruct(what#combine~locmappers~reconstruct)|Ptyp_constr(path,params)->letmap=pexp_send~loc(evar~loc"self")(Loc.mappath~f:mangle_type_name)in(matchparamswith|[]->map|_->eapply~locmap(List.mapparams~f:(funte->type_expr_mapper~whatte)))|_->what#any~locandmap_variables~(what:what)varstes=List.map2tesvars~f:(funtevar->(var,what#apply~loc:te.ptyp_loc(type_expr_mapper~whatte)[evar_of_varvar]));;letgen_record'~(what:what)~loclds=letvars=List.maplds~f:(funld->ld.pld_name)inletdeconstruct=ppat_record~loc(List.mapvars~f:(funv->(Loc.mapv~f:lident,pvar_of_varv)))Closedinletreconstruct=what#record~loc(List.mapvars~f:(funv->(Loc.mapv~f:lident,evar_of_varv)))inletmappers=map_variables~whatvars(List.maplds~f:(funld->ld.pld_type))indeconstruct,reconstruct,mappers;;letgen_record~(what:what)~loclds=letdeconstruct,reconstruct,mappers=gen_record'~whatlds~locinwhat#abstract~locdeconstruct(what#combine~locmappers~reconstruct);;letis_constant_constructorcd=matchcd.pcd_argswith|Pcstr_tuple[]->true|_->falseleterase_type_variables=objectinheritAst_traverse.mapassupermethod!core_type_desc=function|Ptyp_var_->Ptyp_any|x->super#core_type_descxendletgen_variant~(what:what)~loccds=ifString.(<>)what#name"lift"&&List.for_allcds~f:is_constant_constructorthenwhat#any~locelseletcases=List.mapcds~f:(funcd->letcstr=Loc.mapcd.pcd_name~f:lidentinletloc=cd.pcd_locinletargs=matchcd.pcd_reswith|None->cd.pcd_args|Some_->(* This is a big sur-approximation but it's enough for our only use of GADTs
in ppx_custom_format *)erase_type_variables#constructor_argumentscd.pcd_argsinmatchargswith|Pcstr_tupleargs->letvars=vars_of_listargs~get_loc:(funt->t.ptyp_loc)inletdeconstruct=ppat_constructcstr~loc(matchvarswith|[]->None|_->Some(ppat_tuple~loc(pvars_of_varsvars)))inletreconstruct=what#constructcstr~loc(evars_of_varsvars)inletmappers=map_variables~whatvarsargsincase~lhs:deconstruct~rhs:(what#combine~locmappers~reconstruct)~guard:None|Pcstr_recordlabels->letdeconstruct,reconstruct,mappers=gen_record'~loc~whatlabelsinletdeconstruct=ppat_construct~loccstr(Somedeconstruct)inletreconstruct=what#construct~loccstr[reconstruct]incase~lhs:deconstruct~rhs:(what#combine~locmappers~reconstruct)~guard:None)inwhat#abstract~loc(pvar~loc"x")(pexp_match~loc(evar~loc"x")cases)letgen_mapper~(what:what)td=letbody=letloc=td.ptype_locinmatchtd.ptype_kindwith|Ptype_open->what#any~loc|Ptype_recordlds->gen_record~whatlds~loc|Ptype_variantcds->gen_variant~whatcds~loc|Ptype_abstract->matchtd.ptype_manifestwith|None->what#any~loc|Somete->type_expr_mapper~whatteinList.fold_righttd.ptype_params~init:body~f:(fun(ty,_)acc->letloc=ty.ptyp_locinmatchty.ptyp_descwith|Ptyp_vars->pexp_fun~locNolabelNone(pvar~loc("_"^s))acc|_->pexp_fun~locNolabelNone(ppat_any~loc)acc);;lettype_deps=letcollect=objectinherit[intLongident.Map.t]Ast_traverse.foldassupermethod!core_typetacc=letacc=matcht.ptyp_descwith|Ptyp_constr(id,vars)->Longident.Map.addid.txt(List.lengthvars)acc|_->accinsuper#core_typetaccendinfuntds->letempty=Longident.Map.emptyinletmap=List.fold_lefttds~init:empty~f:(funmaptd->letmap=collect#type_kindtd.ptype_kindmapinmatchtd.ptype_kind,td.ptype_manifestwith|Ptype_abstract,Somety->collect#core_typetymap|_->map)inletmap=List.fold_lefttds~init:map~f:(funmaptd->Longident.Map.remove(Lidenttd.ptype_name.txt)map)inLongident.Map.bindingsmapletlift_virtual_methods~locmethods=letcollect=objectinherit[String.Set.t]Ast_traverse.foldassupermethod!expression_descxacc=matchxwith|Pexp_send(_,({txt="tuple"|"record"|"constr"|"other"ass;loc=_;}))->String.Set.addsacc|_->super#expression_descxaccendinletused=collect#listcollect#class_fieldmethodsString.Set.emptyinletall_virtual_methods=match[%striclassvirtualblah=objectmethodvirtualrecord:(string*'res)list->'resmethodvirtualconstr:string->'reslist->'restmethodvirtualtuple:'reslist->'resmethodvirtualother:'a.'a->'resend]with|{pstr_desc=Pstr_class[{pci_expr={pcl_desc=Pcl_structure{pcstr_fields=l;_};_};_}];_}->l|_->assertfalseinList.filterall_virtual_methods~f:(funm->matchm.pcf_descwith|Pcf_method(s,_,_)->String.Set.mems.txtused|_->false)letgen_class~(what:what)~loctds=letclass_params=what#class_params~locinletvirtual_methods=List.map(type_depstds)~f:(fun(id,arity)->pcf_method~loc({txt=mangle_type_nameid;loc},Public,Cfk_virtual(mapper_type~what~loc{txt=id;loc}(List.init~len:arity~f:(fun_->ptyp_any~loc)))))inletmethods=List.maptds~f:(funtd->letloc=td.ptype_locinletmapper=gen_mapper~whattdinletis_gadt=matchtd.ptype_kindwith|Ptype_variantcds->List.existscds~f:(funcd->Option.is_somecd.pcd_res)|_->falseinletmapper=constrained_mapper~what~is_gadtmappertdinpcf_method~loc(td.ptype_name,Public,Cfk_concrete(Fresh,mapper)))inletvirtual_methods=ifString.equalwhat#name"lift"thenlift_virtual_methods~locmethods@virtual_methodselsevirtual_methodsinletvirt=ifList.is_emptyvirtual_methodsthenConcreteelseVirtualinclass_infos~loc~virt~params:class_params~name:{loc;txt=what#name}~expr:(pcl_structure~loc(class_structure~self:(ppat_var~loc{txt="self";loc})~fields:(virtual_methods@methods)))letgen_str~(what:what)~loc~path:_(rf,tds)=(matchrfwith|Nonrecursive->(* The method name would clash... *)Location.raise_errorf~loc"ppxlib_traverse doesn't support nonrec"|Recursive->());letcl=gen_class~loc~whattdsin[pstr_class~loc:cl.pci_loc[cl]]let()=letderivers=List.mapBackends.all~f:(funwhat->Deriving.add("traverse_"^what#name)~str_type_decl:(Deriving.Generator.make_noarg(gen_str~what)))inDeriving.add_alias"traverse"(List.revderivers)|>Deriving.ignore