expansion of splicing let-syntax needs revision

Bug #309223 reported by Abdulaziz Ghuloum
8
This bug affects 1 person
Affects Status Importance Assigned to Milestone
Ikarus Scheme
Confirmed
Low
Abdulaziz Ghuloum
IronScheme
New
Undecided
Unassigned
r6rs-libraries
New
Undecided
Unassigned

Bug Description

Currently, splicing let-syntax is kind of equivalent to define-syntax in that the following is valid:

(let ()
  (let-syntax ([foo (identifier-syntax 12)])
    (define-syntax x (identifier-syntax foo)))
  x)
=> 12

That is, foo expands correctly even though it's referenced out of its context (which is incorrect).

Changed in ikarus:
assignee: nobody → aghuloum
importance: Undecided → Low
status: New → Confirmed
Revision history for this message
leppie (leppie) wrote :

Scary! I dont think I have ever come across it, but then again, I am not too comfortable with let-syntax and friends either still. :)

Revision history for this message
Derick Eddington (derick-eddington) wrote : Re: [Bug 309223] Re: expansion of splicing let-syntax needs revision

On Thu, 2008-12-18 at 16:16 +0000, leppie wrote:
> Scary! I dont think I have ever come across it, but then again, I am
> not too comfortable with let-syntax and friends either still. :)

I used to think they are exotic and more complicated than they are.
They just bind identifiers to macro transformers, just like
define-syntax, but with the region of the bindings limited, and their
body is just like begin so it can have defines that get spliced. Take a
look at xitomatl/{alists,define,fuego}.sls for the simple way I've used
let-syntax so far.

Revision history for this message
Michael D. Adams (mdmkolbe) wrote :

Just to be clear, would the following still be legal?

