[Larceny-users] Ticket 638

Derick Eddington derick.eddington at gmail.com
Tue Apr 21 03:04:22 EDT 2009


On Mon, 2009-04-20 at 22:04 -0400, Lynn Winebarger wrote:
> This ticket is pretty interesting:
> 
>   % cat temp2.sps
>   (import (for (rnrs) run expand)
>           (rename (only (rnrs base) cons) (cons kons)))
> 
>   (free-identifier=? #'cons #'kons)
>   % ./larceny --r6rs --program temp2.sps
> 
>   Syntax violation: invalid reference
> 
>   Attempt to use binding of cons in library (program~19XamJ~2) at
>   invalid level -1.  Binding is only available at levels: 0 1 2
> 
> Evidently this should evaluate to #t according to the PLT test suite.

For implicit phasing systems, such as Ikarus and Ypsilon, a result of #T
makes sense because any phase level specifications are ignored and
`cons' and `kons' are bound to the same thing at every phase.

But for explicit phasing systems, such as Larceny and PLT, I don't think
a result of #T makes sense because `cons' and `kons' are unbound at
phase -1 and unbound identifiers are compared according to their
spelling.  If they are supposed to be bound, that's either implicit
phasing or confusing syntax template semantics.

I've encountered this weirdness with PLT syntax templates before.  I
found it quite confusing and inconsistent that PLT's syntax templates'
identifiers are apparently not always (- phase 1) (even more explicit
phasing complications to scare people away from learning macros, yay!).
I think it's a bug in PLT because my code shown below has a syntax
template at phase 0 and the identifiers in it are certainly at phase -1
(because I made that the only possibility) and it works on PLT, which is
inconsistent with the PLT test suite program above.

> First, if it isn't clear, this is occuring because Andre's system is
> resolving the reflected identifier in the syntax form, regardless of
> whether the form is being evaluated on the right hand side of a syntax
> binding form (define-syntax etc).  That's why it reports the
> identifier being desired at level -1.

I think Larceny's phase mismatch detection is very preferable to
allowing separate namespaces (that would be very unSchemely) for
different phases such that `cons' would be allowed unbound at phase -1
but bound at the phases it's imported for.  And this detection is
consistent with the fact that R6RS requires preventing importing the
same name but different bindings at different phases.

> There are multiple issues:
> 1) The syntax violation is getting triggered too early.  

How can you tell?

> There's an
> echo of Will's complaint that R6RS requires compiling programs with
> obvious errors to give error messages at run-time

That temp2.sps is being compiled and run in the same process, so how can
you tell when the error is happening?  I think it probably actually is
happening at expand-time.

> 2) The binding is getting resolved too early.  It shouldn't be
> resolved until it appears on the right hand side of a syntax binding
> form.  Consider whether the following program should produce 'a or 7:

Because Scheme is lexically scoped and maintaining that is a primary
purpose of R6RS syntax templates, it's obvious to me that `foo' should
be bound to a syntax object representing the identifier `x' from the
lexical scope where that identifier occurs, and that identifier refers
to the `x' imported from `(defines x)'.

> (library (defines x) (export x) (import (rnrs))
> (define x 7))
> 
> (library (defines foo)
> (export foo)
> (import (rnrs) (rnrs syntax-case) (for (defines x) (meta -1)))
> (define foo (syntax x))
> )
> 
> (library (expands foo)
> (export foo-expander)
> (import (for (rnrs) run expand)
>         (for (rnrs syntax-case) run expand)
>         (for (defines foo) run expand))
> 
> (define x 'a)
> (define-syntax foo-expander
>   (lambda (x)
>     (syntax-case x ()
>       ((_) foo))))
> )
> 
> (import (expands foo))
> (foo-expander)
> 
> This test would imply 'a is the right answer.  

Ikarus, Larceny, PLT, and Ypsilon (which all have different
implementations of R6RS macros) all say the answer is 7.

> That preserves
> referential transparency at the site of the macro definiton, even
> though the identifier object is constructed outside that context.

I don't think it would preserve referential transparency because the
value of `foo' is a syntax object representing the identifier `x' from
the lexical scope where that identifier occurred.  Referential
transparency means an expression can be replaced with its value without
changing the semantics.  If you replaced the `foo' expression with its
value, it would be like importing the `x' from `(defines x)' with a
renamed name and referring to that renamed name.

I certainly want to be able to make helpers like in the below example
and know what their output is going to refer to.  (This is also the code
with the PLT syntax template phase level inconsistency I mentioned
above).

$ cat help/do-it.sls 
#!r6rs
(library (help do-it)
  (export do-it)
  (import (rnrs))
  (define (do-it x)
    (list x x)))
$ cat help/helper.sls 
#!r6rs
(library (help helper)
  (export helper)
  (import (rnrs)
          (for (help do-it) (meta -1)))
  (define (helper x)
    (quasisyntax (do-it (unsyntax x)))))
$ cat use-help.sps
#!r6rs
(import (rnrs)
        (for (help helper) expand))
(define do-it 'different)
(define-syntax m
  (lambda (stx)
    (syntax-case stx ()
      ((_ x) (helper (syntax x))))))
(write (m 1)) (newline)
$ ikarus --r6rs-script use-help.sps
(1 1)
$ larceny -path . -r6rs -program use-help.sps
(1 1)
$ plt-r6rs ++path . use-help.sps
(1 1)
$ ypsilon --sitelib . use-help.sps
(1 1)
$ 

IIUC, you're saying the syntax object returned from `helper' should
refer to the `do-it' in the program.  That would defeat the whole point
of hygienic macros.

> 3) It doesn't make a lot of sense to have free-identifier=? if you
> can't create a free identifier without triggering an expand time
> error.

You can do that.  Larceny's error is happening because the free
identifiers have imported bindings in scope but not at the right phase
level and so it's preventing separate namespaces from existing.

-- 
: Derick
----------------------------------------------------------------




More information about the Larceny-users mailing list