[plt-scheme] syntax/cx+loc

From: Doug Orleans (dougo at place.org)
Date: Tue Mar 22 11:19:37 EST 2005

For a while I've been confused about why there was a difference
between having helper procedures local to a `define-syntax'
transformer and putting them into a module and using

(module m1 mzscheme
  (provide macro1)
  (define-syntax (macro1 stx)
    (define (helper1 stx)
      (syntax-case stx ()
	((a . b)
	 (syntax (list . b)))))
    (helper1 stx)))

(require m1)
(macro1 1 2 3) ; => (1 2 3)

(module m2 mzscheme
  (provide helper2)
  (define (helper2 stx)
    (syntax-case stx ()
      ((a . b)
       (syntax (list . b))))))

(module m3 mzscheme
  (require-for-syntax m2)
  (provide macro2)
  (define-syntax (macro2 stx)
    (helper2 stx)))

(require m3)
(macro2 1 2 3) ; => stdin::324: compile: bad syntax; function application is not allowed, because no #%app syntax transformer is bound in: (list 1 2 3)

I used to be able to use `namespace-syntax-introduce' in the helper
function, which would bind `#%app', but that no longer works in 299.33
(not sure why exactly).  But I think I now have a handle on what's
going on: when a `syntax' form is lexically enclosed in a transformer,
it attaches the lexical context of the input expression to the new
syntax object, which contains a transformer binding for `#%app';
otherwise, the new syntax object has the lexical context of the
module, which has no transformer bindings (because it was required for
syntax).  (Am I close, Matthew?)

So instead of using `syntax' (or `syntax/loc', which copies the source
location information), now I use `syntax/cx+loc', which copies both
the lexical context and source location information:

  (define-syntax syntax/cx+loc
    (syntax-rules ()
      ((_ source-stx-expr template-expr)
       (let ((source-stx source-stx-expr))
	  source-stx (syntax-e #'template-expr) source-stx)))))

This seems to work fine, so I thought I'd share it.  There's probably
a better name for this... maybe `syntax*'?

--dougo at place.org

Posted on the users mailing list.