123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204open!ImportmoduletypeLoc=sigvalloc:Location.tendmoduletypeAdditional_helpers=sigtype'awith_locvaleint:(int->expression)with_locvalechar:(char->expression)with_locvalestring:(string->expression)with_locvalefloat:(string->expression)with_locvaleint32:(int32->expression)with_locvaleint64:(int64->expression)with_locvalenativeint:(nativeint->expression)with_locvalebool:(bool->expression)with_locvalpint:(int->pattern)with_locvalpchar:(char->pattern)with_locvalpstring:(string->pattern)with_locvalpfloat:(string->pattern)with_locvalpint32:(int32->pattern)with_locvalpint64:(int64->pattern)with_locvalpnativeint:(nativeint->pattern)with_locvalpbool:(bool->pattern)with_locvaleunit:expressionwith_locvalpunit:patternwith_locvalevar:(string->expression)with_loc(** [evar id] produces a [Pexp_ident _] expression, it parses its input so you
can pass any dot-separated identifier, for instance:
[evar ~loc "Foo.bar"]. *)valpvar:(string->pattern)with_locvaleapply:(expression->expressionlist->expression)with_loc(** Same as pexp_apply but without labels *)valeabstract:(patternlist->expression->expression)with_locvalesequence:(expressionlist->expression)with_locvalppat_tuple_opt:(patternlist->patternoption)with_locvalpexp_tuple_opt:(expressionlist->expressionoption)with_locvalpexp_fun:(arg_label->expressionoption->pattern->expression->expression)with_loc(** [pexp_fun] can be used to create function expressions. It will check if
the function's body is itself a function expression and if so it will
coalesce the arguments.
For example, if we have [pexp_fun Nolabel None (var "x") f] and [f] is
[fun y -> x + y] then the function expression returned will be
[fun x y -> x + y] and not [fun x -> y -> x + y]. However, it will be more
efficient to create maximum arity functions directly with
{! pexp_function}. *)valpexp_function:(function_paramlist->type_constraintoption->function_body->expression)with_locvalpexp_function_cases:(Import.cases->expression)with_loc(** [pexp_function_cases] builds an expression in the shape
[function C1 -> E1 | ...]. *)valpconstruct:constructor_declaration->patternoption->patternvaleconstruct:constructor_declaration->expressionoption->expressionvalelist_tail:(expressionlist->expression->expression)with_loc(** [elist_tail ~loc [expr1; expr2; expr3] expr_tail] produces the expression
[expr1::expr2::expr3::expr_tail]. *)valelist:(expressionlist->expression)with_loc(** [elist ~loc [expr1; expr2; expr3]] produces the list litteral expression
[[expr1; expr2; expr3]]. *)valplist_tail:(patternlist->pattern->pattern)with_loc(** [plist_tail ~loc [pat1; pat2; pat3] pat_tail] produces the pattern
[pat1::pat2::pat3::pat_tail]. *)valplist:(patternlist->pattern)with_loc(** [plist ~loc [pat1; pat2; pat3]] produces the list pattern
[[pat1; pat2; pat3]]. *)valvalue_binding:(pat:Import.pattern->expr:Import.expression->Import.value_binding)with_locvalpstr_value_list:loc:Location.t->Asttypes.rec_flag->value_bindinglist->structure_itemlist(** [pstr_value_list ~loc rf vbs] = [pstr_value ~loc rf vbs] if [vbs <> []],
[[]] otherwise. *)valnonrec_type_declaration:(name:stringLoc.t->params:(core_type*Asttypes.variance)list->cstrs:(core_type*core_type*Location.t)list->kind:type_kind->private_:Asttypes.private_flag->manifest:core_typeoption->type_declaration)with_loc[@@deprecated"[since 2016-10] use Nonrecursive on the P(str|sig)_type instead"]valunapplied_type_constr_conv:(Longident.tLoc.t->f:(string->string)->expression)with_loc(** [unapplied_type_constr_conv] is the standard way to map identifiers to
conversion fonctions, for preprocessor that creates values that follow the
structure of types. More precisely,
[path_conv path (sprintf "sexp_of_%s")] is:
- sexp_of_t if path is "t"
- A.B.sexp_of_foo if path is "A.B.foo"
- A.B.sexp_of_f__foo (module A1) (module A2) if path is
"A.B.F(A1)(A2).foo" [type_constr_conv] also applies it to a list of
expression, which both prevents the compiler from allocating useless
closures, and almost always what is needed, since type constructors are
always applied. *)valtype_constr_conv:(Longident.tLoc.t->f:(string->string)->expressionlist->expression)with_locvaleta_reduce:expression->expressionoption(** Tries to simplify [fun v1 v2 .. -> f v1 v2 ..] into [f]. Only works when
[f] is a path, not an arbitrary expression as that would change the
meaning of the code. This can be used either for cleaning up the generated
code, or to reduce allocation if [f] is a local variable (the compiler
won't optimize the allocation of the closure).
Eta-reduction can change the types/behavior in some corner cases that are
unlikely to show up in generated code:
- if [f] has optional arguments, eta-expanding [f] can drop them
- because labels commute, it can change the type of an expression: $ let f
~x y = x + y let f2 = fun x -> add x;; val f : x:int -> int -> int =
<fun> val f2 : int -> x:int -> int = <fun> In fact, if [f] does side
effects before receiving all its arguments, and if the eta-expansion is
partially applied, eta-reducing could change behavior.
[eta_reduce_if_possible_and_nonrec] is meant for the case where the
resulting expression is going to be bound in a potentially recursive
let-binding, where we have to keep the eta-expansion when [rec_flag] is
[Recursive] to avoid a compile error. *)valeta_reduce_if_possible:expression->expressionvaleta_reduce_if_possible_and_nonrec:expression->rec_flag:rec_flag->expression(** {2:future-asts Compat functions for future AST nodes}
The functions in this section provide a safe interface to generate AST
nodes that cannot be represented with Ppxlib's own AST but are available
with more recent versions of the compiler.
Note that producing such nodes will make the generated code incompatible
with compilers older than the feature you are trying to represent. Those
nodes also won't play nicely with the driver's default source output or if
printed as source using [Ppxlib.Pprintast]. You can use the
--use-compiler-pp flag of the driver to use your current compiler's AST to
source printers. *)valppat_effect:(pattern->pattern->pattern)with_loc(** Returns an encoded effect pattern as introduced in OCaml 5.3 *)valptyp_labeled_tuple:((stringoption*core_type)list->core_type)with_loc(** Returns an encoded labeled tuple type as introduced in OCaml 5.4. *)valpexp_labeled_tuple:((stringoption*expression)list->expression)with_loc(** Returns an encoded labeled tuple expression as introduced in OCaml 5.4. *)valppat_labeled_tuple:((stringoption*pattern)list->closed_flag->pattern)with_loc(** Returns an encoded labeled tuple pattern as introduced in OCaml 5.4. *)endmoduletypeLocated=sigtype'awith_loctype'at='aLoc.tvalloc:_t->Location.tvalmk:('a->'at)with_locvalmap:('a->'b)->'at->'btvalmap_lident:stringt->Longident.ttvallident:(string->Longident.tt)with_locendtype'awithout_location='atype'awith_location=loc:Location.t->'amoduletypeS=sigmoduleLocated:Locatedwithtype'awith_loc:='awithout_locationincludeAst_builder_generated.Intf_locatedincludeAdditional_helperswithtype'awith_loc:='awithout_locationend