Subject: bug#16158: psyntax: bug in bound-identifier=?

From: Mark H Weaver <[email-masked]>
Date: Mon, 16 Dec 2013 11:38:55 -0500

Hi,

Marco Maggi <[email-masked]> writes:
> Mark H Weaver wrote:
>> While reading psyntax.scm, I noticed that the definition of 'bound-id=?'
>> does not match the definition in "Syntax Abstraction in Scheme" by
>> Dybvig, Hieb, and Bruggeman.
>>
>> The paper states "Two identifiers that are bound-identifier=? are also
>> free-identifier=?".
>
> I think you are referring to this paragraph from the paper[1] (page 12):
>
>     Two    identifiers   that    are   bound-identifier=?     are   also
>     free-identifier=?,  but two  identifiers that  are free-identifier=?
>     may not be bound-identifier=?.  An  identifier introduced by a macro
>     transformer may refer to the same enclosing binding as an identifier
>     not introduced by the transformer, but an introduced binding for one
>     will not capture references to the other.

Yes.

>> The following expression shows that this is not the case in Guile 2.0:
>>
>>   (let* ((x 1) (s1 #'x)
>>          (x 2) (s2 #'x))
>>     (list (bound-identifier=? s1 s2)
>>           (free-identifier=? s1 s2)))
>>   => (#t #f)
>
>   The expander in Ikarus/Vicare also returns this value.

I think that indicates a bug in Ikarus/Vicare.

>> Racket reports (#f #f) for the same expression.
>
>   Racket is different because its expander implements a variant of phase
> separation; if the whole form is evaluated  at phase N, the "x" in "#'x"
> should be searched  among the bindings at  phase N-1 (if any)

I don't see how that's relevant to this example.

> Your code  works, but  when you actually  try to  use the
> identifiers for something:
>
>     #!r6rs
>     (import (rnrs))
>     (define-syntax doit
>       (lambda (stx)
>         (let* ((x 1) (s1 #'x)
>                (x 2) (s2 #'x))
>           #`(let ((#,s1 123))
>               #,s2))))
>     (doit)

Whether #`(let ((#,s1 123)) #,s2) works is equivalent to asking whether
s1 and s2 are 'bound-identifier=?', by definition.  That's precisely
what 'bound-identifier=?' is supposed to be used for: to determine
whether a binding for one should capture the other.

I don't see why you think #`(let ((#,s1 123)) #,s2) should work.  Why
would you use two identifiers with different binding names (s1 and s2)
to construct that code?  Can you construct a more realistic example?

     Thanks,
       Mark