~ chicken-core (chicken-5) dfa5c29a4941a7d6aad6980373c51c0df6ee4867
commit dfa5c29a4941a7d6aad6980373c51c0df6ee4867
Author: felix <felix@call-with-current-continuation.org>
AuthorDate: Sun Sep 26 22:12:03 2010 +0200
Commit: felix <felix@call-with-current-continuation.org>
CommitDate: Sun Sep 26 22:12:03 2010 +0200
use er-macro-transformer in er-macro examples (suggested by sjamaan)
diff --git a/manual/Macros b/manual/Macros
index 796e189a..858e1dbe 100644
--- a/manual/Macros
+++ b/manual/Macros
@@ -69,20 +69,22 @@ where symbols have all context-information removed.
=== Explicit renaming macros
The low-level macro facility that CHICKEN provides is called "explicit
-renaming" and allows writing hygienic or non-hygienic macros procedurally.
-When given a lambda-expression instead of a {{syntax-rules}} form,
+renaming" and allows writing hygienic or non-hygienic macros
+procedurally. When given a lambda-expression or the return value of
+the procedure {{er-macro-transformer}} (to be preferred for
+portability reasons) instead of a {{syntax-rules}} form,
{{define-syntax}} evaluates the procedure in a distinct expansion
-environment (initially having access to the exported identifiers
-of the {{scheme}} module). The procedure takes an expression and two
-other arguments and returns a transformed expression.
+environment (initially having access to the exported identifiers of
+the {{scheme}} module). The procedure takes an expression and two
+other arguments and returns a transformed expression.
-For example, the transformation
-procedure for a {{call}} macro such that
-{{(call proc arg ...)}} expands
-into {{(proc arg ...)}} can be written as
+For example, the transformation procedure for a {{call}} macro such
+that {{(call proc arg ...)}} expands into {{(proc arg ...)}} can be
+written as
- (lambda (exp rename compare)
- (cdr exp))
+ (er-macro-transformer
+ (lambda (exp rename compare)
+ (cdr exp)))
Expressions are represented as lists in the traditional manner,
except that identifiers are represented as special uninterned symbols.
@@ -93,25 +95,26 @@ representation of a fresh identifier that occurs nowhere else in the
program. For example, the transformation procedure for a simplified
version of the {{let}} macro might be written as
- (lambda (exp rename compare)
- (let ((vars (map car (cadr exp)))
- (inits (map cadr (cadr exp)))
- (body (cddr exp)))
- `((lambda ,vars ,@body)
- ,@inits)))
-
-This would not be hygienic, however. A
-hygienic {{let}} macro must rename the identifier {{lambda}} to protect it
-from being captured by a local binding. The renaming effectively
-creates a fresh alias for {{lambda}}, one that cannot be captured by
-any subsequent binding:
-
- (lambda (exp rename compare)
- (let ((vars (map car (cadr exp)))
- (inits (map cadr (cadr exp)))
- (body (cddr exp)))
- `((,(rename 'lambda) ,vars ,@body)
- ,@inits)))
+ (er-macro-transformer
+ (lambda (exp rename compare)
+ (let ((vars (map car (cadr exp)))
+ (inits (map cadr (cadr exp)))
+ (body (cddr exp)))
+ `((lambda ,vars ,@body)
+ ,@inits))))
+
+This would not be hygienic, however. A hygienic {{let}} macro must
+rename the identifier {{lambda}} to protect it from being captured by
+a local binding. The renaming effectively creates a fresh alias for
+{{lambda}}, one that cannot be captured by any subsequent binding:
+
+ (er-macro-transformer
+ (lambda (exp rename compare)
+ (let ((vars (map car (cadr exp)))
+ (inits (map cadr (cadr exp)))
+ (body (cddr exp)))
+ `((,(rename 'lambda) ,vars ,@body)
+ ,@inits))))
The expression returned by the transformation procedure will be
expanded in the syntactic environment obtained from the syntactic
@@ -136,20 +139,21 @@ transformed macro application. For example, the transformation
procedure for a simplified version of the {{cond}} macro can be written
as
- (lambda (exp rename compare)
- (let ((clauses (cdr exp)))
- (if (null? clauses)
- `(,(rename 'quote) unspecified)
- (let* ((first (car clauses))
- (rest (cdr clauses))
- (test (car first)))
- (cond ((and (symbol? test)
- (compare test (rename 'else)))
- `(,(rename 'begin) ,@(cdr first)))
- (else `(,(rename 'if)
- ,test
- (,(rename 'begin) ,@(cdr first))
- (,(r 'cond) ,@rest))))))))
+ (er-macro-transformer
+ (lambda (exp rename compare)
+ (let ((clauses (cdr exp)))
+ (if (null? clauses)
+ `(,(rename 'quote) unspecified)
+ (let* ((first (car clauses))
+ (rest (cdr clauses))
+ (test (car first)))
+ (cond ((and (symbol? test)
+ (compare test (rename 'else)))
+ `(,(rename 'begin) ,@(cdr first)))
+ (else `(,(rename 'if)
+ ,test
+ (,(rename 'begin) ,@(cdr first))
+ (,(r 'cond) ,@rest)))))))))
In this example the identifier {{else}} is renamed before being passed
to the comparison predicate, so the comparison will be true if and
@@ -170,11 +174,12 @@ references to {{exit}} in the body of the loop, so {{exit}} is not
renamed.
(define-syntax loop
- (lambda (x r c)
- (let ((body (cdr x)))
- `(,(r 'call-with-current-continuation)
- (,(r 'lambda) (exit)
- (,(r 'let) ,(r 'f) () ,@body (,(r 'f))))))))
+ (er-macro-transformer
+ (lambda (x r c)
+ (let ((body (cdr x)))
+ `(,(r 'call-with-current-continuation)
+ (,(r 'lambda) (exit)
+ (,(r 'let) ,(r 'f) () ,@body (,(r 'f)))))))))
Suppose a {{while}} macro is implemented using {{loop}}, with the intent
that {{exit}} may be used to escape from the {{while}} loop. The {{while}}
@@ -192,12 +197,13 @@ inserted by the {{loop}} macro. In other words, this {{while}} macro is
not hygienic. Like {{loop}}, it must be written using procedurally:
(define-syntax while
- (lambda (x r c)
- (let ((test (cadr x))
- (body (cddr x)))
- `(,(r 'loop)
- (,(r 'if) (,(r 'not) ,test) (exit #f))
- ,@body))))
+ (er-macro-transformer
+ (lambda (x r c)
+ (let ((test (cadr x))
+ (body (cddr x)))
+ `(,(r 'loop)
+ (,(r 'if) (,(r 'not) ,test) (exit #f))
+ ,@body)))))
Think about it: If we ''did'' rename {{exit}}, it would refer to an
{{exit}} procedure existing in the context of the macro's definition.
diff --git a/manual/Unit expand b/manual/Unit expand
index b9b6f41b..add35003 100644
--- a/manual/Unit expand
+++ b/manual/Unit expand
@@ -39,9 +39,14 @@ Signals an exception of the kind {{(exn syntax)}}. Otherwise identical to
<procedure>(er-macro-transformer TRANSFORMER)</procedure>
-This procedure does nothing and is available for writing low-level
-macros in a more portable fashion, without hard-coding the signature
-of a transformer procedure.
+Returns an explicit-renaming macro transformer procedure created from
+the procedural macro body {{TRANSFORMER}}, which is a procedure of
+three arguments.
+
+Implementation note: this procedure currently just returns its
+argument unchanged and is available for writing low-level macros in a
+more portable fashion, without hard-coding the signature of a
+transformer procedure.
==== ir-macro-transformer
Trap