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:
- Syntax Model
- Syntax Objects,
especially
datum->syntaxandsyntax-e(which Fusion callssyntax_unwrap). - Syntax Quoting
- Expanding Top-Level Forms
Limitations
Here’s some notable things missing from Fusion’s current macro system compared to Racket:
- There’s only one expansion phase, which primarily means one must generally import a macro from another module before using it.
- Not all expansion contexts are implemented. There’s no internal definitions yet; see issue #67.
- Tamper status (aka tainting) is not implemented.
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.
Exported Bindings
bound_identifier_equalcheck_duplicate_identifierdatum_to_syntaxdefine_syntaxexpand_oncefree_identifier_equalis_identifieris_syntaxquasisyntaxquote_syntaxsyntax_appendsyntax_columnsyntax_cons_qsyntax_getsyntax_is_originalsyntax_linesyntax_originsyntax_propertysyntax_sizesyntax_subseqsyntax_to_datumsyntax_track_originsyntax_unwrapunsyntaxwrong_syntax
(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 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 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 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 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 identifier1 identifier2)
Compares two identifiers to determine whether they both refer to the same binding.
(is_identifier value)
Determines whether a value is a syntax object holding a symbol, returning
true or false.
(is_syntax value)
Determines whether a value is a syntax object, returning true or false.
(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 datum)
Returns a syntax object retaining the lexical information of datum.
(syntax_append front back ...)
Returns a new syntax sexp that combines the front and back syntax
sequences.
(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_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_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 stx)
DEPRECATED as of FusionJava R23
(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 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 syntax)
Given a syntax object, removes the lexical information and returns a plain
value, unwrapping all layers recursively.
(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 syntax)
Given a syntax object, removes the lexical information and returns a plain
value. This only unwraps one layer, retaining inner syntax objects.
(unsyntax expr)
Used as an escape within a quasisyntax form; not valid in any other context.
(wrong_syntax stx message ...)
Raises a syntax error located at the given stx syntax. The messages are
displayed as part of the error.