5 Zuo with Hygienic Macros
#lang zuo/hygienic |
The zuo/hygienic language provides the same set of bindings as zuo/base, but with hygienic macros. Its macro-expansion protocol uses a different representation of identifiers and binding scope, and different rules for quote-syntax and macros:
A zuo/hygienic term’s representation always uses identifier syntax objects in place of symbols. A macro will never receive a plain symbol in its input, and if the macro produces a term with plain symbol, it is automatically coerced to a syntax object using the scope of the module that defines the macro.
A syntax object’s context includes a set of scopes, instead of just one scope. Before expanding forms in a new context, a fresh scope representation is added to every identifier appearing within the context. An reference is resolved by finding the binding identifier with the most specific set of scopes that is a subset of the referencing identifier’s scopes.
In addition to binding contexts, a specific macro invocation is also represented by a scope: a fresh scope is added to every syntax object introduced by a macro expansion. This fresh scope means that an identifier introduced by the expansion can only bind identifiers that were introduced by the same expansion. Meanwhile, a quote-syntax-imposed scope on an introduced identifier prevents it from being bound by an identifier that’s at the macro-use site and not visible at the macro-definition site.
The quote-syntax form produces an identifier syntax object with all of its scope intact. That syntax object acquires additional scope if it is returned from a macro expander into a new context.
These differences particularly affect the functions that operate on syntax objects:
procedure
(identifier? v) → boolean?
v : any/c
procedure
v : identifier?
procedure
(syntax->datum v) → any/c
v : any/c
procedure
(datum->syntax ctx v) → any/c
ctx : identifier? v : any/c
procedure
(bound-identifier=? id1 id2) → boolean?
id1 : identifier? id2 : identifier?