[plt-scheme] A question on "expand"

From: Eli Barzilay (eli at barzilay.org)
Date: Tue Nov 12 21:14:19 EST 2002

On Nov 12, Robert Bruce Findler wrote:
> The latest version of DrScheme gives you much better feedback about
> syntax objects. In the REPL, they have a little turn down knobby
> that, when turned, shows you all kinds of information about them.

[Wouldn't it be possible to use the syntax marks thing to do a step by
step expansion and show the new stuff at each stage with a different
color?]


> If you can't get to the CVS archive, you might instead use
> syntax-object->datum -- it produces an sexp version of the syntax
> object.

I have some code that fits nicely in the .mzschemerc file.  It allows
you to do this:

  > (-test (let/cc foo (cond (x1 x2))))
  --> (let/cc foo (cond (x1 x2)))
  > -step*
  --> (call/cc (lambda (foo) (cond (x1 x2))))
  --> (#%app call/cc (lambda (foo) (if (#%top . x1) (begin (#%top . x2)) (#%app void))))
  --> (#%app call/cc (lambda (foo) (if (#%top . x1) (begin (#%top . x2)) (#%app void))))
  --> ...

You get these things:

  (-test foo) - uses `foo' as the current syntax
  -test       - return the current syntax as an s-exp (the rest return
                void)
  -step       - expand-once
  -expand     - complete expand
  -step*      - expand-once until no change

and you can set and do some operation quickly by supplying an initial
syntax as in:

  > (-step* (let/cc foo (cond (x1 x2))))
  --> (let/cc foo (cond (x1 x2)))
  --> (call/cc (lambda (foo) (cond (x1 x2))))
  --> (#%app call/cc (lambda (foo) (if (#%top . x1) (begin (#%top . x2)) (#%app void))))
  --> (#%app call/cc (lambda (foo) (if (#%top . x1) (begin (#%top . x2)) (#%app void))))
  --> ...

I couldn't figure out any way to do a step-by-step expansion and
avoid getting the result infected with "#%"s and other things you
usually don't want to see (like define/let-values etc).  At least not
without some reimplementation of expand.

Here is the code:
-------------------------------------------------------------------------------
;; Syntax debugging
;; -test or (-test)     returns current syntax object as an s-expression
;; (-test foo)          set current
;; (-test :this)        show current
;; (-test :expand)      expand current (possibly in a context)
;; (-test :expand-once) expand one step
;; (-test :expand*)     expand one step repeatedly
(define-syntax -test
  (let ((v #f)
        (->datum (lambda (x) (if (syntax? x) (syntax-object->datum x) x))))
    (lambda (stx)
      (syntax-case stx ()
        ((_ m)
         (let ((msg #'m))
           (let loop ((new (case (->datum msg)
                             ((:this) v)
                             ((:expand) (expand v))
                             ((:expand-once :expand*) (expand-once v))
                             (else msg))))
             (printf "--> ~s\n" (->datum new))
             (let ((old v))
               (set! v new)
               (when (eq? (->datum msg) ':expand*)
                 (if (equal? (->datum new) (->datum old))
                   (printf "--> ...\n")
                   (loop (expand-once v))))))
           #'(void)))
        (_ #`'#,v)))))
;; shortcuts: each one calls the above with a message when used as -foo,
;; setting the expression first if it was used with one as in (-foo expr).
(define-syntaxes (-step -step* -expand)
  (apply values (map (lambda (msg)
                       (lambda (stx)
                         (syntax-case stx ()
                           ((_ expr) #'(begin (-test expr) _))
                           (_ #`(-test #,msg)))))
                     '(:expand-once :expand* :expand))))
-------------------------------------------------------------------------------

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


Posted on the users mailing list.