[racket] Flatten syntax and runtime phases?

From: Nick Sivo (nick at kogir.com)
Date: Sat Jun 16 00:41:55 EDT 2012

Hi,

I have the following code:

#lang racket
(require mzlib/defmacro)

(defmacro w/uniq (name . body)
  `(let ([,name (gensym)])
     , at body))

(defmacro in (x . choices)
  (w/uniq g
     `(let ([,g ,x])
        (or ,@(map (lambda (c) `(eqv? ,g ,c)) choices)))))

Naturally, it fails:

expand: unbound identifier in module (in phase 1, transformer environment) in: g

Additionally defining w/uniq for-syntax fixes it:

#lang racket
(require mzlib/defmacro
         (for-syntax racket
                     mzlib/defmacro))

(begin-for-syntax
  (defmacro w/uniq (name . body)
    `(let ([,name (gensym)])
       , at body)))

(defmacro w/uniq (name . body)
    `(let ([,name (gensym)])
       , at body))

(defmacro in (x . choices)
  (w/uniq g
     `(let ([,g ,x])
        (or ,@(map (lambda (c) `(eqv? ,g ,c)) choices)))))

I know this is Racket's phase separation working as intended.  Now, I
appreciate why Racket separates phases as well as the advantages of
hygienic macros, but I'm not writing new code.  I'm trying to enable
existing code* to run natively in Racket and take advantage of its
great JIT and some module optimizations (like inlining).

Is there any way to hack the first version to work? One option is to
build a deeper nest of duplicate macro definitions each time I
encounter a new one.  It seems possible, and it might even work, but
it sounds awful.  I've already written a custom reader and have an
extensive library of language syntax/parse macros, so I'm open to
anything.

-Nick

* If you're curious, I believe this is the last obstacle in my
implementation of Arc as a Racket language.

Posted on the users mailing list.