chicken-users
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Chicken-users] Re: Explicit Renaming Macros Help/Tutorial?


From: Jim Ursetto
Subject: Re: [Chicken-users] Re: Explicit Renaming Macros Help/Tutorial?
Date: Tue, 9 Jun 2009 21:12:46 -0500

2009/6/9 Jack Trades <address@hidden>:
> A couple more questions.  I was playing with a macro that extends the syntax
> of if.  This macro works fine on its own and also if I import the module
> with no prefix.  However I get an error if I try to import the module with a
> prefix.

It's because you're testing the head of args against the symbol 'ef,
which will fail because the actual symbol is now 't-ef.  The cond statement
therefore falls through and returns #<unspecified> as you did not handle
the case of an illegal clause.  The append error is implicit in the
quasiquotation.

It is uncommon to test against the macro's name, but we can
do it by using the compare procedure against the renamed 'ef
identifier.  In other words, we check that 't-ef (or whatever the imported
name is) in the macro usage environment means the same thing
syntactically as 'ef does in the definition environment of the macro.
We also add a catch-all clause for syntax errors.

In addition it is important to rename the 'else identifier for the cond form
(otherwise you break hygiene).  It is probably also a good idea to use
the "compare" procedure rather than equal? to test for the elif and
else identifiers, to honor any lexical binding the user established
for those.  (This latter may be a matter of taste.  Unlike cond's else
clause, which resembles a regular test clause, your test/elif/else
clauses are unlikely to be confused as they differ structurally.)

Try variations on:
  (let ((else #f)) (t-ef (< 1 0) #t elif (< 1 0) 2 else #f))
with and without using compare and/or rename to get a feel for
what is going on.

Here is the modified code.

(module test (ef)
(import scheme)

(define-syntax ef
  (er-macro-transformer
   (lambda (x r c)
     (let ((%if (r 'if))
           (%cond (r 'cond)))
       `'(,@(let loop ((args x) (cons-form '()))
             (cond ((null? args)
                    (reverse cons-form))
                   ((c (car args) (r 'ef))
                    (cond ((= (length x) 3)
                           (let ((test (cadr x)) (true (caddr x)))
(cons %if (list test true))))
                          ((= (length x) 4)
                           (let ((t (cadr x)) (tt (caddr x)) (ft
(cadddr x))) (cons %if (list t tt ft))))
                          (else
                           (cons %cond (loop (cdddr args) (cons (list
(cadr args) (caddr args)) cons-form))))))
                   ((c (car args) (r 'elif))
                    (loop (cdddr args) (cons (list (cadr args) (caddr
args)) cons-form)))
                   ((c (car args) (r 'else))
                    (loop (cddr args) (cons (list (r 'else) (cadr
args)) cons-form)))
                   (else (syntax-error "malformed clause" args)))))))))
)




reply via email to

[Prev in Thread] Current Thread [Next in Thread]