On this page:
9.1 Name Roots
name-root
name-root-proc
prop:  name-root
name-root?
name-root-ref
9.2 Operators
operator
prefix-operator
prefix-operator-ref
infix-operator
infix-operator-ref
9.3 Parameterized Enforestation
define-enforest
9.4 Prefix Transformers
transformer
transformer-ref
define-transform
8.13.0.7

9 Enforestation API🔗

9.1 Name Roots🔗

 (require enforest/name-root) package: rhombus-prototype

procedure

(name-root proc)  name-root?

  proc : procedure?
Returns an implementation of prop:name-root with a function that results in the structure instance itself.

The transformer procedure proc takes an introducer funciton and a syntax list of terms and returns two values: a new head identifier or operator, and a syntax list of remaining terms. The introducer function corresponds to the space that is otherwise used to lookup identifiers, which the transformer procedure might take into account.

procedure

(name-root-proc v)  procedure?

  v : any/c
Extracts the transformer procedure from v, which must be an instance of name-root.

A structure type property whose value must be a function that takes a structure implementing the property and returns an instance of name-root.

procedure

(name-root? v)  boolean?

  v : any/c
Returns #t if v implements prop:name-root, #f otherwise.

procedure

(name-root-ref v)  any/c

  v : any/c
Returns an instance of name-root if v implements prop:name-root, #f otherwise.

9.2 Operators🔗

 (require enforest/operator) package: rhombus-prototype

struct

(struct operator (name precs protocol proc))

  name : identifier?
  precs : 
