Summary
A case when composing with ir-macro-transformer
Metadata
- Id: 9b1842fd90e8044a64b7b6410f67302512be4e9b
- Trac id: 1362
- Type: defect
- Reporter: megane
- Owner:
- Cc:
- Status: closed
- Component: expander
- Estimated difficulty: hard
- Resolution: fixed
- Priority: major
- Milestone: 4.13.0
- Version: 4.12.0
- Changetime: 2017-04-19 10:50:17 UTC
- Created: 2017-04-12 14:13:40 UTC
- Keywords: ir-macro-transformer
Attachments
- 9b1842fd90e8044a64b7b6410f67302512be4e9b/attachments/foo.scm
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.