unofficial mirror of guile-user@gnu.org 
 help / color / mirror / Atom feed
* bindings for free identifiers in (ice-9 syncase)
@ 2009-03-19 15:16 Julian Graham
  2009-03-19 16:32 ` Andreas Rottmann
  2009-03-21 12:04 ` Andy Wingo
  0 siblings, 2 replies; 7+ messages in thread
From: Julian Graham @ 2009-03-19 15:16 UTC (permalink / raw)
  To: guile-user

Hi Guilers,

Alright, I've been banging my head against this for several weeks now
and only just had the time to sit down and research this: If you use a
symbol in an `(ice-9 syncase)' macro definition that's bound in the
lexical closure in which that definition lives, then that binding
should be the one that gets used at transformation time.  At least,
that's how I interpret the following bit of R5RS:

"If a macro transformer inserts a free reference to an identifier, the
reference refers to the binding that was visible where the transformer
was specified, regardless of any local bindings that may surround the
use of the macro."

...but that's not what Guile seems to do.  (I'm fiddling around in
1.9.0 HEAD, because the VM is awesome and because there are some
already-committed syncase fixes that have been useful to me...)  If
you create the following module:

(define (foo-module)
  #:use-module (ice-9 syncase)
  #:export-syntax (foo-macro))

(define (foo-function) (display "Hello, world!"))

(define-syntax foo-macro
  (lambda (stx)
    (syntax-case stx ()
      ((_) (syntax (foo-function))))))

...and then import `(foo-module)' into the REPL or somewhere else,
evaluating `(foo-macro)' throws an error because `foo-function' can't
be found.  What am I doing wrong?


Regards,
Julian




^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: bindings for free identifiers in (ice-9 syncase)
  2009-03-19 15:16 bindings for free identifiers in (ice-9 syncase) Julian Graham
@ 2009-03-19 16:32 ` Andreas Rottmann
  2009-03-19 18:22   ` Julian Graham
  2009-03-19 19:53   ` Neil Jerram
  2009-03-21 12:04 ` Andy Wingo
  1 sibling, 2 replies; 7+ messages in thread
From: Andreas Rottmann @ 2009-03-19 16:32 UTC (permalink / raw)
  To: Julian Graham; +Cc: Guile Users

Julian Graham <joolean@gmail.com> writes:

> Hi Guilers,
>
> Alright, I've been banging my head against this for several weeks now
> and only just had the time to sit down and research this: If you use a
> symbol in an `(ice-9 syncase)' macro definition that's bound in the
> lexical closure in which that definition lives, then that binding
> should be the one that gets used at transformation time.  At least,
> that's how I interpret the following bit of R5RS:
>
> "If a macro transformer inserts a free reference to an identifier, the
> reference refers to the binding that was visible where the transformer
> was specified, regardless of any local bindings that may surround the
> use of the macro."
>
> ...but that's not what Guile seems to do.  (I'm fiddling around in
> 1.9.0 HEAD, because the VM is awesome and because there are some
> already-committed syncase fixes that have been useful to me...)  If
> you create the following module:
>
> (define (foo-module)
>   #:use-module (ice-9 syncase)
>   #:export-syntax (foo-macro))
>
> (define (foo-function) (display "Hello, world!"))
>
> (define-syntax foo-macro
>   (lambda (stx)
>     (syntax-case stx ()
>       ((_) (syntax (foo-function))))))
>
> ...and then import `(foo-module)' into the REPL or somewhere else,
> evaluating `(foo-macro)' throws an error because `foo-function' can't
> be found.  What am I doing wrong?
>
Nothing, this is a deficiency in Guile:
https://savannah.gnu.org/bugs/?20941. I wonder why it is marked as
"invalid", though.

Regards, Rotty




^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: bindings for free identifiers in (ice-9 syncase)
  2009-03-19 16:32 ` Andreas Rottmann
@ 2009-03-19 18:22   ` Julian Graham
  2009-03-19 20:28     ` Neil Jerram
  2009-03-19 19:53   ` Neil Jerram
  1 sibling, 1 reply; 7+ messages in thread
From: Julian Graham @ 2009-03-19 18:22 UTC (permalink / raw)
  To: Andreas Rottmann; +Cc: Guile Users

This does strike me as a serious problem (and it's a spanner in the
works for implementing R6RS libraries).  In effect, isn't the bug
saying that Guile's syncase macros aren't totally hygienic?  That is,
in my example, if you provide your own binding for `foo-function' in
the REPL environment, then that will be used in the evaluation of the
transformed expression instead of the one in `(foo-module)', which is
certainly *not* the intent of the macro author.

