[plt-scheme] Syntax hack...

From: Eli Barzilay (eli at barzilay.org)
Date: Mon Feb 17 04:34:35 EST 2003

Here's a problem: say I want a syntax `foo' that will do something
like capture a continuation and bind it to a known variable.  The
problem is I don't want to capture the continuation if it's not going
to get used...  Basically something that behaves like this:

  (foo (+ 1 2))        --expands-to--> (+ 1 2)
  (foo (+ 1 (break 2)) --expands-to--> (let/ec break (+ 1 (break 2)))

The only sane way I can see of solving this is to locally expand the
body and crawl over it -- but doing that I'd have to take care of
things like these:

  (foo 'break)                  --expands-to--> 'break
  (foo (let ((break 1)) break)) --expands-to--> (let ((break 1)) break)

So instead, I tought it would be nice to just bind `break' temporarily
to some syntax that I can tell if it was invoked or not.  This is
implemented like this:

  (define-syntax (foo stx)
    (define (id-in-expr sym expr)
      (let ((return #f) (id (datum->syntax-object expr sym expr)))
        (local-expand
         ;; Note: this hacks compilation levels but it should be fine
         #`(let-syntax ((#,id #,(lambda (stx) (set! return id) #'()))) #,expr)
         'expression '())
        return))
    (syntax-case stx ()
      ((_ x) (cond ((id-in-expr 'break #'x) =>
                    (lambda (break) #`(let/ec #,break x)))
                   (else #'x)))))

The thing is that AFAICT this mixes compilation levels -- at the
marked spot a syntax is created with a literal function instead of
some valid syntax.  This seems to be OK since that expression with the
hacked literal is never needed for saving in a compiled file or
something, it is only needed for the expansion.

So my questions are:

* Is there any other elegant way that can do this without a full code
  walker implementation?

* How bad would it be to rely on this shortcut to work?  (i.e, will
  there ever be a restriction on syntax pieces so they will have to
  evaluate to some valid syntax?)

* If something like this is useful, maybe it is best to add it as an
  implementation level functionality?  (So if such a restriction is
  ever made, then there is one place to change...)

-- 
          ((lambda (x) (x x)) (lambda (x) (x x)))          Eli Barzilay:
                  http://www.barzilay.org/                 Maze is Life!


Posted on the users mailing list.