~ chicken-core (chicken-5) b2b9030b6dc3628d7ea330ec3eb0062abeb41a0f
commit b2b9030b6dc3628d7ea330ec3eb0062abeb41a0f Author: felix <bunny351@gmail.com> AuthorDate: Fri May 28 09:42:51 2010 +0200 Commit: felix <bunny351@gmail.com> CommitDate: Fri May 28 09:42:51 2010 +0200 split modules-and-macros manual chapter (suggested by mario) diff --git a/manual/Declarations b/manual/Declarations index 3d1527ed..5115695b 100644 --- a/manual/Declarations +++ b/manual/Declarations @@ -388,6 +388,6 @@ are registered as features during compile-time, so {{cond-expand}} knows about them. --- -Previous: [[Modules and macros]] +Previous: [[Modules]] Next: [[Parameters]] diff --git a/manual/Getting started b/manual/Getting started index fe7f8326..5917c969 100644 --- a/manual/Getting started +++ b/manual/Getting started @@ -148,37 +148,7 @@ for C libraries ([[http://www.swig.org]]). This chapter provides you with an overview of the entire system, with enough information to get started writing and running small Scheme -programs. Subsequent chapters cover - -* [[Basic mode of operation]]: Compiling Scheme files. - -* [[Using the compiler]]: Explains how to use CHICKEN to compile - programs and execute them. - -* [[Using the interpreter]]: Invocation and usage of {{csi}}, the - CHICKEN interpreter - -* [[Supported language]]: The language implemented by CHICKEN - (deviations from the standard and extensions). - -* [[Interface to external functions and variables]]: Accessing C and - C++ code and data. - -* [[Extensions]]: Packaging and installing extension libraries. - -* [[Cross development]] : Building software for a different architecture. - -* [[Data representation]]: How Scheme data is internally represented. - -* [[Bugs and limitations]]: Things that do not work yet. - -* [[FAQ]]: A list of Frequently Asked Questions about CHICKEN (and - their answers!). - -* [[Acknowledgements]]: A list of some of the people that have - contributed to make CHICKEN what it is. - -* [[Bibliography]]: Links to documents that may be of interest. +programs. === CHICKEN repositories, websites, and community @@ -232,7 +202,7 @@ can pretty much ignore the C compiler once you have installed it.) Unix-style development/build environment, again ported from free software. *** You can build CHICKEN either with MinGW alone or with MinGW plus - MSys. Both approaches produce a CHICKEN built against the mingw headers + MSYS. Both approaches produce a CHICKEN built against the mingw headers and import libraries. The only difference is the environment where you actually run make. {{Makefile.mingw}} is can be used in {{cmd.exe}} with the version of make diff --git a/manual/Macros b/manual/Macros new file mode 100644 index 00000000..5c40447c --- /dev/null +++ b/manual/Macros @@ -0,0 +1,209 @@ +[[tags: manual]] +[[toc:]] + + +== Macros + + +CHICKEN supports standard R5RS {{syntax-rules}} macros and a low-level +macro system based on ''explicit renaming''. + + +=== Macro definitions + +==== define-syntax + +<macro>(define-syntax IDENTIFIER TRANSFORMER)</macro> + +Defines a macro named {{IDENTIFIER}} that will transform an expression +with {{IDENTIFIER}} in operator position according to {{TRANSFORMER}}. +The transformer expression must be a procedure with three arguments or +a {{syntax-rules}} form. If {{syntax-rules}} is used, the usual R5RS +semantics apply. If {{TRANSFORMER}} is a procedure, then it will +be called on expansion with the complete s-expression of the macro +invocation, a rename procedure that hygienically renames identifiers +and a comparison procedure that compares (possibly renamed) identifiers +(see the section "Explicit renaming macros" below for a detailed explanation +on non-R5RS macros). + +{{define-syntax}} may be used to define local macros that are visible +throughout the rest of the body in which the definition occurred, i.e. + + (let () + ... + (define-syntax foo ...) + (define-syntax bar ...) + ...) + +is expanded into + + (let () + ... + (letrec-syntax ((foo ...) (bar ...)) + ...) ) + +{{syntax-rules}} partially supports [[http://srfi.schemers.org/srfi-46/|SRFI-46]] +in allowing the ellipsis identifier to be user-defined by passing it as the first +argument to the {{syntax-rules}} form. + +The effect of destructively modifying the s-expression passed to a +transformer procedure is undefined. + + +==== syntax + +<macro>(syntax EXPRESSION)</macro> + +Similar to {{quote}} but retains syntactical context information for +embedded identifiers. + + +==== strip-syntax + +<procedure>(strip-syntax EXPRESSION)</procedure> + +Strips all syntactical information from {{EXPRESSION}}, returning a new expression +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, +{{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. + +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)) + +Expressions are represented as lists in the traditional manner, +except that identifiers are represented as special uninterned symbols. + +The second argument to a transformation procedure is a renaming procedure that +takes the representation of an identifier as its argument and returns the +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))) + +The expression returned by the transformation procedure will be +expanded in the syntactic environment obtained from the syntactic +environment of the macro application by binding any fresh identifiers +generated by the renaming procedure to the denotations of the original +identifiers in the syntactic environment in which the macro was +defined. This means that a renamed identifier will denote the same +thing as the original identifier unless the transformation procedure +that renamed the identifier placed an occurrence of it in a binding +position. + +Identifiers obtained from any two calls to the renaming procedure with +the same argument will necessarily be the same, but will denote the +same syntactical binding. It is an error if the renaming procedure is +called after the transformation procedure has returned. + +The third argument to a transformation procedure is a comparison +predicate that takes the representations of two identifiers as its +arguments and returns true if and only if they denote the same thing +in the syntactic environment that will be used to expand the +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)) + (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 +only if the test expression is an identifier that denotes the same +thing in the syntactic environment of the expression being transformed +as {{else}} denotes in the syntactic environment in which the {{cond}} +macro was defined. If {{else}} were not renamed before being passed to +the comparison predicate, then it would match a local variable that +happened to be named {{else}}, and the macro would not be hygienic. + +Some macros are non-hygienic by design. For example, the +following defines a {{loop}} macro that implicitly binds {{exit}} to an +escape procedure. The binding of {{exit}} is intended to capture free +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)))))))) + +Suppose a {{while}} macro is implemented using {{loop}}, with the intent +that {{exit}} may be used to escape from the {{while}} loop. The {{while}} +macro cannot be written as + + (define-syntax while + (syntax-rules () + ((while test body ...) + (loop (if (not test) (exit #f)) + body ...)))) + +because the reference to {{exit}} that is inserted by the {{while}} macro +is intended to be captured by the binding of {{exit}} that will be +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)))) + +Note: this implementation of explicit-renaming macros allows passing +arbitrary expressions to the renaming and comparison procedures. When +being renamed, a fresh copy of the expression will be produced, with all +identifiers renamed appropriately. Comparison also supports arbitrary +expressions as arguments. + + +--- +Previous: [[Non-standard macros and special forms]] + +Next: [[Modules]] diff --git a/manual/Modules and macros b/manual/Modules similarity index 57% rename from manual/Modules and macros rename to manual/Modules index 30bc97fe..bdbcacda 100644 --- a/manual/Modules and macros +++ b/manual/Modules @@ -2,207 +2,6 @@ [[toc:]] -== Modules and macros - - -CHICKEN supports standard R5RS {{syntax-rules}} macros and a low-level -macro system based on ''explicit renaming''. - - -=== Macro definitions - -==== define-syntax - -<macro>(define-syntax IDENTIFIER TRANSFORMER)</macro> - -Defines a macro named {{IDENTIFIER}} that will transform an expression -with {{IDENTIFIER}} in operator position according to {{TRANSFORMER}}. -The transformer expression must be a procedure with three arguments or -a {{syntax-rules}} form. If {{syntax-rules}} is used, the usual R5RS -semantics apply. If {{TRANSFORMER}} is a procedure, then it will -be called on expansion with the complete s-expression of the macro -invocation, a rename procedure that hygienically renames identifiers -and a comparison procedure that compares (possibly renamed) identifiers -(see the section "Explicit renaming macros" below for a detailed explanation -on non-R5RS macros). - -{{define-syntax}} may be used to define local macros that are visible -throughout the rest of the body in which the definition occurred, i.e. - - (let () - ... - (define-syntax foo ...) - (define-syntax bar ...) - ...) - -is expanded into - - (let () - ... - (letrec-syntax ((foo ...) (bar ...)) - ...) ) - -{{syntax-rules}} partially supports [[http://srfi.schemers.org/srfi-46/|SRFI-46]] -in allowing the ellipsis identifier to be user-defined by passing it as the first -argument to the {{syntax-rules}} form. - -The effect of destructively modifying the s-expression passed to a -transformer procedure is undefined. - - -==== syntax - -<macro>(syntax EXPRESSION)</macro> - -Similar to {{quote}} but retains syntactical context information for -embedded identifiers. - - -==== strip-syntax - -<procedure>(strip-syntax EXPRESSION)</procedure> - -Strips all syntactical information from {{EXPRESSION}}, returning a new expression -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, -{{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. - -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)) - -Expressions are represented as lists in the traditional manner, -except that identifiers are represented as special uninterned symbols. - -The second argument to a transformation procedure is a renaming procedure that -takes the representation of an identifier as its argument and returns the -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))) - -The expression returned by the transformation procedure will be -expanded in the syntactic environment obtained from the syntactic -environment of the macro application by binding any fresh identifiers -generated by the renaming procedure to the denotations of the original -identifiers in the syntactic environment in which the macro was -defined. This means that a renamed identifier will denote the same -thing as the original identifier unless the transformation procedure -that renamed the identifier placed an occurrence of it in a binding -position. - -Identifiers obtained from any two calls to the renaming procedure with -the same argument will necessarily be the same, but will denote the -same syntactical binding. It is an error if the renaming procedure is -called after the transformation procedure has returned. - -The third argument to a transformation procedure is a comparison -predicate that takes the representations of two identifiers as its -arguments and returns true if and only if they denote the same thing -in the syntactic environment that will be used to expand the -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)) - (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 -only if the test expression is an identifier that denotes the same -thing in the syntactic environment of the expression being transformed -as {{else}} denotes in the syntactic environment in which the {{cond}} -macro was defined. If {{else}} were not renamed before being passed to -the comparison predicate, then it would match a local variable that -happened to be named {{else}}, and the macro would not be hygienic. - -Some macros are non-hygienic by design. For example, the -following defines a {{loop}} macro that implicitly binds {{exit}} to an -escape procedure. The binding of {{exit}} is intended to capture free -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)))))))) - -Suppose a {{while}} macro is implemented using {{loop}}, with the intent -that {{exit}} may be used to escape from the {{while}} loop. The {{while}} -macro cannot be written as - - (define-syntax while - (syntax-rules () - ((while test body ...) - (loop (if (not test) (exit #f)) - body ...)))) - -because the reference to {{exit}} that is inserted by the {{while}} macro -is intended to be captured by the binding of {{exit}} that will be -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)))) - -Note: this implementation of explicit-renaming macros allows passing -arbitrary expressions to the renaming and comparison procedures. When -being renamed, a fresh copy of the expression will be produced, with all -identifiers renamed appropriately. Comparison also supports arbitrary -expressions as arguments. - - === Modules To allow some control over visible bindings and to organize code at @@ -526,6 +325,6 @@ be one. --- -Previous: [[Non-standard macros and special forms]] +Previous: [[Macros]] Next: [[Declarations]] diff --git a/manual/Non-standard macros and special forms b/manual/Non-standard macros and special forms index 22458309..807f1e4b 100644 --- a/manual/Non-standard macros and special forms +++ b/manual/Non-standard macros and special forms @@ -542,4 +542,4 @@ that is the current value of {{(current-error-port)}}. --- Previous: [[Non-standard read syntax]] -Next: [[Modules and macros]] +Next: [[Macros]] diff --git a/manual/Supported language b/manual/Supported language index ccbf3790..3fe014cd 100644 --- a/manual/Supported language +++ b/manual/Supported language @@ -7,7 +7,8 @@ * [[Extensions to the standard]] * [[Non-standard read syntax]] * [[Non-standard macros and special forms]] -* [[Modules and macros]] +* [[Macros]] +* [[Modules]] * [[Declarations]] * [[Parameters]] * [[Exceptions]]Trap