unofficial mirror of guile-devel@gnu.org 
 help / color / mirror / Atom feed
* Internal defines
@ 2003-11-09 22:40 Dirk Herrmann
  2003-11-11  2:21 ` Rob Browning
  0 siblings, 1 reply; 6+ messages in thread
From: Dirk Herrmann @ 2003-11-09 22:40 UTC (permalink / raw)


Hi folks,

Guile currently chokes on the following form:

  (defmacro a forms
    (cons 'define forms))
  (let ((c identity) (x #t))
    (define (a x y) (and x y))
    (a (c x) (c x))))

According to R5RS, the body of a form like lambda, let, let* etc. looks 
like follows:

<body> --> <definition>* <sequence>
<sequence> --> <command>* <expression>
<command> --> <expression>
<definition> --> (define <variable> <expression>)
      | (define (<variable> <def formals>) <body>)
      | (begin <definition>*)

That is, it starts with zero or more definitions followed by one or more 
expressions.
The definition forms must start with the literal symbol 'define' or 
'begin', which
may enclose further definitions or begin forms.  In any case, there is 
no mentioning
of macro expansion here.

In other words, the examle code above should return #t, because the 
expression
(a (c x) (c x)) refers to the internal define rather than to the outer 
macro.
Guile, however, has up to now performed macro expansion before checking 
whether the
form is a definition.  Thus, the example above returns an error, since Guile
interprets (a (c x) (c x)) as a macro application, in this case a 
definition.
The body then (according to Guile's interpretation) consists only of 
definitions.

The above example also shows that it is no good practice to define 
macros that
expand into definitions.  Messing with 'define' always means to play 
around with
one of scheme's most basic syntactical structures.  The optargs 
implementation
of define* is an example for a macro that expands to a 'define' form.  
According
to R5RS and as demonstrated by the above example, such macros are 
confusing, and
Guile's current implementation breaks code that already has a meaning 
with respect
to R5RS.

I am about to submit a patch that fixes Guile's behaviour, such that the 
example
above would work.  This means, that there is not macro expansion 
performed prior
to detecting the internal defines.  I want, however, to check with you 
before doing
so, since it is likely to break existing code.  In the long term, just 
to mention
it early, I would also like to fix Guile's code such that it also 
handles top-level
defines correctly, since there a similar problem applies.

Best regards
Dirk Herrmann




_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-devel


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

* Re: Internal defines
  2003-11-09 22:40 Internal defines Dirk Herrmann
@ 2003-11-11  2:21 ` Rob Browning
  2003-11-11  3:11   ` Tom Lord
  0 siblings, 1 reply; 6+ messages in thread
From: Rob Browning @ 2003-11-11  2:21 UTC (permalink / raw)
  Cc: Marius Vollmer, Guile-Devel Mailing List

Dirk Herrmann <dirk@dirk-herrmanns-seiten.de> writes:

> In other words, the examle code above should return #t, because the
> expression (a (c x) (c x)) refers to the internal define rather than
> to the outer macro.  Guile, however, has up to now performed macro
> expansion before checking whether the form is a definition.  Thus,
> the example above returns an error, since Guile interprets (a (c x)
> (c x)) as a macro application, in this case a definition.  The body
> then (according to Guile's interpretation) consists only of
> definitions.

Hmm, so just to clarify, you're arguing against a rigid "read, expand,
eval" process, and in favor of considering the context of expansions
before deciding whether or not to expand?

If so, could you elaborate a bit more on the justification for either
choice?  Note that I'm not at all predisposed against your
position[1]; I'd just like to make sure I understand the rationale(s).

Thanks

[1] though I'm not sure I would have been completely surprised by a
macro taking effect before anything else.

-- 
Rob Browning
rlb @defaultvalue.org and @debian.org; previously @cs.utexas.edu
GPG starting 2002-11-03 = 14DD 432F AE39 534D B592  F9A0 25C8 D377 8C7E 73A4


_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-devel


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

* Re: Internal defines
  2003-11-11  2:21 ` Rob Browning
