r7rs-small-texinfo

Unnamed repository; edit this file 'description' to name the repository.
git clone https://kaka.farm/~git/r7rs-small-texinfo
Log | Files | Refs

commit 7838ef12db91f94552c87484172ffe323028312c
parent 054dc6c0d009b6ffd3c972f9bfc020882fc91109
Author: Wolfgang Corcoran-Mathe <wcm@sigwinch.xyz>
Date:   Thu,  1 Feb 2024 15:20:54 -0500

Restore macros section.

Diffstat:
Adoc/r7rs-small/macros.texinfo | 302++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
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