(let ()
  (let-syntax ([foo (identifier-syntax 12)])
    (define-syntax x (lambda (stx) #`(+ 3 #,foo))))
  x)
=> 15

or would I still have to pull the define syntax to the outer layer like so?

(let ()
  (define-syntax x
    (let-syntax ([foo (identifier-syntax 12)])
      (lambda (stx) #`(+ 3 #,foo))))
  x)
=> 15

Revision history for this message
leppie (leppie) wrote :

I think the required behaviour is almost like the 2nd example.

Here is how I think it should behave:

(let ()
  (define-syntax x
    (let-syntax ([foo (identifier-syntax 12)])
      (lambda (stx) #'foo)))
  x)
=> error "identifier out of context" 'foo

Revision history for this message
Abdulaziz Ghuloum (aghuloum) wrote :

On Dec 20, 2008, at 11:45 AM, Michael D. Adams wrote:

> Just to be clear, would the following still be legal?
>
> (let ()
> (let-syntax ([foo (identifier-syntax 12)])
> (define-syntax x (lambda (stx) #`(+ 3 #,foo))))
> x)
> => 15

Yes.

This is the same as:

(let ()
   (let-syntax ([foo (identifier-syntax 12)])
     (define-syntax x (lambda (stx) (list #'+ #'3 foo))))
   x)

which is the same as:

(let ()
   (define-syntax x (lambda (stx) (list #'+ #'3 #'12)))
   x)

which is the same as:

(let ()
   (+ 3 12))

Aziz,,,

Revision history for this message
Abdulaziz Ghuloum (aghuloum) wrote :

On Dec 20, 2008, at 12:13 PM, leppie wrote:

> I think the required behaviour is almost like the 2nd example.
>
> Here is how I think it should behave:
>
> (let ()
> (define-syntax x
> (let-syntax ([foo (identifier-syntax 12)])
> (lambda (stx) #'foo)))
> x)
> => error "identifier out of context" 'foo

Your example is different from Michael's.

His is closer to:

(let ()
   (define-syntax x
     (let-syntax ([foo (identifier-syntax 12)])
       (lambda (stx) foo))) ;;; no #'
   x)

which is the same as:

(let ()
   (define-syntax x (lambda (stx) 12))
   x)

which is the same as:

(let ()
   12)

Aziz,,,

Revision history for this message
leppie (leppie) wrote :

Here is a variation on the theme:

#!r6rs
(import (rnrs))

(define lit 41)

(define-syntax foo
 (syntax-rules (lit)
   ((_ lit)
    (syntax-rules () ((_) lit)))))

(let ((lit2 42))
  (let-syntax ((z (foo lit)))
    (display (z))))

This should not run.

Changing lit2 to lit raises what seems an incorrect error.

Cheers

leppie

Revision history for this message
Abdulaziz Ghuloum (aghuloum) wrote :

On Jun 25, 2009, at 9:19 PM, leppie wrote:

> #!r6rs
> (import (rnrs))
>
> (define lit 41)
>
> (define-syntax foo
> (syntax-rules (lit)
> ((_ lit)
> (syntax-rules () ((_) lit)))))
>
> (let ((lit2 42))
> (let-syntax ((z (foo lit)))
> (display (z))))
>
> This should not run.

Why not?

> Changing lit2 to lit raises what seems an incorrect error.

Huh? What do you mean incorrect error.
(let ((lit 42)) (foo lit)) should *not* match the rule for foo
since the two "lit"s are not free-identifier=?.

Aziz,,,

Revision history for this message
leppie (leppie) wrote :

> Why not?

'foo' is being used out of context (in both cases), all non-psyntax R6RS implementations agree on this, as well the expected behavior of non-R6RS (I asked on IRC, as I thought incorrectly that this was an implicit phasing issue).

> Huh? What do you mean incorrect error.
> (let ((lit 42)) (foo lit)) should *not* match the rule for foo
> since the two "lit"s are not free-identifier=?.

The incorrect error should be 'foo' being used out of context, not a match failure.

Cheers

leppie

Revision history for this message
Abdulaziz Ghuloum (aghuloum) wrote :

On Jun 26, 2009, at 8:06 AM, leppie wrote:

>> Why not?
>
> 'foo' is being used out of context (in both cases),

??

> all non-psyntax R6RS implementations agree on this,

That's not a good reason to add a restriction to Ikarus.
There is no reason why a compile-time entity (a macro)
cannot be used at compile time.

> as well the expected behavior of non-R6RS

Huh? What non-R6RS are you talking about?

Aziz,,,

Revision history for this message
leppie (leppie) wrote :

On Fri, Jun 26, 2009 at 8:19 AM, Abdulaziz Ghuloum <email address hidden>wrote:

>
> >> Why not?
> >
> > 'foo' is being used out of context (in both cases),
>
> ??
>
> > all non-psyntax R6RS implementations agree on this,
>
> That's not a good reason to add a restriction to Ikarus.
> There is no reason why a compile-time entity (a macro)
> cannot be used at compile time.
>
> > as well the expected behavior of non-R6RS
>
> Huh? What non-R6RS are you talking about?
>

I'm no language lawyer, but according to Taylor R. Campbell for R5RS, the
identifier should be out of context (I did not test this), just as I did see
in all other R6RS's I tested (PLT, Larceny, Ypsilon).

I will investigate and gather some more information.

Cheers

leppie

Revision history for this message
Abdulaziz Ghuloum (aghuloum) wrote :

On Jun 26, 2009, at 11:55 AM, leppie wrote:

> I'm no language lawyer, but according to Taylor R. Campbell for R5RS,
> the identifier should be out of context (I did not test this), just as
> I did see in all other R6RS's I tested (PLT, Larceny, Ypsilon).

R5RS only specifies the behavior when the "syntax-rules" appears on
the right-hand-side of {let,letrec,define}-syntax. It says nothing
about what happens when something else (e.g., (foo)) appears there.

All implementations of psyntax (the current R6RS one, as well as the
original one) allow macros to be used in both variable and syntax
bindings. All implementations that use psyntax, even non-R6RS ones,
follow the same semantics (try sisc, guile, chicken's psyntax egg,
gambit, to name a few). Chez Scheme's R6RS libraries also allow it.

Even if R6RS disallows it (which I doubt it would, since the whole
macro business is so loosy-goosy), that still does not make a good
case. That would be just an arbitrary restriction since Ikarus's
behavior is a demonstration for why such restriction need not be
required.

> I will investigate and gather some more information.

I don't see the point of that since it's very unlikely that anything
will change w.r.t. this issue. I am not going to require writing
auxiliary libraries for the sole purpose of making a macro available
at syntax definitions. If the other implementations require it, and
you want to run your code on these implementations, then by all means
do split your libraries and don't forget to add the appropriate phase
declarations.

Aziz,,,

To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.