However, as a novice who's spent some time poking around in
ice-9/boot-9.scm and `(ice-9 syncase)', I'm sort of confused about why
this is hard -- isn't this metadata available?  The transformer should
have access to the closure in which it was created, and at creation
time, we certainly know which identifiers are free and which ones
aren't -- and we can look up the variables bound to the free ones in
the transformer's lexical closure.

The real issue with modules is that they hide bindings, not variables.
 If you have the variable, you can use it, no matter which module is
current.


On Thu, Mar 19, 2009 at 12:32 PM, Andreas Rottmann <a.rottmann@gmx.at> wrote:
> Julian Graham <joolean@gmail.com> writes:
>
>> Hi Guilers,
>>
>> Alright, I've been banging my head against this for several weeks now
>> and only just had the time to sit down and research this: If you use a
>> symbol in an `(ice-9 syncase)' macro definition that's bound in the
>> lexical closure in which that definition lives, then that binding
>> should be the one that gets used at transformation time.  At least,
>> that's how I interpret the following bit of R5RS:
>>
>> "If a macro transformer inserts a free reference to an identifier, the
>> reference refers to the binding that was visible where the transformer
>> was specified, regardless of any local bindings that may surround the
>> use of the macro."
>>
>> ...but that's not what Guile seems to do.  (I'm fiddling around in
>> 1.9.0 HEAD, because the VM is awesome and because there are some
>> already-committed syncase fixes that have been useful to me...)  If
>> you create the following module:
>>
>> (define (foo-module)
>>   #:use-module (ice-9 syncase)
>>   #:export-syntax (foo-macro))
>>
>> (define (foo-function) (display "Hello, world!"))
>>
>> (define-syntax foo-macro
>>   (lambda (stx)
>>     (syntax-case stx ()
>>       ((_) (syntax (foo-function))))))
>>
>> ...and then import `(foo-module)' into the REPL or somewhere else,
>> evaluating `(foo-macro)' throws an error because `foo-function' can't
>> be found.  What am I doing wrong?
>>
> Nothing, this is a deficiency in Guile:
> https://savannah.gnu.org/bugs/?20941. I wonder why it is marked as
> "invalid", though.
>
> Regards, Rotty
>




^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: bindings for free identifiers in (ice-9 syncase)
  2009-03-19 16:32 ` Andreas Rottmann
  2009-03-19 18:22   ` Julian Graham
@ 2009-03-19 19:53   ` Neil Jerram
  1 sibling, 0 replies; 7+ messages in thread
From: Neil Jerram @ 2009-03-19 19:53 UTC (permalink / raw)
  To: Andreas Rottmann; +Cc: Guile Users

Andreas Rottmann <a.rottmann@gmx.at> writes:

> Nothing, this is a deficiency in Guile:
> https://savannah.gnu.org/bugs/?20941. I wonder why it is marked as
> "invalid", though.

Regardless of how it's marked, I'm still hoping to get to this soon.

    Neil




^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: bindings for free identifiers in (ice-9 syncase)
  2009-03-19 18:22   ` Julian Graham
@ 2009-03-19 20:28     ` Neil Jerram
  0 siblings, 0 replies; 7+ messages in thread
From: Neil Jerram @ 2009-03-19 20:28 UTC (permalink / raw)
  To: Julian Graham; +Cc: Guile Users

Julian Graham <joolean@gmail.com> writes:

> This does strike me as a serious problem (and it's a spanner in the
> works for implementing R6RS libraries).  In effect, isn't the bug
> saying that Guile's syncase macros aren't totally hygienic?  That is,
> in my example, if you provide your own binding for `foo-function' in
> the REPL environment, then that will be used in the evaluation of the
> transformed expression instead of the one in `(foo-module)', which is
> certainly *not* the intent of the macro author.

Completely agree.  I don't think there's any doubt that current
behaviour is wrong.

> However, as a novice who's spent some time poking around in
> ice-9/boot-9.scm and `(ice-9 syncase)', I'm sort of confused about why
> this is hard -- isn't this metadata available?  The transformer should
> have access to the closure in which it was created, and at creation
> time, we certainly know which identifiers are free and which ones
> aren't -- and we can look up the variables bound to the free ones in
> the transformer's lexical closure.

The problem is some combination of

- how lexical identifiers are memoized (as a pair of numbers I, J,
  meaning the Ith variable in the Jth level up from the current
  lexical environment)

- the fact that at any given point, the evaluator is only aware of one
  lexical environment

- that the macro transformation process doesn't memoize top-level
  variables at the time of the transformation.

I would guess it's mostly the last point.

Regards,
        Neil




^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: bindings for free identifiers in (ice-9 syncase)
  2009-03-19 15:16 bindings for free identifiers in (ice-9 syncase) Julian Graham
  2009-03-19 16:32 ` Andreas Rottmann
@ 2009-03-21 12:04 ` Andy Wingo
  2009-03-25  0:42   ` Neil Jerram
  1 sibling, 1 reply; 7+ messages in thread
From: Andy Wingo @ 2009-03-21 12:04 UTC (permalink / raw)
  To: Julian Graham; +Cc: guile-user

Hi Julian,

Just to add to the melee, I have been thinking hard about this too.
Somehow output produced by a macro must have its free identifiers scoped
in the module that was current when the macro was defined.

This could mean that syntax objects need a new field, and that output
should be serialized with the `@@' syntax, but I don't know right now.

I really want this within a couple of months though. But I would of
course be delighted to find that someone else has already implemented
this!

BTW if you haven't read it, I recommend the "Beautiful Code" paper on
syntax-case. See http://www.cs.indiana.edu/~dyb/pubs.html.

Andy
-- 
http://wingolog.org/




^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: bindings for free identifiers in (ice-9 syncase)
  2009-03-21 12:04 ` Andy Wingo
@ 2009-03-25  0:42   ` Neil Jerram
  0 siblings, 0 replies; 7+ messages in thread
From: Neil Jerram @ 2009-03-25  0:42 UTC (permalink / raw)
  To: Andy Wingo; +Cc: guile-user

Andy Wingo <wingo@pobox.com> writes:

> Hi Julian,
>
> Just to add to the melee, I have been thinking hard about this too.
> Somehow output produced by a macro must have its free identifiers scoped
> in the module that was current when the macro was defined.

I've been reaching that conclusion too.  (For others following this,
I've appended some notes / a draft email to explain why, after my
sig.)  There are a couple of relevant bits of R6RS.  From section 7.1:

  Bindings defined with a library are not visible in code outside of
  the library, unless the bindings are explicitly exported from the
  library. An exported macro may, however, implicitly export an
  otherwise unexported identifier defined within or imported into the
  library. That is, it may insert a reference to that identifier into
  the output code it produces.

