Summary

A case when composing with ir-macro-transformer

Metadata

Attachments

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:
{{{#!scheme
(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.

Changes and comments

[2017-04-12 14:17:21 UTC] megane attached foo.scm (description=#f)

[2017-04-14 15:39:18 UTC] sjamaan changed priority from not urgent at all to major

[2017-04-14 15:39:18 UTC] sjamaan set difficulty to hard

[2017-04-14 15:39:18 UTC] sjamaan changed milestone from someday to 4.13.0

[2017-04-14 18:04:14 UTC] sjamaan wrote:

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.

[2017-04-19 10:50:17 UTC] evhan changed keywords from ir-macro-trasformer to ir-macro-transformer

[2017-04-19 10:50:17 UTC] evhan changed status from new to closed

[2017-04-19 10:50:17 UTC] evhan set resolution to fixed

[2017-04-19 10:50:17 UTC] evhan wrote:

Fixed by 9473076e and 0d7f83f4.