Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Macro stepper in DrRacket

On the link http://www.ccs.neu.edu/home/ryanc/macro-stepper/tutorial.html there are instructions for working with the macro stepper.

However, when I'm going to try it, I can't get the second expansion of myor in the definition of nonzero? function, only the first. Also, I have no buttons "Previous term" and "Next term".

So my question is: how i must configure macro stepper to get the second expansion, like in tutorial?

like image 787
Racket Noob Avatar asked Jan 22 '12 14:01

Racket Noob


1 Answers

I'm assuming that your source program looked something like this:

#lang racket
(define-syntax myor
  (syntax-rules ()
    [(myor e) e]
    [(myor e1 . es)
     (let ([r e1]) (if r r (myor . es)))]))
(define (nonzero? r)
  (myor (negative? r)
        (positive? r)))

Short story: use syntax-case rather than syntax-rules for the moment; there appears to be some bug associated with the Macro stepper and syntax-rules. I've sent along a bug report to the Racket developers, so hopefully this will be fixed soon. The syntax-case version of the above program looks like this.

#lang racket

(define-syntax (myor stx)
  (syntax-case stx ()
    [(_ e) #'e]
    [(_ e1 . es)
     #'(let ([r e1]) (if r r (myor . es)))]))

(define (nonzero? r)
  (myor (negative? r)
        (positive? r)))

Below is the longer story...

When I run your program under the pre-release of 5.2.1, I see the following in the Macro Stepper, with Macro hiding set to "Standard":

(module anonymous-module racket
  (#%module-begin
   (define-syntax myor
     (syntax-rules () [(myor e) e] [(myor e1 . es) (let ([r e1]) (if r r (myor . es)))]))
   (define (nonzero? r)
     (let:26 ([r:26 (negative? r)]) (if:26 r:26 r:26 (myor:26 (positive? r)))))))

which looks wrong. It expands only one use of myor out to uses of if. Very odd!

Let's see what things look like under Racket 5.2...

(module anonymous-module racket
  (#%module-begin
   (define-syntax myor
     (syntax-rules () [(myor e) e] [(myor e1 . es) (let ([r e1]) (if r r (myor . es)))]))
   (define (nonzero? r) (let ([r (negative? r)]) (if r r (myor (positive? r)))))))

Ah. Ok, I can confirm that I see the same problem that you see in Racket 5.2, as well as the pre-release.

The bug seems related to the behavior of the "Macro hiding" feature, which tries to not overwhelm you with the full expansion when it is set to Standard. If you set it to "Disabled", you'll see that the macro debugger will show the expansion in its full, unvarnished glory, and it does include the expansion that we expect to see:

(module anonymous-module racket
  (#%module-begin
   (define-syntaxes (myor)
     (lambda (x)
        ; ... I'm omitting the content here: it's way too long.
     ))
   (define-values:20 (nonzero?)
     (lambda:21 (r) (let-values:22 (((r) (#%app:23 negative? r))) (if r r (#%app:24 positive? r)))))))

I'll write a bug report and send it to the Racket developers.

If you write your macro using syntax-case, as opposed to syntax-rules, it appears to work better with the Macro Stepper.

#lang racket

(define-syntax (myor stx)
  (syntax-case stx ()
    [(_ e) #'e]
    [(_ e1 . es)
     #'(let ([r e1]) (if r r (myor . es)))]))

(define (nonzero? r)
  (myor (negative? r)
        (positive? r)))

When I step through this, it appears to work a lot better. So whatever is triggering the bug, it appears to be some interaction with the Macro Stepper and syntax-rules. So try using syntax-case instead.

like image 171
dyoo Avatar answered Sep 28 '22 15:09

dyoo