On this page:
bind
bind_  meta.space
bind.macro
bind_  meta.pack
bind_  meta.unpack
bind.infoer
bind_  meta.pack_  info
bind_  meta.unpack_  info
bind_  meta.get_  info
bind_  meta.is_  immediate
bind.matcher
bind.committer
bind.binder
bind_  meta.Parsed
bind_  meta.After  Prefix  Parsed
bind_  meta.After  Infix  Parsed
bind_  meta.Argument
bind_  meta.Result
8.12

7.8 Binding Macros🔗ℹ

space

bind

The space for bindings of identifiers and operators that can be used in binding positions such as the left-hand side of def or the formal arguments of fun.

Provided as meta.

A compile-time value that identifies the same space as bind. See also SpaceMeta.

Like expr.macro, but defines an identifier or operator as a binding form in the bind space. The result of the macro expansion can be a low-level binding description created with bind_meta.pack.

bind.macro 'many $ann as $id':

  '$id && [_ :: $ann, $('...')]'

> def many Int as tickets = [1, 2, 3]

> tickets

[1, 2, 3]

> def many String as names = "oops"

def: value does not satisfy annotation

  value: "oops"

  annotation: matching(List((_ :: String), ...))

See Binding Low-Level Protocol for examples using the low-level protocol.

function

fun bind_meta.pack(stx :: Syntax) :: Syntax

Provided as meta.

Packs binding information that is represented by a syntax object with two parts: infoer_id and data, combined in the form

'(infoer_id, data)'

The infoer_id identifier must be bound to a transformer with bind.infoer, and data is propagated to that transformer to get initial binding information and further “continuations” for generating matching and variable-defining forms.

The representation of packed information as a syntax object is unspecified and meant to be opaque.

See Binding Low-Level Protocol for more explanation and for examples.

Provided as meta.

The inverse of bind_meta.pack, normally used only internally in the expander.

Defines id as the infoer “continuation” of a binding macro’s implementation. The inforer is invoked with “upward” static information provided by the context of a use of the binding form, plus the same data syntax object that was supplied as part of the argument to bind_meta.pack. The transformer’s result is automatically packed via bind_meta.pack_info, so it should be a syntax object that is suitable to pack—which means that it encodes information about identifiers to be bound as well as further “continuations” in the form of a matcher transformer defined with bind.matcher, a committer transformer defined with bind.committer, and binder transformer defined with bind.binder.

See Binding Low-Level Protocol for more explanation and for examples.

Provided as meta.

Packs binding information that specific to a use of a binding form, which means that “upward” has been provided to an infoer, and the infoer converts that to initial information about bindings plus “continuations” to generate the matching expression and variable definitions.

The syntax object stx must have the following shape:

'(ann_string,

  name_id,

  ((static_key, static_value), ...),

  ((defined_id,

    [var_use, ...],

    ((var_static_key, var_static_value), ...)),

   ...),

  matcher_id,

  committer_id,

  binder_id,

  data)'

The ann_string term is for error repoting when a value fails to match the binding. It describes the binder’s match requires in the form of an annotation.

The name_id term is for error reporting and reflection in the sense that it is used as the inferred name for a value matched to the binder, in case such a name is relevant.

The static_keystatic_value pairs describe “upward” static information for anything that successfully matches the binding. The “upward” information can be useful to an enclosing binding form.

The defined_ids are the identifiers that are ultimately bound by the binding form. Each identifier to be defined has associated uses through var_use values, and each identifier has “downward” static information through the var_static_keyvar_static_value pairs. Like var_static_keys, the meaning of var_uses is up to cooperating parts in general, but two values are recognized by built-in forms:

The matcher_id, committer_id, and binder_id identifiers provide the “continuation” of the binder’s expansion to generate a matching expression and a definition sequence.

The data term is propoagated to the use of matcher_id, committer_id, and binder_id, providing a communication channel from an infoer to a matcher and binder.

The representation of packed information as a syntax object is unspecified and meant to be opaque.

See Binding Low-Level Protocol for more explanation and for examples.

