123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551(** This module does not have an associated .mli file because its
signature depends dynamically from the contents of [Parsetree].
The module mainly provides two sub-modules [Metaquot.Exp] and
[Metaquot.Pat], which provide lifters for expressions and patterns
respectively. *)[%%metapackagemetapp,findlib][%%metaflag"-open","Stdcompat"]letexpression_of_default_loc():Ppxlib.expression=Metapp.apply(Metapp.Exp.var"!")[Metapp.Exp.ident(Ldot(Ldot(Lident"Ppxlib","Ast_helper"),"default_loc"))]typemapper={expression:Ppxlib.expression->Ppxlib.expression;pattern:Ppxlib.pattern->Ppxlib.pattern;}moduleEq=structtype('a,'b)t=Refl:('a,'a)tendmoduletypeQuoteValueS=sigincludeMetapp.ValueSvalquote_location:Location.t->tvalquote_location_stack:_->tvalsubst_of_expr:Ppxlib.expression->tvalis_expr:(t,Ppxlib.expression)Eq.toptionvalget_mapper:mapper->t->tendmoduleQuoteExp:QuoteValueSwithtypet=Ppxlib.expression=structincludeMetapp.Expletquote_location(_:Location.t):Ppxlib.expression=expression_of_default_loc()letquote_location_stack(_:_):Ppxlib.expression=Metapp.Exp.nil()letsubst_of_expre=eletis_expr=SomeEq.Reflletget_mappermapper=mapper.expressionendmoduleQuotePat:QuoteValueSwithtypet=Ppxlib.pattern=structincludeMetapp.Patletquote_location(_:Location.t):Ppxlib.pattern=Ppxlib.Ast_helper.Pat.any()letquote_location_stack(_:_):Ppxlib.pattern=Ppxlib.Ast_helper.Pat.any()letsubst_of_expr(e:Ppxlib.expression)=matchewith|{pexp_desc=Pexp_ident{txt=Lidenttxt;loc}}->Ppxlib.Ast_helper.Pat.var{txt;loc}|{pexp_loc;_}->Location.raise_errorf~loc:pexp_loc"Simple variable expected"letis_expr=Noneletget_mappermapper=mapper.patternend[%%metadefletppxlib=Longident.Lident"Ppxlib"letasttypes=Longident.Ldot(ppxlib,"Asttypes")letfind_modulemodule_name(signature:Types.signature):Types.signatureoption=signature|>List.find_map(fun(item:Types.signature_item)->matchitemwith|Sig_module(ident,_,{md_type=Mty_signatures;_},_,_)whenIdent.nameident=module_name->Somes|_->None)letquote_namename=Printf.sprintf"%s"nameletquote_of_path(path:Path.t):Ppxlib.expression=letname=matchUntypeast.lident_of_pathpathwith|Lidentname|Ldot(Lident"Asttypes",name)->name|Ldot((Ldot(Lident"Astlib__","Location")|Lident"Location"),"t")->"location"|Ldot((Ldot(Lident"Astlib__","Longident")|Lident"Longident"),"t")->"longident"|lident->failwith(Format.asprintf"quote_of_path: %s"(String.concat"."(Longident.flattenlident)))inMetapp.Exp.var(quote_namename)letindex_variablesargs=List.mapi(funiarg->Printf.sprintf"x%d"i,arg)argsletrecquote_of_type_expr(ty:Types.type_expr):Ppxlib.expression=matchMetapp.Types.get_desctywith|Tvarx->Metapp.Exp.var(quote_name(Option.getx))|Tconstr(Pidentlist,[arg],_)whenIdent.namelist="list"->Metapp.apply(Metapp.Exp.var(quote_name"list"))~labels:["subst",[%esubst]]~optional:["in_list",[%ein_list]][Ppxlib.Ast_helper.Exp.fun_(Labelled"subst")None(Metapp.Pat.var"subst")(Ppxlib.Ast_helper.Exp.fun_(Optional"in_list")None(Metapp.Pat.var"in_list")(quote_of_type_exprarg))]|Tconstr(path,args,_)->Metapp.apply(quote_of_pathpath)~labels:["subst",[%esubst]]~optional:["in_list",[%ein_list]](List.mapquote_of_type_exprargs)|Ttupleargs->letargs=index_variablesargsinletpat=Metapp.Pat.tuple(List.map(fun(x,_)->Metapp.Pat.varx)args)inletexp=Metapp.apply(Metapp.Exp.ident(Ldot(Lident"Target","tuple")))[Metapp.Exp.list(args|>List.map(fun(x,arg)->Metapp.apply(quote_of_type_exprarg)[Metapp.Exp.varx]))]inPpxlib.Ast_helper.Exp.fun_NolabelNonepatexp|_->assertfalseletcase_of_ctor(prefix:Longident.t)(declaration:Types.constructor_declaration):Ppxlib.case=letargs=matchdeclaration.cd_argswith|Cstr_tupleargs->args|_->assertfalseinletargs=index_variablesargsinletname=Ident.namedeclaration.cd_idinletpat=Metapp.Pat.construct(Lidentname)(List.map(fun(x,_)->Metapp.Pat.varx)args)inletexp=[%eTarget.construct[%metaMetapp.Exp.of_longident(Ldot(prefix,name))][%metaMetapp.Exp.list(args|>List.map(fun(x,arg)->Metapp.apply(quote_of_type_exprarg)[Metapp.Exp.varx]))]]inPpxlib.Ast_helper.Exp.casepatexpletquote_of_record(prefix:Longident.t)(labels:Types.label_declarationlist):Ppxlib.case=letlabels=index_variableslabelsinletpat=Metapp.Pat.record(labels|>List.map(fun(x,(label:Types.label_declaration))->(Longident.Lident(Ident.namelabel.ld_id),Metapp.Pat.varx)))inletexp=Metapp.apply(Metapp.Exp.ident(Ldot(Lident"Target","record")))[Metapp.Exp.list(labels|>List.map(fun(x,(label:Types.label_declaration))->letname=Ident.namelabel.ld_idinletvalue=matchnamewith|"pexp_loc_stack"|"ppat_loc_stack"->[%eTarget.quote_location_stack()]|_->Metapp.apply(quote_of_type_exprlabel.ld_type)[Metapp.Exp.varx]inMetapp.Exp.tuple[Metapp.Exp.of_longident(Ldot(prefix,name));value]))]inletexp=matchlabels|>List.find_map(fun(x,(label:Types.label_declaration))->matchMetapp.Types.get_desclabel.ld_typewith|Tconstr(Pidentident,[],_)whenIdent.nameident="attributes"->Somex|_->None)with|None->exp|Someattributes->[%eletsubst,[%metaMetapp.Pat.varattributes]=matchMetapp.Attr.chop"subst"[%metaMetapp.Exp.varattributes]with|None->subst,[%metaMetapp.Exp.varattributes]|Some(attribute,attributes)->StringMap.union(fun__x->Somex)subst(parse_substattribute),attributesinlet[%metaMetapp.Pat.varattributes],k=matchMetapp.Attr.chop"for"[%metaMetapp.Exp.varattributes]with|None->[%metaMetapp.Exp.varattributes],Fun.id|Some(attribute,attributes)->matchMetapp.Exp.of_payload(Metapp.Attr.payloadattribute)with|[%expr[%e?target]:=[%e?list]]->letloc=Metapp.Attr.to_locattributeinbeginmatchin_listwith|None->Location.raise_errorf~loc"@for attribute is only allowed in lists"|Somein_list->letlist_index=!list_counterinlist_counter:=succlist_index;letlist_identifier=Printf.sprintf"list%d"list_indexinin_list:=list_identifier::!in_list;letk(e:Target.t):Target.t=matchTarget.is_exprwith|None->Location.raise_errorf~loc"@for attribute is only allowed in expressions"|SomeRefl->[%exprletlist=match![%eMetapp.Exp.varlist_identifier]with|None->[%elist]|Somelist->listinmatchlistwith|[]->raiseEnd_of_list|hd::tl->[%eMetapp.Exp.varlist_identifier]:=Sometl;let[%pQuotePat.subst_of_exprtarget]=hdin[%ee]]inattributes,kend|_->Location.raise_errorf~loc:(Metapp.Attr.to_locattribute)"Unsupported binding for @for"ink[%metaexp]]inPpxlib.Ast_helper.Exp.casepatexpletquote_of_declaration(prefix:Longident.t)(name:string)(declaration:Types.type_declaration):Ppxlib.value_binding=letcases=matchdeclaration.type_kindwith|Type_abstract->[Ppxlib.Ast_helper.Exp.case(Metapp.Pat.var"x")(Metapp.apply(quote_of_type_expr(Option.getdeclaration.type_manifest))[Metapp.Exp.var"x"])]|Type_variant_->letctors,_=Option.get(Metapp.Types.destruct_type_variantdeclaration.type_kind)inList.map(case_of_ctorprefix)ctors|Type_record(labels,_)->[quote_of_recordprefixlabels]|Type_open->assertfalseinletpat=matchnamewith|"core_type"->Some[%p?{ptyp_desc=Ptyp_extension({txt="t";_},payload);_}]|"pattern"->Some[%p?{ppat_desc=Ppat_extension({txt="p";_},payload);_}]|"expression"->Some[%p?{pexp_desc=Pexp_extension({txt="e";_},payload);_}]|"module_type"->Some[%p?{pmty_desc=Pmty_extension({txt="m";_},payload);_}]|"module_expr"->Some[%p?{pmod_desc=Pmod_extension({txt="m";_},payload);_}]|"signature_item"->Some[%p?{psig_desc=Psig_extension(({txt="i";_},payload),_);_}]|"structure_item"->Some[%p?{pstr_desc=Pstr_extension(({txt="i";_},payload),_);_}]|"class_type"->Some[%p?{pcty_desc=Pcty_extension({txt="c";_},payload);_}]|"class_type_field"->Some[%p?{pctf_desc=Pctf_extension({txt="c";_},payload);_}]|"class_expr"->Some[%p?{pcl_desc=Pcl_extension({txt="c";_},payload);_}]|"class_field"->Some[%p?{pcf_desc=Pcf_extension({txt="c";_},payload);_}]|_->Noneinletcases=matchpatwith|None->cases|Somepat->Ppxlib.Ast_helper.Exp.casepat[%eTarget.get_mapperMapper.mapper(Target.of_payloadpayload)]::casesinletexp=[%efunx->try[%meta(Ppxlib.Ast_helper.Exp.match_[%ex]cases)]withSubst{ty=[%metaMetapp.Pat.of_stringname];target}->target]inlettarget=Ppxlib.Ast_helper.Typ.constr(Metapp.mkloc(Longident.Ldot(Lident"Target","t")))[]inletparam_names=declaration.type_params|>List.map(fun(ty:Types.type_expr)->matchMetapp.Types.get_desctywith|Tvar(Somename)->name|_->assertfalse)inlettyp=Ppxlib.Ast_helper.Typ.arrowNolabel(Ppxlib.Ast_helper.Typ.constr(Metapp.mkloc(Longident.Ldot(prefix,name)))(List.mapPpxlib.Ast_helper.Typ.varparam_names))targetinletadd_paramtytyp=Ppxlib.Ast_helper.Typ.arrowNolabel(Ppxlib.Ast_helper.Typ.arrowNolabel(Ppxlib.Ast_helper.Typ.varty)target)typinlettyp=List.fold_rightadd_paramparam_namestypinlettyp=[%t:?subst:substStringMap.t->?in_list:stringlistref->[%metatyp]]inlettyp=matchparam_nameswith|[]->typ|_->Metapp.Typ.poly(List.mapMetapp.mklocparam_names)typinletadd_paramnameexp=Ppxlib.Ast_helper.Exp.fun_NolabelNone(Metapp.Pat.var(quote_namename))expinletexp=List.fold_rightadd_paramparam_namesexpinletexp=[%efun?(subst=StringMap.empty)?in_list->[%metaexp]]inletpat=Ppxlib.Ast_helper.Pat.constraint_(Metapp.Pat.var(quote_namename))typinPpxlib.Ast_helper.Vb.mkpatexpletquote_of_sig(filter:stringlist->bool)(prefix:Longident.t)(s:Types.signature):Ppxlib.structure_item=letaccu_groupgroupaccu=matchgroupwith|None->accu|Some(rec_flag,group)->(rec_flag,List.revgroup)::accuinletadd_item(group,accu)(item:Types.signature_item)=matchMetapp.Types.Sigi.destruct_sig_typeitemwith|Some{id;decl;rec_status;_}->let((rec_status,accu_group),accu)=match(rec_status,group)with|(Trec_next,Somegroup)->(group,accu)|(Trec_first,_)->((Ppxlib.Asttypes.Recursive,[]),accu_groupgroupaccu)|(Trec_not,_)->((Ppxlib.Asttypes.Nonrecursive,[]),accu_groupgroupaccu)|_->assertfalsein(Some(rec_status,(id,decl)::accu_group),accu)|None->(group,accu)inlet(group,accu)=List.fold_leftadd_item(None,[])sinletgroups=List.rev(accu_groupgroupaccu)inletgroups=groups|>List.filter(fun(_,declarations)->filter(declarations|>List.map(fun(id,_)->Ident.nameid)))inlets=groups|>List.map(fun(rec_flag,declarations)->Ppxlib.Ast_helper.Str.valuerec_flag(List.map(fun(id,decl)->quote_of_declarationprefix(Ident.nameid)decl)declarations))inMetapp.Stri.of_listslet()=Findlib.init()letcompiler_libs=Findlib.package_directory"ppxlib.ast"letsignature_of_cmifilename=(Cmi_format.read_cmi(Filename.concatcompiler_libsfilename)).cmi_signletast_module_name=letmajor,minor=Metapp.ast_versioninPrintf.sprintf"OCaml_%d%.2d"majorminorletppxlib_signature=Option.get(find_module"Ast"(Option.get(find_moduleast_module_name(signature_of_cmi"ppxlib_ast__Versions.cmi"))))]moduletypeMapperS=sigvalmapper:mapperendmoduleDefaultMap=structletmapper={expression=Fun.id;pattern=Fun.id}endmoduleStringMap=Map.Make(String)moduleMake(Target:QuoteValueS)=structmoduleQuoter(Mapper:MapperS)=structtypesubst={ty:string;target:Target.t;}exceptionSubstofsubstletlist_counter=ref0letsubst_of_value_binding(binding:Ppxlib.value_binding):string*subst=matchbindingwith|{pvb_pat={ppat_desc=Ppat_constraint({ppat_desc=Ppat_var{txt=identifier;_}|Ppat_construct({txt=Lidentidentifier;_},None)},{ptyp_desc=Ptyp_constr({txt=Lidentty;_},[])|Ptyp_poly(_,{ptyp_desc=Ptyp_constr({txt=Lidentty;_},[])})})};pvb_expr=expr}->letexpr=matchexprwith|{pexp_desc=Pexp_constraint(expr,_);_}->expr|_->exprinidentifier,{ty;target=Target.subst_of_exprexpr}|{pvb_loc;_}->Location.raise_errorf~loc:pvb_loc"Typed value-binding expected"letparse_subst(subst:Ppxlib.attribute):substStringMap.t=matchMetapp.Stri.of_payload(Metapp.Attr.payloadsubst)with|{pstr_desc=Pstr_value(Nonrecursive,values)}->List.mapsubst_of_value_bindingvalues|>List.to_seq|>StringMap.of_seq|{pstr_loc;_}->Location.raise_errorf~loc:pstr_loc"Let-binding expected"letunit?subst?in_list=Target.of_unitletstring?subst?in_list=Target.of_stringletchar?subst?in_list=Target.of_charletlocation?subst?in_list=Target.quote_locationletlocation_stack?subst?in_list=Target.quote_location_stackletbool?subst?in_list=Target.of_boolletlongident?(subst=StringMap.empty)?in_list(l:Longident.t)=trymatchmatchlwith|Lidents->StringMap.find_optssubst|_->Nonewith|None->Target.of_longidentl|Somesubst->raise(Substsubst)withSubst{ty="longident";target}->targetletlist?(subst=StringMap.empty)?in_list(f:subst:substStringMap.t->?in_list:stringlistref->'a->Target.t)(l:'alist):Target.t=trymatchTarget.is_exprwith|None->Target.list(List.map(f~subst?in_list)l)|SomeRefl->letl=l|>List.map(funitem->letin_list=ref[]inletitem=f~subst~in_listiteminmatch!in_listwith|[]->Target.list[item]|lists->letitem:Ppxlib.expression=letloc=!Ppxlib.Ast_helper.default_locin[%exprletexceptionEnd_of_listinletrecloopaccu=match[%eitem]with|exceptionEnd_of_list->List.revaccu|item->loop(item::accu)inloop[]]inList.fold_left(funitemlist:Ppxlib.expression->letloc=!Ppxlib.Ast_helper.default_locin[%exprlet[%pMetapp.Pat.varlist]=refNonein[%eitem]])itemlists)inletloc=!Ppxlib.Ast_helper.default_locin[%exprList.concat[%eTarget.listl]]withSubst{ty="list";target}->targetletoption?subst?in_list(quote_value:'a->Target.t)(option:'aoption):Target.t=tryTarget.option(Option.mapquote_valueoption)withSubst{ty="option";target}->target[%%metaquote_of_sig(funnames->not(List.mem"constant"names))asttypes(Option.get(find_module"Asttypes"ppxlib_signature))](* redefined here after constants, because we do not want substitutions on
string constants. *)letstring?(subst=StringMap.empty)?in_list(s:string)=trymatchStringMap.find_optssubstwith|None->Target.of_strings|Somesubst->raise(Substsubst)withSubst{ty="string";target}->target[%%meta