[Top][All Lists]

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

Re: [Chicken-users] combining syntax-rules and er/ir-macro

From: Peter Bex
Subject: Re: [Chicken-users] combining syntax-rules and er/ir-macro
Date: Thu, 30 Jan 2014 09:00:42 +0100
User-agent: Mutt/

On Wed, Jan 29, 2014 at 10:05:03PM -0700, wrote:
> Thank you Evan, that helps explain the error message I was seeing.
> When I make your proposed changes, I get the following:
>     (ir-macro-transformer
>       (lambda (form inject compare?)
>         `(define-values (,(cadr form)
>                          ,@(map (lambda (x) (symbol-append (cadr form) '- x))
>                                 (cddr form)))
>            (values ,@((inject '%map) (inject 'quote) (cdr form)))))))
>   (enum my foo bar)
>   (pretty-print `(,my ,my-foo ,my-bar))
>   <-->
>   $ csi -n my-file.scm
>   Error: during expansion of (enum ...) - call of non-procedure: %map128
> I might assume the problem here is that %map isn't a procedure,
> it's syntax, and that the symbol is being properly injected, but
> then how do I can a macro from a macro?  I'm not even certain I'm
> diagnosing the problem correctly.

No, the problem is that Evan's advice of using "inject" here is wrong.

Your original problem was that a procedural macro only has access to
those procedures and macros which are available at expansion time, which
are those that are defined or imported "for syntax".  It's precisely by
using "inject" here that it will take literally whatever was input to
the macro, which is *always* going to be aliased already (for IR-macros,
inject is generally only useful when passing it direct quoted symbols).

The solution for that problem is to remove the inject calls.  However,
that produces a new problem due to (cdr form) being an invalid or
unexpected input to your map macro; the enum macro's invocation of
%map looks like

(%map quote (cdr foo))

The macro itself contains a macro call.  It's much simpler if you can
make it _expand_ to code that does a macro call.  That way, you get
better control over what needs to be taken literally as input to the
macro and what requires further list manipulation.

I think the main problem here (the one which requires all these weird
phasing gymnastics) is your %map macro.  It also needlessly complicates
matters due to returning a list of things like ((foo x) (bar y)), which
is then taken as code to be executed (as it is, after all, a macro and
macros are used to produce code), so you get something like

(define-values (my my-foo my-bar)
  ((quote foo) (quote bar)))

This isn't going to work, and I don't really see how to make it work.

You could probably complicate it further by introducing yet another
macro that first expands cdr foo and then creates all the define-values
entries (possibly introducing yet another phase), but it's probably
better to do a small rewrite:

(define-syntax define-composed-name
   (lambda (e r c)
     `(,(r 'define) ,(symbol-append (cadr e) '- (caddr e))
        ,@(cdddr e)))))

(define-syntax enum
  (syntax-rules ()
    ((_ ?name ?attrs ...)
       (define ?name '(?attrs ...))
       (define-composed-name ?name ?attrs '?attrs) ...))))

(enum my foo bar)
(pretty-print `(,my ,my-foo ,my-bar))

This is much simpler, but I'm not sure if it's going to help
you much: I'm sure this case is a simplification of your actual
code.  I do hope, however, that my little "analysis" helps you
to get the necessary insights to see what's going wrong.


reply via email to

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