@ 2003-11-11  3:11   ` Tom Lord
  2003-11-11  3:50     ` David Van Horn
  0 siblings, 1 reply; 6+ messages in thread
From: Tom Lord @ 2003-11-11  3:11 UTC (permalink / raw)
  Cc: guile-devel, mvo




Dirk wrote:



  According to R5RS, the body of a form like lambda, let, let*
  etc. looks like follows:

  <body> --> <definition>* <sequence>
  <sequence> --> <command>* <expression>
  <command> --> <expression>
  <definition> --> (define <variable> <expression>)
  | (define (<variable> <def formals>) <body>)
  | (begin <definition>*)

  That is, it starts with zero or more definitions followed by one or
  more expressions.  The definition forms must start with the literal
  symbol 'define' or 'begin', which may enclose further definitions or
  begin forms. In any case, there is no mentioning of macro expansion
  here.


Dirk is wrong.   

(By striking coincidence, I recently spent about 6 hours figuring this
out myself.  In my personal experience, it is hella easy to be wrong
on this topic :-)

R5RS is not strikingly crystal clear on this matter, but it _does_
speak of macro expansion in this context and actually provides a
coherent and reasonable semantic.

The critical section is "5.3 Syntax definitions":

    Although macros may expand into definitions and syntax definitions
    in any context that permits them, it is an error for a definition
    or syntax definition to shadow a syntactic keyword whose meaning
    is needed to determine whether some form in the group of forms
    that contains the shadowing definition is in fact a definition,
    or, for internal definitions, is needed to determine the boundary
    between the group and the expressions that follow the group. For
    example, the following are errors:

Key here is "macros may expand into definitions and syntax definitions
in _any_ context that permits them" [emphasis added].

Thus, this is quite legal:

  (let-syntax
    ((foo (syntax-rules ()
            ((foo (proc args ...) body ...)
             (define proc
               (lambda (args ...)
                 body ...))))))
    (let ((x 3))
      (foo (plus x y) (+ x y))
      (define bar x)
      (plus bar x)))

  => 6