And from section 9.2:

  If a macro transformer inserts a free reference to an identifier,
  the reference refers to the binding that was visible where the
  transformer was specified, regardless of any local bindings that may
  surround the use of the macro. 

I don't believe there's any guidance from the specs prior to R6RS,
because none of them had modules/libraries.

> This could mean that syntax objects need a new field, and that output
> should be serialized with the `@@' syntax, but I don't know right now.

It also means, I think, that a module/library has to have a lexical
effect.  Basically the reader needs to know what the current module is
at any point, and to mark each read identifier with that module.

Guile's modules are technically determined at eval time, so don't
conform to that.  On the other hand, the common practice, using
(define-module ...), and the fact that Guile reads and evaluates forms
from a file (or stdin) sequentially, together could give us a close
approximation to the necessary lexical effect.

Regards,
        Neil



Notes on the lexical effect thing, or "Hmmm...  I remember now that
this problem is actually harder than it looks."

It helps to consider define-macro, defmacro and
procedure->memoizing-macro first.  With all of these, it's clear that
you are really defining a procedure that will transform the supplied
expression into an expanded expression.  For example:

(define (foo-function a)
  ...)

(define-macro (foo-macro arg)
  `(foo-function ,arg))

(export-syntax foo-macro)

and then in another module, a call

(foo-macro bar)

will be expanded to

(foo-function bar)

At this point, the programmer thinks it is obvious that foo-function
should be looked up in the environment of the (define-macro ...) call,
and that bar should be looked up in the environment of the (foo-macro
...) call.  But as far as Guile is concerned, it now sees just
(foo-function bar), and has no idea that the environments for
foo-function and bar should be different.

And the same applies to (ice-9 syncase), because Guile's
implementation of syncase (from Dybvig) also boils down to defining a
transformer procedure.




^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2009-03-25  0:42 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-03-19 15:16 bindings for free identifiers in (ice-9 syncase) Julian Graham
2009-03-19 16:32 ` Andreas Rottmann
2009-03-19 18:22   ` Julian Graham
2009-03-19 20:28     ` Neil Jerram
2009-03-19 19:53   ` Neil Jerram
2009-03-21 12:04 ` Andy Wingo
2009-03-25  0:42   ` Neil Jerram

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).