Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Source file meta_deriving.ml
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142openPpxlibmodulePlugin=structtypet={name:string;type_name:[`before|`after];impl:location->expression->expression;intf:location->core_type->core_type;}letcreate?(type_name=`after)~impl~intfname={name;type_name;impl;intf}letop_name_of_type_nametn=match(n,t.type_name)with|"t",_->t.name|x,`before->Printf.sprintf"%s_%s"xt.name|x,`after->Printf.sprintf"%s_%s"t.namexletderive_strt~loc~type_name~params~expr:repr=let(moduleAst_builder)=Ast_builder.makelocinletopenAst_builderinletname=op_name_of_type_namettype_nameinletexpr=letbody=t.impllocreprinListLabels.fold_rightparams~init:body~f:(funpacc->pexp_funNolabelNone(pvarp)acc)inpstr_valueNonrecursive[value_binding~pat:(ppat_var(Located.mkname))~expr]letderive_sigt~loc~type_name~params~ctyp:repr=let(moduleAst_builder)=Ast_builder.makelocinletopenAst_builderinletname=op_name_of_type_namettype_nameinlettype_=letreturn_type=t.intflocreprinListLabels.fold_rightparams~init:return_type~f:(ptyp_arrowNolabel)inpsig_value(value_description~name:(Located.mkname)~type_~prim:[])letdefaults=[create"equal"~impl:(funloct->[%exprRepr.unstage(Repr.equal[%et])])~intf:(funloct->[%type:[%tt]->[%tt]->bool]);create"compare"~impl:(funloct->[%exprRepr.unstage(Repr.compare[%et])])~intf:(funloct->[%type:[%tt]->[%tt]->int]);create"size_of"~impl:(funloct->[%exprRepr.unstage(Repr.size_of[%et])])~intf:(funloct->[%type:[%tt]->intoption]);create"pp"~impl:(funloct->[%exprRepr.pp[%et]])~intf:(funloct->[%type:Stdlib.Format.formatter->[%tt]->unit]);create"pp_dump"~impl:(funloct->[%exprRepr.pp_dump[%et]])~intf:(funloct->[%type:Stdlib.Format.formatter->[%tt]->unit]);create"random"~impl:(funloct->[%exprRepr.unstage(Repr.random[%et])])~intf:(funloct->[%type:unit->[%tt]]);create"to_bin_string"~type_name:`before~impl:(funloct->[%exprRepr.unstage(Repr.to_bin_string[%et])])~intf:(funloct->[%type:[%tt]->string]);create"of_bin_string"~type_name:`before~impl:(funloct->[%exprRepr.unstage(Repr.of_bin_string[%et])])~intf:(funloct->[%type:string->([%tt],[`Msgofstring])Stdlib.result]);create"encode_bin"~impl:(funloct->[%exprRepr.unstage(Repr.encode_bin[%et])])~intf:(funloct->[%type:[%tt]->(string->unit)->unit]);create"decode_bin"~impl:(funloct->[%exprRepr.unstage(Repr.decode_bin[%et])])~intf:(funloct->[%type:string->intref->[%tt]]);create"short_hash"~impl:(funloct->[%exprRepr.unstage(Repr.short_hash[%et])])~intf:(funloct->[%type:?seed:int->[%tt]->unit]);create"pre_hash"~impl:(funloct->[%exprRepr.unstage(Repr.pre_hash[%et])])~intf:(funloct->[%type:[%tt]->(string->unit)->unit]);]end(** [Deriving.Args.t] is a heterogeneous list that supports only [revcons] but
we need [cons] below. As a workaround, we use our own argument list type for
the intermediate representation. *)moduleArgs=structmodulePlain=Deriving.Argstype(_,_)t=|[]:('a,'a)t|(::):'aPlain.param*('b,'c)t->('a->'b,'c)tletto_plain:typeab.(a,b)t->(a,b)Plain.t=letrecaux:typeabc.(a,b)Plain.t->(b,c)t->(a,c)Plain.t=funacc->function[]->acc|x::xs->auxPlain.(acc+>x)xsinfunt->auxDeriving.Args.emptytletrecappend:typeabc.(a,b)t->(b,c)t->(a,c)t=funab->matchawith[]->b|x::xs->x::appendxsbend(** Each plugin gets a flag in the main deriver corresponding to whether it's
activated or not. For instance, [\[@@deriving repr ~equal\]] indicates that
the "equal" plugin should be run on this type definition.
Given the list of plugins [ p1; p2; ... pn ], we need to build:
- the [Deriving.Args] list of flags to pass to [Ppxlib];
- a corresponding function over booleans [fun b1 b2 ... bn -> ...] for
Ppxlib to call indicating which of the plugins have been activated.
For each derivation, we pass the list of activated plugins to the deriver. *)moduleArg_collector=structtype_t=|E:{args:('f,'output)Args.t;consumer:(Plugin.tlist->'output)->'f;}->'outputtletempty=E{args=Args.[];consumer=(funk->k[])}letadd(plugin:Plugin.t)(E{args;consumer})=letargs=Args.(Deriving.Args.flagplugin.name::args)inletconsumerkflag_passed=(* If this plugin has been selected, then add it to the list and pass it
along, otherwise skip. *)consumer(funps->ifflag_passedthenk(plugin::ps)elsekps)inE{args;consumer}letfor_pluginsps=ListLabels.fold_rightps~f:add~init:emptyendletmake_generator?attributes?deps~args:extra_args~supported_pluginsf=let(E{args;consumer})=Arg_collector.for_pluginssupported_pluginsinDeriving.Generator.make?attributes?depsArgs.(to_plain(appendargsextra_args))(fun~loc~pathinput->consumer(funplugins->f~loc~pathpluginsinput))