Ion Fusion Documentation
Release 0.38a1-SNAPSHOT (2026-04-16T19:45:37.790Z)

Module /fusion/experimental/syntax

Experimental operators for macros and syntax manipulation.

WARNING

This module contains unstable, experimental features. There is NO SUPPORT for this module.

Overview

Fusion’s macro system is intended to be operationally identical to that of Racket, so we strongly recommend taking advantage of the extensive documentation Racket provides.

Fusion does not yet implement Racket's higher-level macro facilities like define-syntax-rule so one has to work with more primitive tools.

Fusion’s current feature-set generally aligns with the content of these parts of the Racket Guide:

To write low-level macros you'll want to be familiar with these parts of the Racket Reference:

Limitations

Here’s some notable things missing from Fusion’s current macro system compared to Racket:

These are the primary reasons this module is “experimental”. Of particular concern is that extant code may break when phases are introduced.

Internals

Fusion implements the lexical-context algorithms used by Racket 6.2 and earlier, which is best described by Matthew Flatt's paper, Composable and Compilable Macros.

Racket 6.3 introduced a new mechanism for tracking lexical context. Quoting the Racket Blog:

Racket’s macro expander uses a new representation of binding called “set of scopes”. The new binding model provides a simpler explanation of how macros preserve binding, especially across module boundaries and in hygiene-bending expansions. The new expander is mostly compatible with existing Racket macros, but there are some incompatibilities. For the formally inclined, a research paper on this macro system will appear at POPL next year: http://www.cs.utah.edu/plt/scope-sets/

We intend for Fusion to migrate to this algorithm, too, since it is significantly simpler to implement and easier to understand.

bound_identifier_equal procedure
(bound_identifier_equal id1 id2)

Compares two identifiers to determine whether id1 would bind id2 (or vice versa) if one were in a binding position and the other in a suitable reference position.

check_duplicate_identifier procedure
(check_duplicate_identifier ids)

Given a sexp of identifiers ids, compares each pair of identifiers with bound_identifier_equal. If any comparison returns true, the result is the first duplicate identifier (i.e., the first with a preceding match); otherwise the result is void.

datum_to_syntax procedure
(datum_to_syntax datum [context location])

Recursively converts the datum to a syntax object with lexical information copied from the context syntax identifier, and source-location copied from the location syntax object. Existing syntax objects in datum are included as-is.

When context isn't provided, converted syntax objects have no lexical context. When location isn't provided, they will have no location.

define_syntax syntax
(define_syntax id xform)

Binds the identifier ID to a syntax transformer XFORM. The transformer must be a procedure that accepts an syntax object and returns a syntax object.

expand_once procedure
(expand_once top_level_form)

Expands a top-level form through one step of macro expansion, using the bindings of the current namespace.

The top_level_form may be a syntax object or another datum.

free_identifier_equal procedure
(free_identifier_equal identifier1 identifier2)

Compares two identifiers to determine whether they both refer to the same binding.

is_identifier procedure
(is_identifier value)

Determines whether a value is a syntax object holding a symbol, returning true or false.

is_syntax procedure
(is_syntax value)

Determines whether a value is a syntax object, returning true or false.

quasisyntax syntax
(quasisyntax template)

Like quote_syntax, but the template datum may contain nested unsyntax forms that act as escapes. The unsyntaxed expression is evaluated when the containing quasisyntax is evaluated, and its result is inserted into the containing quoted datum.

As with unquote, unsyntax forms only escape one "level" of quasiquotation.

quote_syntax syntax
(quote_syntax datum)

Returns a syntax object retaining the lexical information of datum.

syntax_append procedure
(syntax_append front back ...)

Returns a new syntax sexp that combines the front and back syntax sequences.

syntax_column procedure
(syntax_column stx)

Returns the one-based column number of the source of a syntax object. The result is zero if there's no column number available.

syntax_cons_q
syntax_get procedure
(syntax_get container key ...)

Traverses down through syntax objects. container must be syntax container (struct, list, or sexp). Each key must be a string, symbol, or int, to denote either a struct's field-name or a sequence's index.

syntax_is_original
syntax_line procedure
(syntax_line stx)

Returns the one-based line number of the source of a syntax object. The result is zero if there's no line number available.

syntax_origin procedure
(syntax_origin stx)

DEPRECATED as of FusionJava R23

syntax_property
syntax_size procedure
(syntax_size sequence)

Returns the number of child elements contained in the syntax sequence. The size of null.list and null.sexp is zero.

syntax_subseq procedure
(syntax_subseq sequence from)

Returns a new syntax sexp that copies children from sequence starting at from. If from is beyond the end of the sequence, the result is an empty sequence.

syntax_to_datum procedure
(syntax_to_datum syntax)

Given a syntax object, removes the lexical information and returns a plain value, unwrapping all layers recursively.

syntax_track_origin procedure
(syntax_track_origin new_stx orig_stx origin)

Copies properties from orig_stx to new_stx and extending origin data with the origin identifier.

syntax_unwrap procedure
(syntax_unwrap syntax)

Given a syntax object, removes the lexical information and returns a plain value. This only unwraps one layer, retaining inner syntax objects.

unsyntax syntax
(unsyntax expr)

Used as an escape within a quasisyntax form; not valid in any other context.

wrong_syntax procedure
(wrong_syntax stx message ...)

Raises a syntax error located at the given stx syntax. The messages are displayed as part of the error.