(listof (cons/c (or/c identifier? 'default)
                (or/c 'stronger 'weaker
                      'same 'same-on-left 'same-on-right)))
  protocol : (or/c 'macro 'automatic)
  proc : procedure?
The name identifier is the name of the operator.

The precs list is an association list from identifiers to 'stronger, 'weaker, 'same, 'same-on-left, or 'same-on-right, indicating that the operator’s precedence is stronger than, weaker than, or the same as (when on the indicated side of) the associated identifier; 'default can be used instead of an identifier to specify a default relationship.

The protocol is either 'macro for macro protocol or 'auto for automatic protocol.

The proc transformer procedure depends on the mode (prefix or infix) as well as the protocol for its arguments and results.

This structure type should not be used directly. Instead, use its subtypes prefix-operator and infix-operator.

If the protocol is 'macro, proc takes a syntax list of terms consisting of all remaining terms (including the operator term) in the enclosing group and returns two values: a parsed form, and a syntax list of remaining terms.

If the protocol is 'auto, proc takes two arguments: a parsed right-hand form and the operator name, and returns a further parsed form.

procedure

(prefix-operator-ref v)  any/c

  v : any/c
Returns v if it is an instance of prefix-operator, #f otherwise.

struct

(struct infix-operator operator (assoc))

  assoc : (or/c 'left 'right 'none)
The assoc is either 'left for left-associativity, 'right for right-associativity, or 'none for non-associativity.

If the protocol is 'macro, proc takes two arguments: a parsed left-hand form and a syntax list of terms consisting of all remaining terms (including the operator term) in the enclosing group, and returns two values: a parsed form, and a syntax list of remaining terms.

If the protocol is 'auto, proc takes three arguments: a parsed left-hand form, a parsed right-hand form, and the operator name, and returns a further parsed form.

procedure

(infix-operator-ref v)  any/c

  v : any/c
Returns v if it is an instance of infix-operator, #f otherwise.

9.3 Parameterized Enforestation🔗

 (require enforest) package: rhombus-prototype

syntax

(define-enforest option ...)

 
option = #:enforest enforest
  | #:enforest-step enforest-step
  | #:syntax-class syntax-class
  | #:relative-precedence relative-precedence
  | #:prefix-more-syntax-class prefix-more-syntax-class
  | #:infix-more-syntax-class infix-more-syntax-class
  | #:desc desc
  | #:operator-desc operator-desc
  | #:parsed-tag parsed-tag
  | #:in-space in-space
  | #:prefix-operator-ref prefix-operator-ref
  | #:infix-operator-ref infix-operator-ref
  | #:name-path-op name-path-op
  | #:name-root-ref name-root-ref
  | #:in-name-root-space in-name-root-space
  | #:check-result check-result
  | #:make-identifier-form make-identifier-form
  | #:make-operator-form make-operator-form
  | #:juxtapose-implicit-name juxtapose-implicit-name
  | #:select-implicit-prefix select-implicit-prefix
  | #:select-implicit-infix select-implicit-infix
  | #:track-origin track-origin
  | #:use-site-scopes? use-site-scopes?
  | #:lookup-space-description lookup-space-description
The enforest name (defaulting to a fresh name) is bound to an enforest function, which is used to start enforestation of a group. It takes a syntax list of S-expressions for parsed shrubberies in a group and returns a parsed form. The enforest function drives a loop that calls the enforest-step function.

The enforest-step name (defaulting to a fresh name) is bound to an enforest-step function that continues an enforestation. It takes two arguments: a syntax list of all remaining terms in a group and the current operator, and returns two values: a parsed form and a syntax list of remaining terms (starting with an infix operator that has lower precedence than the input operator).

The syntax-class is a name (defaulting to a fresh name) or a parenthesized name with arguments. The name is bound to a syntax class (see define-syntax-class) that matches and enforests a group shrubbery representation, and an error is reported if a match is attempted but fails. A match has a parsed attribute for the enforestation result. If syntax-class is a parenthesized name with arguments, then each argument is also passed along to a prefix or infix operator after all other arguments (which vary, depending on the protocol).

The relative-precedence name, if present, is bound to a function that compares the precedence of two operators. The function takes four arguments: 'infix or 'prefix for the left operator’s mode, the left operator’s identifier, 'infix or 'prefix for the right operator’s mode, and the right operator’s identifier. The result is either 'stronger (left takes precedence), 'weaker (right takes precedence), or an error result: #f (no precedence relation), 'inconsistent-prec (inconsistent precedence), 'inconsistent-assoc (inconsistent associativity), 'same (same precedence but non-associativity), 'same-on-left (same precedence but on the wrong side), 'unbound (one of the operators is unbound).

The prefix-more-syntax-class and infix-more-syntax-class names (defaulting to fresh names) are bound to syntax classes that take an operator-name argument, and match and enforest a group that’s intended to represent the tail of a group. The enforestation is based on the precedence and associatvity of the given operator. A match has a parsed attribute for the enforestation result and a tail attribute for the remaining terms in a group. If syntax-class is a parenthesized name with arguments, then prefix-more-syntax-class and infix-more-syntax-class accept those additional arguments, too, after the operator-name argument.

The desc (defaulting to "form") and operator-desc (defaulting to "operator") strings are used in error reporting to refer to a form or an operator for a form.

The parsed-tag value, which typically a quoted symbol or a keyword, is recognized in a 'parsed form to detect already-parsed forms that are not enforested further.

The in-space function (defaulting to the identity function) takes an identifier syntax object and adds a space scope if the enforesting context uses a space.

The prefix-operator-ref (defaulting to prefix-operator-ref) and infix-operator-ref (defaulting to infix-operator-ref) functions take a compile-time value and extract an instance of prefix-operator or infix-operator, respectively, if the value has one suitable for the context, returning #f otherwise. Normally, these functions use structure-property accessors.

The name-path-op symbol (defaulting to '|.|) is an operator name that is (symbolically) recognized after a name-root identifier for hierarhical name references.

The name-root-ref function (defaulting to name-root-ref) takes a compile-time value and extracts an instance of name-root. The compile-time value is resolved from an identifier that is followed by an operator recognized by name-path-op.

The in-name-root-space function is analogous to in-space, but applied to an identifier before searching for a name resolver using name-root-ref.

The check-result function (defaulting to a function that checks whether its first argument is a syntax object, returning it as-is if so, raising an exception otherwise) takes an enforestation result and checks whether the result is suitable for the context. It should either raise an exception for earlier detection of errors or return its first argument (possibly adjusted). A second argument to the function is the procedure that produced the result, which can be used for error reporting (e.g., through object-name). If syntax-class is a parenthesized name with arguments, then check-result receives those arguments, too, after all others.

The make-identifier-form function (defaulting to the identity function) takes an identifier an produces a suitable parsed form. If a context does not have a meaning for unbound identifiers, a syntax error can be reported. If syntax-class is a parenthesized name with arguments, then make-identifier-form receives those arguments, too, after all others.

The make-operator-form function, if non-#f, takes an operator and produces a suitable parsed form. Absence or #f means that an error is reported for an unbound operator in an expression position.

The juxtapose-implicit-name symbol (defaulting to '#%juxtapose as described in Implicit Operators) is the name for the implicit infix operator between two immediately adjacent expressions.

The select-implicit-prefix function (defaulting to a function that selects implicit prefix operators as described in Implicit Operators) takes a term within a group that is not an operator and does not follow an infix operator. The result should be two values: a symbol as the name for the implicit prefix operator and a syntax object whose lexical context is added to the symbol to look up the operator binding.

The select-implicit-infix function (defaulting to a function that selects implicit infix operators as described in Implicit Operators) takes a term within a group that is not an operator and follows a parsed term. The result should be two values: a symbol as the name for the implicit infix operator and a syntax object whose lexical context is added to the symbol to look up the operator binding.

The track-origin function is used to track expansion via prefix and infix operators. It defaults to syntax-track-origin.

The use-site-scopes? value configures whether expansion process via prefix and infix operators should introduce use-site scopes. See also syntax-local-apply-transformer. The default is #f to not introduce use-site scopes.

The lookup-space-description function is used when reporting a syntax error due to an unbound identifier or operator. The function is called with a symbol representing an interned scope, and if the result is not #f, it is used as a description of the binding space. The default always returns #f.

9.4 Prefix Transformers🔗

 (require enforest/transformer) package: rhombus-prototype

struct

(struct transformer (proc))

  proc : procedure?
The proc transformer procedure takes a syntax list of all terms (including the resolved name) in a group and returns a parsed term.

procedure

(transformer-ref v)  any/c

  v : any/c
Returns v if it is an instance of transformer, #f otherwise.

syntax

(define-transform option ...)

 
option = #:syntax-class syntax-class
  | #:desc desc
  | #:transform transform
  | #:predicate predicate
  | #:transformer-ref transformer-ref
  | #:name-path-op name-path-op
  | #:name-root-ref name-root-ref
  | #:in-name-root-space in-name-root-space
  | #:check-result check-result
  | #:track-origin track-origin
  | #:use-site-scopes? use-site-scopes?
The syntax-class is a name (defaulting to a fresh name) or a parenthesized name with arguments. The name is bound to a syntax class that matches and parses a group shrubbery representation, but unlike a syntax class introduced with define-enforest, the match can fail without triggering an error. A match has a parsed attribute for the parsed result. If syntax-class is a parenthesized name with arguments, then each argument is also passed along to a transformer after the syntax argument.

The desc string (defaulting to "form") is used in error reporting to refer to a form.

The transformer-ref function (defaulting to transformer-ref) takes a compile-time value and extracts an instance of transformer, if the value has one suitable for the context, returning #f otherwise. Normally, this function uses a structure-property accessor.

If transform is not #f, it is bound to a function that takes syntax and parses it using syntax-class. The default is #f.

If predicate is not #f, it is bound to a function that takes syntax and reports whether the form starts with an identifier that is bound as a transformer. The default is #f.

See define-enforest for the meanings of desc, name-path-op, name-root-ref, in-name-root-space, check-result, track-origin, and use-site-scopes?.