Ast_builder.DefaultSourceWe expose the types within the specific Ast_builder.S modules because those modules are designed to be opened.
The modes that can go on function arguments or return types
type arrow_argument = {arg_label : Ppxlib_ast.Asttypes.arg_label;arg_mode : mode option;arg_type : Ppxlib_ast.Parsetree.core_type;}Function return types; a value of this type represents ... -> result_mode result_type.
The modalities that can go on constructor fields
type function_param_desc = Jane_syntax.N_ary_functions.function_param_desc = | Pparam_val of Ppxlib_ast.Asttypes.arg_label
* Ppxlib_ast.Parsetree.expression option
* Ppxlib_ast.Parsetree.patternIn Pparam_val (lbl, def, pat):
lbl is the parameter labeldef is the default argument for an optional parameterpat is the pattern that is matched against the argument. See comment on Parsetree.Pexp_fun for more detail.| Pparam_newtype of string Ppxlib_ast.Asttypes.loc
* Ppxlib_jane__.Jane_asttypes.const_jkind Location.loc optionPparam_newtype tv represents a locally abstract type argument (type tv)
This type corresponds to Parsetree.function_param added in #12236; see the comment below introducing function arity.
type function_param = Jane_syntax.N_ary_functions.function_param = {pparam_desc : function_param_desc;pparam_loc : Astlib.Location.t;}val ptyp_arrow :
loc:Astlib.Location.t ->
arrow_argument ->
arrow_result ->
Ppxlib_ast.Parsetree.core_typeConstruct an arrow type with the provided argument and result, including the types, modes, and argument label (if any).
val tarrow :
loc:Astlib.Location.t ->
arrow_argument list ->
arrow_result ->
Ppxlib_ast.Parsetree.core_typeConstruct a multi-argument arrow type with the provided arguments and result.
val tarrow_maybe :
loc:Astlib.Location.t ->
arrow_argument list ->
Ppxlib_ast.Parsetree.core_type ->
Ppxlib_ast.Parsetree.core_typeAs tarrow, but will return the result if the input list is empty rather than erroring; this means the result type cannot have a mode annotation.
Splits a possibly-mode-annotated function argument or result into a pair of its mode and the unannotated type. If the resulting mode is None, then the type is returned unchanged.
val pcstr_tuple :
loc:Astlib.Location.t ->
(modality option * Ppxlib_ast.Parsetree.core_type) list ->
Ppxlib_ast.Parsetree.constructor_argumentsConstruct a Pcstr_tuple, a representation for the contents of a tupled variant constructor, that attaches the provided modalities to each field.
val pcstr_record :
loc:Astlib.Location.t ->
(modality option * Ppxlib_ast.Parsetree.label_declaration) list ->
Ppxlib_ast.Parsetree.constructor_argumentsConstruct a Pcstr_record, a representation for the contents of a variant constructor with an inlined record, that attaches the provided modalities to each label.
val ptype_record :
loc:Astlib.Location.t ->
(modality option * Ppxlib_ast.Parsetree.label_declaration) list ->
Ppxlib_ast.Parsetree.type_kindConstruct a Ptype_record, a representation of a record type, that attaches the provided modalities to each label.
val get_tuple_field_modality :
Ppxlib_ast.Parsetree.core_type ->
modality option * Ppxlib_ast.Parsetree.core_typeSplits a possibly-modality-annotated field of a tupled variant constructor into a pair of its modality and the unannotated field. If the resulting mode is None, then the field is returned unchanged.
val get_label_declaration_modality :
Ppxlib_ast.Parsetree.label_declaration ->
modality option * Ppxlib_ast.Parsetree.label_declarationSplits a possibly-modality-annotated label declaration into a pair of its modality and the unannotated label declaration. If the resulting modality is None, then the label declaration is returned unchanged.
Many comments below make reference to the Jane Street compiler's treatment of function arity. These comments refer to a parsetree change made to upstream OCaml in https://github.com/ocaml/ocaml/pull/12236, but that Jane Street has mirrored internally already.
The treatment of arity can be summarized as follows:
fun x1 ... xn -> body construct, with some special allowances for function cases.Why is arity important? In native code, application sites of a function to n syntactic arguments will trigger a fast path (where arguments are passed in registers) only if the function's runtime arity is n.
As a result, ppxes must take more care than before to generate functions of the correct arity. Now, a nested function like fun x -> fun y -> e has arity 1 (returning still another function of arity 1) instead of arity 2. All bindings below that construct functions are documented as to the arity of the returned function.
Some examples of arity:
fun x y -> efun x -> fun y -> efun x y -> function P1 -> e1 | P2 -> e2fun x y -> (function P1 -> e1 | P2 -> e2)fun x -> function P1 -> function P2 -> eNotably, unparenthesized function has a special meaning when used as a direct body of fun: the function becomes part of the arity of the outer fun. The same does not apply for multiple nested functions, even if they each have a single case; the nested functions are treated as unary. (See the last example.)
val eabstract :
loc:Astlib.Location.t ->
?coalesce_fun_arity:bool ->
Ppxlib_ast.Parsetree.pattern list ->
Ppxlib_ast.Parsetree.expression ->
Ppxlib_ast.Parsetree.expressionCreate a function with unlabeled parameters and an expression body. Like Ppxlib.Ast_builder.eapply, but for constructing functions.
coalesce_fun_arity is relevant for the Jane Street compiler. By default, coalesce_fun_arity is true.
Suppose there is a call eabstract pats body ~coalesce_fun_arity
colaesce_fun_arity is true, the arity of the returned function is the same as the arity of: add_fun_params (List.map params ~f:(Fun.param Nolabel)) bodycoalesce_fun_arity is false, then the arity of the returned function is the length of pats.In other words, coalesce_fun_arity = true allows you to build up the arity of an already-constructed function rather than necessarily creating a new function.
val unary_function :
loc:Astlib.Location.t ->
?attrs:Ppxlib_ast.Parsetree.attributes ->
Ppxlib_ast.Parsetree.case list ->
Ppxlib_ast.Parsetree.expressionunary_function cases is function <cases>. When used with the Jane Street compiler, the function's runtime arity is 1, so the fast path for function application happens only when application sites of the resulting function receive 1 argument. To create a function with multiple argument that pattern-matches on the last one, use add_param or add_params to add more parameters. Alternatively, use pexp_function to provide all parameters at once.
The attributes of the resulting expression will be the attrs argument together with any attributes added by the Jane Street compiler.
val fun_param :
loc:Astlib.Location.t ->
Ppxlib_ast.Asttypes.arg_label ->
Ppxlib_ast.Parsetree.pattern ->
function_paramfun_param lbl pat is Pparam_val (lbl, None, pat). This gives a more self-documenting way of constructing the usual case: value parameters without optional argument defaults.
val add_fun_param :
loc:Astlib.Location.t ->
?attrs:Ppxlib_ast.Parsetree.attributes ->
Ppxlib_ast.Asttypes.arg_label ->
Ppxlib_ast.Parsetree.expression option ->
Ppxlib_ast.Parsetree.pattern ->
Ppxlib_ast.Parsetree.expression ->
Ppxlib_ast.Parsetree.expressionSay an expression is a "function" if it is a Pexp_fun or a Pexp_function. All functions have parameters and arity.
Suppose add_param lbl def pat e ==> e'. Then, letting param = Pparam_val (lbl, def, pat),
e is a function with arity n, then e' is a function with arity n+1. param is added at the outermost layer. For example, if e = fun <params> -> <body>, then e' = fun <param :: params> -> body. The attributes on the resulting expression will be the attrs argument together with any attributes already present on e.e is not a function, then e' is a function with arity 1, namely: fun <param> -> <e>. The attributes of the resulting expression will be the attrs argument together with any attributes added by the Jane Street compiler.val add_fun_params :
loc:Astlib.Location.t ->
?attrs:Ppxlib_ast.Parsetree.attributes ->
function_param list ->
Ppxlib_ast.Parsetree.expression ->
Ppxlib_ast.Parsetree.expressionadd_params params e is List.fold_right params ~init:e ~f:add_param. Note the fold_right: if e is fun <params'> -> <body>, then add_params params e is fun <params @ params'> -> <body>.
This operation is a no-op, except as interpreted by the Jane Street compiler. If e is a function with arity n with an expression body that itself is a function with arity m, then coalesce_fun_arity e is a function of arity n + m.
You should usually call coalesce_fun_arity on metaquot fun expressions whose body may be a function, e.g.:
coalesce_fun_arity [%expr fun x y -> [%e possibly_function]]