commit 7838ef12db91f94552c87484172ffe323028312c
parent 054dc6c0d009b6ffd3c972f9bfc020882fc91109
Author: Wolfgang Corcoran-Mathe <wcm@sigwinch.xyz>
Date: Thu, 1 Feb 2024 15:20:54 -0500
Restore macros section.
Diffstat:
1 file changed, 302 insertions(+), 0 deletions(-)
diff --git a/doc/r7rs-small/macros.texinfo b/doc/r7rs-small/macros.texinfo
@@ -0,0 +1,302 @@
+@node Macros
+@section Macros
+
+Scheme programs can define and use new derived expression types, called
+macros.Program-defined expression types have the syntax
+
+(@svar{keyword} @svar{datum} ...)where @svar{keyword} is an identifier that uniquely determines the
+expression type. This identifier is called the syntactic keyword, or simply keyword, of the
+macro. The number of the @svar{datum}s, and their syntax, depends on the expression type.
+
+Each instance of a macro is called a useof the macro. The set of rules that specifies how a
+use of a macro is transcribed into a more primitive expression is called the transformerof
+the macro.
+
+The macro definition facility consists of two parts:
+
+* A set of expressions used to establish that certain identifiers are macro keywords,
+ associate them with macro transformers, and control the scope within which a macro
+ is defined, and
+
+* a pattern language for specifying macro transformers.
+
+The syntactic keyword of a macro can shadow variable bindings, and local variable
+bindings can shadow syntactic bindings. Two mechanisms are provided to prevent
+unintended conflicts:
+
+* If a macro transformer inserts a binding for an identifier (variable or keyword), the
+ identifier will in effect be renamed throughout its scope to avoid conflicts with other
+ identifiers. Note that a global variable definition may or may not introduce a binding;
+ see section 5.3.
+
+* If a macro transformer inserts a free reference to an identifier, the reference refers to
+ the binding that was visible where the transformer was specified, regardless of any
+ local bindings that surround the use of the macro.
+
+In consequence, all macros defined using the pattern language are ``hygienic'' and
+``referentially transparent'' and thus preserve Scheme's lexical scoping. [21, 22, 2, 9, 12]
+
+Implementations may provide macro facilities of other types.
+
+@menu
+* Binding constructs for syntactic keywords::
+* Pattern language::
+* Signaling errors in macro transformers::
+@end menu
+
+@node Binding constructs for syntactic keywords
+@subsection Binding constructs for syntactic keywords
+
+The let-syntax and letrec-syntax binding constructs are analogous to let and letrec, but
+they bind syntactic keywords to macro transformers instead of binding variables to
+locations that contain values. Syntactic keywords can also be bound globally or locally
+with define-syntax; see section 5.4.
+
+syntax: (let-syntax @svar{bindings} @svar{body})
+
+Syntax: @svar{Bindings} has the form
+
+((@svar{keyword} @svar{transformer spec}) @dots{})Each @svar{keyword} is an identifier, each <transformer
+spec> is an instance of syntax-rules, and @svar{body} is a sequence of zero or more
+definitions followed by one or more expressions. It is an error for a @svar{keyword} to
+appear more than once in the list of keywords being bound.
+
+Semantics: The @svar{body} is expanded in the syntactic environment obtained by extending
+the syntactic environment of the let-syntax expression with macros whose keywords are
+the @svar{keyword}s, bound to the specified transformers. Each binding of a @svar{keyword} has
+@svar{body} as its region.
+
+@example
+(let-syntax ((given-that (syntax-rules ()
+ ((given-that test stmt1 stmt2 ...)
+ (if test
+ (begin stmt1
+ stmt2 ...))))))
+ (let ((if #t))
+ (given-that if (set! if 'now))
+ if)) @result{} now
+
+(let ((x 'outer))
+ (let-syntax ((m (syntax-rules () ((m) x))))
+ (let ((x 'inner))
+ (m)))) @result{} outer
+@end example
+
+syntax: (letrec-syntax @svar{bindings} @svar{body})
+
+Syntax: Same as for let-syntax.
+
+Semantics: The @svar{body} is expanded in the syntactic environment obtained by extending
+the syntactic environment of the letrec-syntax expression with macros whose keywords
+are the @svar{keyword}s, bound to the specified transformers. Each binding of a @svar{keyword}
+has the @svar{transformer spec}s as well as the @svar{body} within its region, so the transformers
+can transcribe expressions into uses of the macros introduced by the letrec-syntax
+expression.
+
+@example
+(letrec-syntax
+ ((my-or (syntax-rules ()
+ ((my-or) #f)
+ ((my-or e) e)
+ ((my-or e1 e2 ...)
+ (let ((temp e1))
+ (if temp
+ temp
+ (my-or e2 ...)))))))
+ (let ((x #f)
+ (y 7)
+ (temp 8)
+ (let odd?)
+ (if even?))
+ (my-or x
+ (let temp)
+ (if y)
+ y))) @result{} 7
+@end example
+
+@node Pattern language
+@subsection Pattern language
+
+A @svar{transformer spec} has one of the following forms:
+
+syntax: (syntax-rules (@svar{pattern literal} @dots{})
+ @svar{syntax rule} @dots{})
+syntax: (syntax-rules @svar{ellipsis} (@svar{pattern literal} @dots{})
+ @svar{syntax rule} @dots{})
+auxiliary syntax: _
+auxiliary syntax: @dots{}
+
+Syntax: It is an error if any of the @svar{pattern literal}s, or the @svar{ellipsis} in the second form, is
+not an identifier. It is also an error if @svar{syntax rule} is not of the form
+
+(@svar{pattern} @svar{template})The @svar{pattern} in a @svar{syntax rule} is a list @svar{pattern} whose first
+element is an identifier.
+
+A @svar{pattern} is either an identifier, a constant, or one of the following
+
+(@svar{pattern} @dots{})
+(@svar{pattern} @svar{pattern} @dots{} . @svar{pattern})
+(@svar{pattern} @dots{} @svar{pattern} @svar{ellipsis} @svar{pattern} @dots{})
+(@svar{pattern} @dots{} @svar{pattern} @svar{ellipsis} @svar{pattern} @dots{}
+ . @svar{pattern})
+#(@svar{pattern} @dots{})
+#(@svar{pattern} @dots{} @svar{pattern} @svar{ellipsis} @svar{pattern} @dots{})and a @svar{template} is either an identifier, a
+constant, or one of the following (@svar{element} @dots{})
+(@svar{element} @svar{element} @dots{} . @svar{template})
+(@svar{ellipsis} @svar{template})
+#(@svar{element} @dots{})where an @svar{element} is a @svar{template} optionally followed by an @svar{ellipsis}.
+An @svar{ellipsis} is the identifier specified in the second form of syntax-rules, or the default
+identifier ... (three consecutive periods) otherwise.
+
+Semantics: An instance of syntax-rules produces a new macro transformer by specifying a
+sequence of hygienic rewrite rules. A use of a macro whose keyword is associated with a
+transformer specified by syntax-rules is matched against the patterns contained in the
+@svar{syntax rule}s, beginning with the leftmost @svar{syntax rule}. When a match is found, the
+macro use is transcribed hygienically according to the template.
+
+An identifier appearing within a @svar{pattern} can be an underscore (_), a literal identifier
+listed in the list of @svar{pattern literal}s, or the @svar{ellipsis}. All other identifiers appearing
+within a @svar{pattern} are pattern variables.
+
+The keyword at the beginning of the pattern in a @svar{syntax rule} is not involved in the
+matching and is considered neither a pattern variable nor a literal identifier.
+
+Pattern variables match arbitrary input elements and are used to refer to elements of
+the input in the template. It is an error for the same pattern variable to appear more
+than once in a @svar{pattern}.
+
+Underscores also match arbitrary input elements but are not pattern variables and so
+cannot be used to refer to those elements. If an underscore appears in the <pattern
+literal>s list, then that takes precedence and underscores in the @svar{pattern} match as
+literals. Multiple underscores can appear in a @svar{pattern}.
+
+Identifiers that appear in (@svar{pattern literal} @dots{}) are interpreted as literal identifiers to be
+matched against corresponding elements of the input. An element in the input matches
+a literal identifier if and only if it is an identifier and either both its occurrence in the
+macro expression and its occurrence in the macro definition have the same lexical
+binding, or the two identifiers are the same and both have no lexical binding.
+
+A subpattern followed by @svar{ellipsis} can match zero or more elements of the input,
+unless @svar{ellipsis} appears in the @svar{pattern literal}s, in which case it is matched as a literal.
+
+More formally, an input expression E matches a pattern P if and only if:
+
+* P is an underscore (_).
+
+* P is a non-literal identifier; or
+
+* P is a literal identifier and E is an identifier with the same binding; or
+
+* P is a list (P1 @dots{} Pn) and E is a list of n elements that match P1 through Pn, respectively;
+ or
+
+* P is an improper list (P1P2 @dots{} Pn . Pn+1) and E is a list or improper list of n or more
+ elements that match P1 through Pn, respectively, and whose nth tail matches Pn+1; or
+
+* P is of the form (P1 @dots{} PkPe @svar{ellipsis} Pm+1 @dots{} Pn) where E is a proper list of n elements,
+ the first k of which match P1 through Pk, respectively, whose next m−k elements each
+ match Pe, whose remaining n−m elements match Pm+1 through Pn; or
+
+* P is of the form (P1 @dots{} PkPe @svar{ellipsis} Pm+1 @dots{} Pn . Px) where E is a list or improper list of n
+ elements, the first k of which match P1 through Pk, whose next m−k elements each
+ match Pe, whose remaining n−m elements match Pm+1 through Pn, and whose nth and
+ final cdr matches Px; or
+
+* P is a vector of the form #(P1 @dots{} Pn) and E is a vector of n elements that match P1
+ through Pn; or
+
+* P is of the form #(P1 @dots{} PkPe @svar{ellipsis} Pm+1 @dots{}Pn) where E is a vector of n elements the
+ first k of which match P1 through Pk, whose next m−k elements each match Pe, and
+ whose remaining n−m elements match Pm+1 through Pn; or
+
+* P is a constant and E is equal to P in the sense of the equal? procedure.
+
+It is an error to use a macro keyword, within the scope of its binding, in an expression
+that does not match any of the patterns.
+
+When a macro use is transcribed according to the template of the matching <syntax
+rule>, pattern variables that occur in the template are replaced by the elements they
+match in the input. Pattern variables that occur in subpatterns followed by one or more
+instances of the identifier @svar{ellipsis} are allowed only in subtemplates that are followed
+by as many instances of @svar{ellipsis}. They are replaced in the output by all of the elements
+they match in the input, distributed as indicated. It is an error if the output cannot be
+built up as specified.
+
+Identifiers that appear in the template but are not pattern variables or the identifier
+@svar{ellipsis} are inserted into the output as literal identifiers. If a literal identifier is inserted
+as a free identifier then it refers to the binding of that identifier within whose scope the
+instance of syntax-rules appears. If a literal identifier is inserted as a bound identifier
+then it is in effect renamed to prevent inadvertent captures of free identifiers.
+
+A template of the form (@svar{ellipsis} @svar{template}) is identical to @svar{template}, except that
+ellipses within the template have no special meaning. That is, any ellipses contained
+within @svar{template} are treated as ordinary identifiers. In particular, the template
+(@svar{ellipsis} @svar{ellipsis}) produces a single @svar{ellipsis}. This allows syntactic abstractions to
+expand into code containing ellipses.
+
+@example
+(define-syntax be-like-begin
+ (syntax-rules ()
+ ((be-like-begin name)
+ (define-syntax name
+ (syntax-rules ()
+ ((name expr (... ...))
+ (begin expr (... ...))))))))
+
+(be-like-begin sequence)
+(sequence 1 2 3 4) @result{} 4
+@end example
+
+As an example, if let and cond are defined as in section 7.3 then
+they are hygienic (as required) and the following is not an error.
+
+@example
+(let ((=> #f))
+ (cond (#t => 'ok))) @result{} ok
+@end example
+
+The macro transformer for cond recognizes @code{=>} as a local
+variable, and hence an expression, and not as the base identifier
+@code{=>}, which the macro transformer treats as a syntactic
+keyword. Thus the example expands into
+
+@example
+(let ((=> #f))
+ (if #t (begin => 'ok)))
+@end example
+
+instead of
+
+@example
+(let ((=> #f))
+ (let ((temp #t))
+ (if temp ('ok temp))))
+@end example
+
+which would result in an invalid procedure call.
+
+@node Signaling errors in macro transformers
+@subsection Signaling errors in macro transformers
+
+syntax: (syntax-error @svar{message} @svar{args} @dots{})
+
+syntax-error behaves similarly to error (6.11) except that implementations with an
+expansion pass separate from evaluation should signal an error as soon as syntax-error
+is expanded. This can be used as a syntax-rules @svar{template} for a @svar{pattern} that is an
+invalid use of the macro, which can provide more descriptive error messages.
+@svar{message} is a string literal, and @svar{args} arbitrary expressions providing additional
+information. Applications cannot count on being able to catch syntax errors with
+exception handlers or guards.
+
+@example
+(define-syntax simple-let
+ (syntax-rules ()
+ ((_ (head ... ((x . y) val) . tail)
+ body1 body2 ...)
+ (syntax-error
+ "expected an identifier but got"
+ (x . y)))
+ ((_ ((name val) ...) body1 body2 ...)
+ ((lambda (name ...) body1 body2 ...)
+ val ...))))
+@end example