123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351openPpxlibopenAst_builder.DefaultmoduleE=ExtensionmoduleA=Ast_patterntypequoted_attributes={quoted_attributes:attributes;(* The attributes that appear quoted, e.g. [@foo] in [%expr [%e e] [@foo]] *)field_name:string;(* The field name where attributes are stored for the kind of AST the quoted
attributes are placed on, e.g. pexp_attributes. *)}moduleMake(M:sigtyperesultvalannotate:result->core_type->resultvalcast:(* The instance of the [std_lifters] class being used. *)<attributes:attributes->result;typed:result->string->result;..>->extension->quoted_attributesoption->(* e.g. [expression]; the callee is responsible for calling
[self#typed ast type_name] on the AST to add a type annotation
that constrains its type.
*)type_name:string->resultvallocation:location->resultvallocation_stack:(location->result)optionvalattributes:(location->result)option(* This is called on the result of evaluating the lifter on an expression.
We special case some expressions internally to Jane Street to support syntactic
function arity. See the comment on the generated call to [coalesce_fun_arity]. *)valon_expression:expression->result->resultclassstd_lifters:location->[result]Ppxlib_traverse_builtins.std_liftersend)=structletliftloc=object(self)inherit[M.result]Ast_traverse.liftassuperinherit!M.std_lifterslocmethodtypedastname=letloc={locwithloc_ghost=true}inM.annotateast(ptyp_constr~loc{loc;txt=Ldot(Ldot(Lident"Ppxlib_ast","Ast"),name)}[])method!attributex=Attribute.mark_as_handled_manuallyx;super#attributexmethod!location_=M.locationlocmethod!attributesx=matchM.attributeswith|None->super#attributesx|Somef->assert_no_attributesx;flocmethod!location_stackx=matchM.location_stackwith|None->super#location_stackx|Somef->flocmethod!expressione=matche.pexp_descwith|Pexp_extension(({txt="e";_},_)asext)->letattributes={quoted_attributes=e.pexp_attributes;field_name="pexp_attributes";}inM.castselfext(Someattributes)~type_name:"expression"|_->M.on_expressione(super#expressione)method!patternp=matchp.ppat_descwith|Ppat_extension(({txt="p";_},_)asext)->letattributes={quoted_attributes=p.ppat_attributes;field_name="ppat_attributes";}inM.castselfext(Someattributes)~type_name:"pattern"|_->super#patternpmethod!core_typet=matcht.ptyp_descwith|Ptyp_extension(({txt="t";_},_)asext)->letattributes={quoted_attributes=t.ptyp_attributes;field_name="ptyp_attributes";}inM.castselfext(Someattributes)~type_name:"core_type"|_->super#core_typetmethod!module_exprm=matchm.pmod_descwith|Pmod_extension(({txt="m";_},_)asext)->letattributes={quoted_attributes=m.pmod_attributes;field_name="pmod_attributes";}inM.castselfext(Someattributes)~type_name:"module_expr"|_->super#module_exprmmethod!module_typem=matchm.pmty_descwith|Pmty_extension(({txt="m";_},_)asext)->letattributes={quoted_attributes=m.pmty_attributes;field_name="pmty_attributes";}inM.castselfext(Someattributes)~type_name:"module_type"|_->super#module_typemmethod!structure_itemi=matchi.pstr_descwith|Pstr_extension((({txt="i";_},_)asext),attrs)->assert_no_attributesattrs;M.castselfextNone~type_name:"structure_item"|_->super#structure_itemimethod!signature_itemi=matchi.psig_descwith|Psig_extension((({txt="i";_},_)asext),attrs)->assert_no_attributesattrs;M.castselfextNone~type_name:"signature_item"|_->super#signature_itemiendendmoduleExpr=Make(structtyperesult=expressionletlocationloc=evar~loc:{locwithloc_ghost=true}"loc"letlocation_stack=Noneletattributes=Noneclassstd_lifters=Ppxlib_metaquot_lifters.expression_liftersletannotateecore_type=pexp_constraint~loc:core_type.ptyp_locecore_type(* Append the quoted attributes to the attributes present on the
antiquoted construct. Take this as example:
[%expr [%e e] [@attr]]
Suppose e has pexp_attributes = [attr1]. Then the resulting attributes
are [ attr1; [@attr] ]. The decision to put outer attributes (here,
[@attr]) at the end of the list is consistent with other parts of ppxlib
that accumulate attributes.
*)letadd_quoted_attributesselfe{quoted_attributes;field_name}~type_name~loc=matchquoted_attributeswith|[]->self#typedetype_name|_::_->letloc={locwithloc_ghost=true}inletvar=gen_symbol~prefix:"_ppx_metaquot_helper_var"()inletvar_expr=pexp_ident~loc(Located.mk~loc(Lidentvar))inletfield_name=Located.mk~loc(Lidentfield_name)inletreified_attrs=self#attributesquoted_attributesin(* append arg1 arg2 = [%expr Stdlib.List.append [%e arg1] [%e arg2]] *)letappendarg1arg2=pexp_apply~loc(pexp_ident~loc(Located.mk~loc(Ldot(Ldot(Lident"Stdlib","List"),"append"))))[(Nolabel,arg1);(Nolabel,arg2)]in(*
Morally,
{[
let var = ([%expr e] : [%type: type_name]) in
{ var
with pexp_attributes = var.pexp_attributes @ [%e reified_attrs ]
}
]}
*)pexp_letNonrecursive~loc[value_binding~loc~pat:(ppat_var~loc(Located.mk~locvar))~expr:(self#typedetype_name);](pexp_record~loc[(field_name,append(pexp_field~locvar_exprfield_name)reified_attrs);](Somevar_expr))letcastselfextattrs~type_name=matchsndextwith|PStr[{pstr_desc=Pstr_eval(e,inner_attrs);_}]->(assert_no_attributesinner_attrs;matchattrswith|None->self#typedetype_name|Somequoted_attrs->add_quoted_attributesselfequoted_attrs~type_name~loc:(loc_of_extensionext))|_->pexp_extension~loc:(loc_of_extensionext)(Location.error_extensionf~loc:(loc_of_extensionext)"expression expected")(* In expressions, convert:
{[
[%expr fun P -> [%e y]]
]}
to:
{[
Ppxlib_jane.Ast_builder.Default.coalesce_fun_arity [%expr fun P -> [%e y]]
]}
and similarly with newtypes:
{[
[%expr fun (type a) -> [%e y]]
]}
In this example, this makes the arity of the resulting expression equal to
[1 + arity(y)] instead of [1].
This notion of "arity" is introduced in an internal Jane Street compiler change
and upstream in (most likely) OCaml 5.2.
*)leton_expression(input_expression:expression)(lifted:result)=matchinput_expression.pexp_descwith|Pexp_function_|Pexp_newtype_->letloc=input_expression.pexp_locinletfun_binding=Ldot(Ldot(Ldot(Lident"Ppxlib_jane","Ast_builder"),"Default"),"coalesce_fun_arity")inpexp_apply~loc(pexp_ident~loc{txt=fun_binding;loc})[Nolabel,lifted]|_->liftedend)modulePatt=Make(structtyperesult=patternletlocationloc=ppat_any~loc:{locwithloc_ghost=true}letlocation_stack=Some(funloc->ppat_any~loc:{locwithloc_ghost=true})letattributes=Some(funloc->ppat_any~loc:{locwithloc_ghost=true})classstd_lifters=Ppxlib_metaquot_lifters.pattern_liftersletannotatepcore_type=ppat_constraint~loc:core_type.ptyp_locpcore_typeletcastselfextattrs~type_name=matchsndextwith|PPat(p,None)->(matchattrswith|None->()|Some{quoted_attributes;field_name=_}->assert_no_attributesquoted_attributes);self#typedptype_name|PPat(_,Somee)->Ast_builder.Default.(ppat_extension~loc:e.pexp_loc(Location.error_extensionf~loc:e.pexp_loc"guard not expected here"))|_->Ast_builder.Default.(ppat_extension~loc:(loc_of_extensionext)(Location.error_extensionf~loc:(loc_of_extensionext)"pattern expected"))leton_expression_pat=patend)let()=letextensionsctxlifter=[E.declare"metaquot.expr"ctxA.(single_expr_payload__)(fun~loc~path:_e->letlift=lifterlocinlift#typed(lift#expressione)"expression");E.declare"metaquot.pat"ctxA.(ppat__none)(fun~loc~path:_p->letlift=lifterlocinlift#typed(lift#patternp)"pattern");E.declare"metaquot.str"ctxA.(pstr__)(fun~loc~path:_s->letlift=lifterlocinlift#typed(lift#structures)"structure");E.declare"metaquot.stri"ctxA.(pstr(__^::nil))(fun~loc~path:_s->letlift=lifterlocinlift#typed(lift#structure_items)"structure_item");E.declare"metaquot.sig"ctxA.(psig__)(fun~loc~path:_s->letlift=lifterlocinlift#typed(lift#signatures)"signature");E.declare"metaquot.sigi"ctxA.(psig(signature(__^::nil)))(fun~loc~path:_s->letlift=lifterlocinlift#typed(lift#signature_items)"signature_item");E.declare"metaquot.sigil"ctxA.(psig(signature__))(fun~loc~path:_s->letlift=lifterlocinlift#typed(lift#signature_itemss)"signature_items");E.declare"metaquot.type"ctxA.(ptyp__)(fun~loc~path:_t->letlift=lifterlocinlift#typed(lift#core_typet)"core_type");]inletextensions=extensionsExpressionExpr.lift@extensionsPatternPatt.liftinDriver.register_transformation"metaquot"~extensions