unofficial mirror of guile-devel@gnu.org 
 help / color / mirror / Atom feed
From: Tom Lord <lord@emf.net>
Cc: guile-devel@gnu.org, mvo@zagadka.de
Subject: Re: Internal defines
Date: Mon, 10 Nov 2003 19:11:18 -0800 (PST)	[thread overview]
Message-ID: <200311110311.TAA22963@morrowfield.regexps.com> (raw)
In-Reply-To: <87ekwf63xu.fsf@raven.i.defaultvalue.org> (message from Rob Browning on Mon, 10 Nov 2003 20:21:01 -0600)




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


  reply	other threads:[~2003-11-11  3:11 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2003-11-09 22:40 Internal defines Dirk Herrmann
2003-11-11  2:21 ` Rob Browning
2003-11-11  3:11   ` Tom Lord [this message]
2003-11-11  3:50     ` David Van Horn
2003-11-11  4:22       ` Tom Lord
2003-11-11  4:33       ` Tom Lord

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/guile/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=200311110311.TAA22963@morrowfield.regexps.com \
    --to=lord@emf.net \
    --cc=guile-devel@gnu.org \
    --cc=mvo@zagadka.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).