Changeset 14236 in project for chicken


Ignore:
Timestamp:
04/13/09 11:32:45 (10 years ago)
Author:
felix winkelmann
Message:

added er-macro-transformer

Location:
chicken/trunk
Files:
12 edited

Legend:

Unmodified
Added
Removed
  • chicken/trunk/NEWS

    r13737 r14236  
     14.0.1
     2
     3- Added `er-macro-transformer'; Low-level syntax definitions should use
     4  this procedure to generate transformers from now on
     5
    164.0.0
    27
  • chicken/trunk/compiler.scm

    r13856 r14236  
    733733                        (let* ((var (if (pair? (cadr x)) (caadr x) (cadr x)))
    734734                               (body (if (pair? (cadr x))
    735                                          `(,(macro-alias 'lambda se) ,(cdadr x) ,@(cddr x))
     735                                         `(,(macro-alias 'er-macro-transformer se)
     736                                           (,(macro-alias 'lambda se) ,(cdadr x) ,@(cddr x)))
    736737                                         (caddr x)))
    737738                               (name (lookup var se)))
  • chicken/trunk/eval.scm

    r13677 r14236  
    625625                          (let* ((var (if (pair? (cadr x)) (caadr x) (cadr x)))
    626626                                 (body (if (pair? (cadr x))
    627                                            `(,(rename 'lambda se) ,(cdadr x) ,@(cddr x))
     627                                           `(,(rename 'er-macro-transformer se)
     628                                             (,(rename 'lambda se) ,(cdadr x) ,@(cddr x)))
    628629                                           (caddr x)))
    629630                                 (name (rename var se)))
  • chicken/trunk/expand.scm

    r13723 r14236  
    531531                     (cdr body)
    532532                     (cons (if (pair? (cadr def))
    533                                `(define-syntax ,(caadr def) (,(macro-alias 'lambda se) ,(cdadr def) ,@(cddr def)))
     533                               `(define-syntax ,(caadr def)
     534                                  (,(macro-alias 'er-macro-transformer se)
     535                                   (,(macro-alias 'lambda se) ,(cdadr def) ,@(cddr def))))
    534536                               def)
    535537                           defs)
     
    728730
    729731;;; explicit-renaming transformer
     732
     733(define (er-macro-transformer x) x)
    730734
    731735(define ((##sys#er-transformer handler) form se dse)
  • chicken/trunk/manual/Modules and macros

    r14061 r14236  
    1818Defines a macro named {{IDENTIFIER}} that will transform an expression
    1919with {{IDENTIFIER}} in operator position according to {{TRANSFORMER}}.
    20 The transformer expression must be a procedure with three arguments or
    21 a {{syntax-rules}} form. If {{syntax-rules}} is used, the usual R5RS
    22 semantics apply. If {{TRANSFORMER}} is a procedure, then it will
    23 be called on expansion with the complete s-expression of the macro
    24 invocation, a rename procedure that hygienically renames identifiers
    25 and a comparison procedure that compares (possibly renamed) identifiers.
     20The transformer expression must be an instance of
     21{{er-macro-transformer}}, called with a procedure of three arguments,
     22or a {{syntax-rules}} form. If {{syntax-rules}} is used, the usual
     23R5RS semantics apply. If {{TRANSFORMER}} is an instance of
     24{{er-macro-transformer}}, then it will be called on expansion with the
     25complete s-expression of the macro invocation, a rename procedure that
     26hygienically renames identifiers and a comparison procedure that
     27compares (possibly renamed) identifiers.
    2628
    2729{{define-syntax}} may be used to define local macros that are visible
     
    4547argument to the {{syntax-rules}} form.
    4648
     49The alternative syntax
     50
     51  (define-syntax (foo . LAMBDALIST) BODY ...)
     52
     53is also allowed and is equivalent to
     54
     55  (define-syntax foo
     56    (er-macro-transformer
     57      (lambda LAMBDALIST BODY ...)))
     58
     59==== er-macro-transformer
     60
     61  [procedure] (er-macro-transformer PROCEDURE)
     62
     63Takes a low-level transformer procedure and returns an explicit renaming
     64syntax transformer. The canonical method of defining a low-level macro is
     65
     66  (define-syntax foo
     67    (er-macro-transformer
     68      (lambda (exp rename compare)
     69        ...)))
    4770
    4871==== define-compiled-syntax
     
    7396
    7497The low-level macro facility that CHICKEN provides is called "explicit
    75 renaming" and allows writing hygienic or non-hygienic macros procedurally.
    76 When given a lambda-expression instead of a {{syntax-rules}} form,
    77 {{define-syntax}} evaluates the procedure in a distinct expansion
    78 environment (initially having access to the exported identifiers
    79 of the {{scheme}} module). The procedure takes an expression and two
    80 other arguments and returns a transformed expression.
    81 
    82 For example, the transformation
    83 procedure for a {{call}} macro such that
    84 {{(call proc arg ...)}} expands
    85 into {{(proc arg ...)}} can be written as
     98renaming" and allows writing hygienic or non-hygienic macros
     99procedurally.  When given a macro-transformer returned by
     100{{er-macro-transformer}} instead of a {{syntax-rules}} form,
     101{{define-syntax}} evaluates the procedure given to it in a distinct
     102expansion environment (initially having access to the exported
     103identifiers of the {{scheme}} module). The procedure takes an
     104expression and two other arguments and returns a transformed
     105expression.
     106
     107For example, the transformation procedure for a {{call}} macro such
     108that {{(call proc arg ...)}} expands into {{(proc arg ...)}} can be
     109written as
    86110
    87111  (lambda (exp rename compare)
    88112    (cdr exp))
    89113
    90 Expressions are represented as lists in the traditional manner,
    91 except that identifiers are represented as special uninterned symbols.
    92 
    93 The second argument to a transformation procedure is a renaming procedure that
    94 takes the representation of an identifier as its argument and returns the
    95 representation of a fresh identifier that occurs nowhere else in the
    96 program.  For example, the transformation procedure for a simplified
    97 version of the {{let}} macro might be written as
     114Expressions are represented as lists in the traditional manner, except
     115that identifiers are represented as special uninterned symbols.
     116
     117The second argument to a transformation procedure is a renaming
     118procedure that takes the representation of an identifier as its
     119argument and returns the representation of a fresh identifier that
     120occurs nowhere else in the program.  For example, the transformation
     121procedure for a simplified version of the {{let}} macro might be
     122written as
    98123
    99124  (lambda (exp rename compare)
     
    104129        ,@inits)))
    105130
    106 This would not be hygienic, however.  A
    107 hygienic {{let}} macro must rename the identifier {{lambda}} to protect it
    108 from being captured by a local binding.  The renaming effectively
    109 creates an fresh alias for {{lambda}}, one that cannot be captured by
    110 any subsequent binding:
     131This would not be hygienic, however.  A hygienic {{let}} macro must
     132rename the identifier {{lambda}} to protect it from being captured by
     133a local binding.  The renaming effectively creates an fresh alias for
     134{{lambda}}, one that cannot be captured by any subsequent binding:
    111135
    112136  (lambda (exp rename compare)
     
    137161in the syntactic environment that will be used to expand the
    138162transformed macro application.  For example, the transformation
    139 procedure for a simplified version of the {{cond}} macro can be written
    140 as
     163procedure for a simplified version of the {{cond}} macro can be
     164written as
    141165
    142166  (lambda (exp rename compare)
     
    160184thing in the syntactic environment of the expression being transformed
    161185as {{else}} denotes in the syntactic environment in which the {{cond}}
    162 macro was defined.  If {{else}} were not renamed before being passed to
    163 the comparison predicate, then it would match a local variable that
     186macro was defined.  If {{else}} were not renamed before being passed
     187to the comparison predicate, then it would match a local variable that
    164188happened to be named {{else}}, and the macro would not be hygienic.
    165189
    166 Some macros are non-hygienic by design.  For example, the
    167 following defines a {{loop}} macro that implicitly binds {{exit}} to an
    168 escape procedure.  The binding of {{exit}} is intended to capture free
     190Some macros are non-hygienic by design.  For example, the following
     191defines a {{loop}} macro that implicitly binds {{exit}} to an escape
     192procedure.  The binding of {{exit}} is intended to capture free
    169193references to {{exit}} in the body of the loop, so {{exit}} is not
    170194renamed.
    171195
    172196  (define-syntax loop
    173      (lambda (x r c)
    174        (let ((body (cdr x)))
    175          `(,(r 'call-with-current-continuation)
    176            (,(r 'lambda) (exit)
    177             (,(r 'let) ,(r 'f) () ,@body (,(r 'f))))))))
     197    (er-macro-transformer
     198      (lambda (x r c)
     199        (let ((body (cdr x)))
     200          `(,(r 'call-with-current-continuation)
     201            (,(r 'lambda) (exit)
     202             (,(r 'let) ,(r 'f) () ,@body (,(r 'f)))))))))
    178203
    179204Suppose a {{while}} macro is implemented using {{loop}}, with the intent
     
    182207
    183208  (define-syntax while
    184     (syntax-rules ()
    185       ((while test body ...)
    186        (loop (if (not test) (exit #f))
    187              body ...))))
     209    (er-macro-transformer
     210      (syntax-rules ()
     211        ((while test body ...)
     212         (loop (if (not test) (exit #f))
     213               body ...)))))
    188214
    189215because the reference to {{exit}} that is inserted by the {{while}} macro
     
    193219
    194220  (define-syntax while
    195      (lambda (x r c)
    196        (let ((test (cadr x))
    197              (body (cddr x)))
    198          `(,(r 'loop)
    199            (,(r 'if) (,(r 'not) ,test) (exit #f))
    200            ,@body))))
     221    (er-macro-transformer
     222      (lambda (x r c)
     223        (let ((test (cadr x))
     224              (body (cddr x)))
     225          `(,(r 'loop)
     226            (,(r 'if) (,(r 'not) ,test) (exit #f))
     227            ,@body)))))
    201228
    202229
  • chicken/trunk/private-namespace.scm

    r12937 r14236  
    2929 (hygienic-macros
    3030  (define-syntax private
     31    ;;XXX use er-macro-transformer
    3132    (lambda (form r c)
    3233      (let ((namespace (cadr form))
  • chicken/trunk/scheme.import.scm

    r13847 r14236  
    5454       with-output-to-file dynamic-wind values call-with-values eval
    5555       char-ready? imag-part real-part magnitude numerator denominator
    56        scheme-report-environment null-environment interaction-environment)
     56       scheme-report-environment null-environment interaction-environment
     57       er-macro-transformer)
    5758 ##sys#default-macro-environment)
  • chicken/trunk/setup-api.scm

    r14074 r14236  
    396396
    397397(define-syntax make
     398  ;;XXX use er-macro-transformer
    398399  (lambda (form r c)
    399400    (##sys#check-syntax 'make form '(_ _ . #(_ 0 1)))
     
    451452        (to (let ((to-path (if (pair? from) (make-pathname to (cadr from)) to)))
    452453              (if (and prefix (not (string-prefix? prefix to-path)))
    453                   (make-pathname prefix to-path) to-path))))
     454                  (make-pathname prefix to-path)
     455                  to-path))))
    454456    (ensure-directory to)
    455457    (cond ((or (glob? from) (file-exists? from))
  • chicken/trunk/srfi-13.scm

    r13737 r14236  
    206206 (else
    207207  (define-syntax let-string-start+end
     208    ;;XXX use er-macro-transformer
    208209    (lambda (form r c)
    209210      (##sys#check-syntax 'let-string-start+end form '(_ _ _ _ _ . _))
  • chicken/trunk/srfi-69.scm

    r13451 r14236  
    145145
    146146(define-syntax $flonum-hash
     147  ;;XXX use er-macro-transformer
    147148  (lambda (form r c)
    148149    (let ( (flo (cadr form))
  • chicken/trunk/tests/srfi-18-tests.scm

    r11038 r14236  
    44(define-for-syntax count 0)
    55(define-syntax trail
     6  (er-macro-transformer
    67  (lambda (form r c)                    ; doesn't bother much with renaming
    78    (let ((loc (cadr form))
     
    1213        (let ((xxx ,expr))
    1314          (print "  (" ,count ") " ,loc ": " ',expr ": get: " (##sys#slot get-mutex 5) ", put: " (##sys#slot put-mutex 5))
    14           xxx) ) ))))
     15          xxx) ) )))))
    1516(else (define-syntax trail (syntax-rules () ((_ loc expr) expr)))))
    1617
  • chicken/trunk/tests/syntax-tests.scm

    r13582 r14236  
    212212
    213213(define-syntax loop
    214   (lambda (x r c)
    215     (let ((body (cdr x)))
    216       `(,(r 'call/cc)
    217         (,(r 'lambda) (exit)
    218          (,(r 'let) ,(r 'f) () ,@body (,(r 'f))))))))
     214  (er-macro-transformer
     215   (lambda (x r c)
     216     (let ((body (cdr x)))
     217       `(,(r 'call/cc)
     218         (,(r 'lambda) (exit)
     219          (,(r 'let) ,(r 'f) () ,@body (,(r 'f)))))))))
    219220
    220221(let ((n 10))
     
    234235
    235236(define-syntax while
    236   (lambda (x r c)
    237     `(,(r 'loop)
    238       (,(r 'if) (,(r 'not) ,(cadr x)) (exit #f))
    239       ,@(cddr x))))
     237  (er-macro-transformer
     238   (lambda (x r c)
     239     `(,(r 'loop)
     240       (,(r 'if) (,(r 'not) ,(cadr x)) (exit #f))
     241       ,@(cddr x)))))
    240242
    241243(let ((n 10))
Note: See TracChangeset for help on using the changeset viewer.