Provided as meta.

The inverse of bind_meta.pack_info, which is useful for unpacking information about the expansion of nested binding forms as produced by bind_meta.get_info.

function

fun bind_meta.get_info(bind_stx :: Syntax,

                       static_info :: Syntax)

  :: Syntax

Provided as meta.

Initiates the expansion of the binding form represented by bind_stx in a context that supplies thet “upward” static information represented by static_info.

Static information is represented by a syntax object that has the following shape:

'((key_id, val), ...)'

The result is a syntax object that represents the initial expansion of the binding form as a packed syntax object, whose form is unspecified and intended to be opaque. Use bind_meta.unpack_info to convert the packed syntax object and expose information about the binding’s expansion.

See Binding Low-Level Protocol for an example.

Provided as meta.

Takes the initialized binding-form expansion produced by bind_meta.get_info and restports whether the binding is immediate in the same sense as just a variable: the binding always matches, and no work is required to convert or unpack the matched value.

definition

bind.matcher 'id(id_pattern, data_pattern,

                  IF_pattern, success_pattern, fail_pattern)':

  body

  ...

Defines id as the matcher “continuation” of a binding form’s expansion. The result is an expression that inspects the value of the identifier matched to id_pattern and uses the pieces matched by IF_pattern, success_pattern, and fail_pattern to dispatch on match success or failure. The term matched to data_pattern is whatever data the infoer included at the end of its result.

When using a matcher unpacked via bind_meta.unpack_info, the group given for success_pattern can be an immediate block formed with : (without a preceding term), and in that case, the groups of the block are spliced into a definition context where the binding is used.

See Binding Low-Level Protocol for more explanation and for examples.

definition

bind.committer 'id(id_pattern, data_pattern)':

  body

  ...

Defines id as the committer “continuation” of a binding form’s expansion. The result is an sequence of definitions for intermediate variables, where id_pattern holds the value that was matched by a matcher. If the matcher included any additional bindings around the success branch, then those bindings are in the environment of the definitions generated by this binder. The term matched to data_pattern is whatever data the infoer included at the end of its result.

The definitions produced by a committer should not use identifiers supplied by a user of the binding form, because those names will not be adjusted by let. Instead, those definitions should be deferred to the binder function’s result.

See Binding Low-Level Protocol for more explanation and for examples.

definition

bind.binder 'id(id_pattern, data_pattern)':

  body

  ...

Defines id as the binder “continuation” of a binding form’s expansion. The result is an sequence of definitions for the variables that are bound by the expander form, where id_pattern holds the value that was matched by a matcher. If the matcher included any additional bindings around the success branch, then those bindings are in the environment of the definitions generated by this binder, and any intermediate definitions from the commiitter are also in the environment. The term matched to data_pattern is whatever data the infoer included at the end of its result.

The definitions produced by a binder should not refer to each other, because they may be adjusted by let expansion. Bindings that need to be referenced by generated bindings should be in the committer function’s output.

See Binding Low-Level Protocol for more explanation and for examples.

syntax class

syntax_class bind_meta.Parsed:

  kind: ~group

  fields:

    group

 

syntax class

syntax_class bind_meta.AfterPrefixParsed(op_name):

  kind: ~group

  fields:

    group

    [tail, ...]

 

syntax class

syntax_class bind_meta.AfterInfixParsed(op_name):

  kind: ~group

  fields:

    group

    [tail, ...]

Provided as meta.

Analogous to expr_meta.Parsed, etc., but for bindings.

syntax class

syntax_class bind_meta.Argument:

  kind: ~group

  fields:

    parsed

    maybe_keyword

    maybe_expr

Provided as meta.

Matches forms that combine a binding with an optional kyword and optional default-value expression, like bind_maybe_kw_opt for fun.

syntax class

syntax_class bind_meta.Result:

  kind: ~sequence

  fields:

    count

    is_predicate

    maybe_converter

    static_info

    annotation_string

Provided as meta.

Matches a sequence of terms (possibly empty) for a result annotation, like maybe_res_annot for fun.