(which contradicts Dirk's reading).



On the other hand, as noted by the spec, this is "an error"

  (let-syntax
    ((foo (syntax-rules ()
            ((foo (proc args ...) body ...)
             (define proc
               (lambda (args ...)
                 body ...))))))
    (let ((x 3))
      (foo (plus x y) (+ x y))
      (define foo x)
      (plus foo x)))

because, looking at the contents of the LET, we can expand FOO and
realize that that is apparently a definition, but the subsequent
DEFINE of FOO undermines that interpretation since it's scope
encompasses the apparent macro-use of FOO (c.f. the "determining
boundaries" foo in the language from 5.3 quoted above).

Guile currently does not detect that error and simply returns 6 for
the second, error-laden, form.  Thus, Guile's conformance is saved in
this instance by the distinction between "is an error" and "an error
is signaled".

It is _slightly_ intimidating to think of what would be required of an
implementation, especially an SCM-derived implementation, to actually
detect that error.   Overall, Guile suffers from the sin of SCM -- of
not making expansion and evaluation separate phases.

Whether or not the unambiguous (but obscure) english language of 5.3
is born out by the "authoritative" denotational semantics is a
question I haven't investigated.   But I think it is crystal clear
(once the subtleties understodd) that if the denotational semantics do
not support 5.3 then the denotational semantics have a bug.

There _is_, denotational semantics notwithstanding, a quite clear
operational interpretation here in which the successive forms in the
"body" (not <body>) of the LET are expanded and then interpreted.
However, to actually detect and report the "an error", the operational
semantics has to include an observence of what head forms arise during
the expansion of forms that might or might not be part of the
<definition>s of the LET.


-t


_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-devel


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

* Re: Internal defines
  2003-11-11  3:11   ` Tom Lord
@ 2003-11-11  3:50     ` David Van Horn
  2003-11-11  4:22       ` Tom Lord
  2003-11-11  4:33       ` Tom Lord
  0 siblings, 2 replies; 6+ messages in thread
From: David Van Horn @ 2003-11-11  3:50 UTC (permalink / raw)
  Cc: mvo, guile-devel, rlb

Tom Lord wrote:
> But I think it is crystal clear (once the subtleties understodd) that if the
> [R5RS] denotational semantics do not support [R5RS] 5.3 then the
> denotational semantics have a bug.

The denotational semantics given by R5RS are for primitive expressions and
selected built-in procedures of the language that the macro system must
transform programs into; it makes no sense for the DS to make mention of
macros and their errors.

The fact that there is no formal semantics for the syntax transformation
language is sad and would be a welcome addition to R6RS, IMO.

-d



_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-devel


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

* Re: Internal defines
  2003-11-11  3:50     ` David Van Horn
@ 2003-11-11  4:22       ` Tom Lord
  2003-11-11  4:33       ` Tom Lord
  1 sibling, 0 replies; 6+ messages in thread
From: Tom Lord @ 2003-11-11  4:22 UTC (permalink / raw)
  Cc: mvo, guile-devel, rlb


    > From: David Van Horn <dvanhorn@cs.uvm.edu>

    > Tom Lord wrote:
    > > But I think it is crystal clear (once the subtleties understodd) that if the
    > > [R5RS] denotational semantics do not support [R5RS] 5.3 then the
    > > denotational semantics have a bug.

    > The denotational semantics given by R5RS are for primitive expressions and
    > selected built-in procedures of the language that the macro system must
    > transform programs into; it makes no sense for the DS to make mention of
    > macros and their errors.

    > The fact that there is no formal semantics for the syntax transformation
    > language is sad and would be a welcome addition to R6RS, IMO.

One way to do that is to add sufficiently to the set of primitive
expressions and built-in procedures so that macros can be explained
operationally (as a translation into those core elements carried out
by an explicit expand-phase that precedes evaluation).

If you'll forgive the self-promotion, please watch for the upcoming
Pika Scheme announcement on c.l.s. (sometime this month) which does
exactly that.   In a not unrelated fashion, Pika provides a foundation
for module systems.


-t



_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-devel


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

* Re: Internal defines
  2003-11-11  3:50     ` David Van Horn
  2003-11-11  4:22       ` Tom Lord
@ 2003-11-11  4:33       ` Tom Lord
  1 sibling, 0 replies; 6+ messages in thread
From: Tom Lord @ 2003-11-11  4:33 UTC (permalink / raw)
  Cc: mvo, guile-devel, rlb


    > From: Tom Lord <lord@emf.net>

    > Guile currently does not detect that error and simply returns 6 for
    > the second, error-laden, form.  Thus, Guile's conformance is saved in
    > this instance by the distinction between "is an error" and "an error
    > is signaled".

    > It is _slightly_ intimidating to think of what would be required of an
    > implementation, especially an SCM-derived implementation, to actually
    > detect that error.   Overall, Guile suffers from the sin of SCM -- of
    > not making expansion and evaluation separate phases.

I just wanted to add that the SCM-family's approach to macros _is_
intrinsicly useful -- as a kind of primitive for implementing
graph-rewriting systems -- even though it's not (without extreme
contortions) appropriate for Scheme macros.

It might be fun to see if someone can make a useful normal-order
evaluation functional langauge using SCM's defmacro facility....


-t



_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-devel


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

end of thread, other threads:[~2003-11-11  4:33 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2003-11-09 22:40 Internal defines Dirk Herrmann
2003-11-11  2:21 ` Rob Browning
2003-11-11  3:11   ` Tom Lord
2003-11-11  3:50     ` David Van Horn
2003-11-11  4:22       ` Tom Lord
2003-11-11  4:33       ` Tom Lord

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).