Opened 8 years ago

Closed 7 years ago

#1362 closed defect (fixed)

A case when composing with ir-macro-transformer

Reported by: megane Owned by:
Priority: major Milestone: 4.13.0
Component: expander Version: 4.12.0
Keywords: ir-macro-transformer Cc:
Estimated difficulty: hard

Description

I ran into this unexpected behaviour when using ir macros in ir macros. I don't think this should happen:

(I have tested this with 4.12, not with 5. )


First macro:

(define-syntax bind-pair
  (ir-macro-transformer
   (lambda (e i c)
     (let* ((b (second e))
            (exp (third e))
            (body (drop e 3)))
       `(let* ((x ,exp)
               (,(first b) (car x))
               (,(second b) (cdr x)))
          ,@body)))))


Testing:


 (bind-pair (x y) (cons 1 2) (print y))
 
 => prints 2


Now a second macro using bind-pair:


 (define-syntax foo
   (ir-macro-transformer
    (lambda (e i c)
      `(bind-pair (x y) (cons 'foo-car 'b) (print y)))))


Running (foo) gives the error:


Error: (cdr) bad argument type: foo-car


The expansion of (foo) looks like this:


 ;; (##core#let
 ;;   ((x40 (cons42 (quote43 foo-car44) (quote43 b45))))
 ;;   (##core#let
 ;;     ((x40 (car48 x40)))
 ;;     (##core#let ((y41 (cdr49 x40))) (##core#let () (print46 y41)))))

As you can see, the x in bind-pair and foo macros refer to the same
variable in the expansion. You can confirm this happens by changing the
x in foo to, say z.

Attachments (1)

foo.scm (1.5 KB) - added by megane 8 years ago.

Download all attachments as: .zip

Change History (4)

Changed 8 years ago by megane

Attachment: foo.scm added

comment:1 Changed 8 years ago by sjamaan

Estimated difficulty: hard
Milestone: someday4.13.0
Priority: not urgent at allmajor

comment:2 Changed 8 years ago by sjamaan

Essentially, the bug is this:

(define-syntax wrapper/do-nothing
  (er-macro-transformer
   (lambda (e r c)
     (let* ((%x (r 'x))
            (%%x (r %x)))
       `(let ((,%x 1)
              (,%%x 2)) ;; Twice the rename, twice the regret
          ,(cadr e))))))

(define x 1)

(display (wrapper/do-nothing x)) ;; Should print 1, but prints 2
(newline)

That's because ir-macro-transformer will rename the entire input form, which may contain identifiers which already have been renamed by another macro, resulting in an "undo" of the renaming of those double-renamed identifiers.

You can test the above snippet in Chibi, MIT Scheme or Scheme48 (remove the er-macro-transformer wrapper from the lambda to test it in the latter), they all print 1. I've sent a patch to chicken-hackers which fixes this.

comment:3 Changed 7 years ago by evhan

Keywords: ir-macro-transformer added; ir-macro-trasformer removed
Resolution: fixed
Status: newclosed

Fixed by 9473076e and 0d7f83f4.

Note: See TracTickets for help on using tickets.