unofficial mirror of bug-guile@gnu.org 
 help / color / mirror / Atom feed
* Re: Bug with macros in SCM and Guile
       [not found] <5D389A9F-1903-4B48-970C-6D704EA11764@iro.umontreal.ca>
@ 2007-01-07  3:42 ` Aubrey Jaffer
  2007-01-15 22:35   ` Kevin Ryde
  2007-01-07  4:12 ` Aubrey Jaffer
  1 sibling, 1 reply; 4+ messages in thread
From: Aubrey Jaffer @ 2007-01-07  3:42 UTC (permalink / raw)
  Cc: bug-guile, Radey Shouman

 | From: Marc Feeley <feeley@iro.umontreal.ca>
 | Date: Wed, 29 Nov 2006 15:58:57 -0500
 | 
 | -----BEGIN PGP SIGNED MESSAGE-----
 | Hash: SHA1
 | 
 | Dear Aubrey and Guile developers, I have found a nasty bug in SCM's  
 | and Guile's macro expansion algorithm.

Which specification does the behavior violate?

 | The code that reproduces the bug is attached below.  This example
 | is an extremely condensed fragment of a portable namespace
 | management system I am developing (it is currently working in 10
 | other implementations of Scheme and I would like to add SCM and
 | Guile to that list).  The example contains 2 definitions for the
 | macro foo, and macro calls to foo between the two definitions.  The
 | problem is that the first definition is not always the one that is
 | used to expand the macro calls.  I expected the expansion to be
 | done sequentially (top-down) using the current definition of the
 | macro foo (in this case always the first definition).
 | 
 | For SCM it seems that a macro call is normally expanded when an  
 | expression is encountered in a top-down traversal of the code, but  
 | not always.  For example, in the function bar2 below the macro call  
 | to foo is expanded when bar2 is *called*, and at that point a new  
 | definition of the macro foo has been introduced.
 | 
 | Apparently Guile consistently expands macro calls when they are  
 | evaluated (only the first time I suppose).  In the example, this  
 | leads to the strange consequence that bar1 and bar3 behave  
 | differently even though they are defined the same.
 | 
 | Note that in my real code, the code is split into 2 files and each  
 | file only defines the macro once.  Imagine in the code below that  
 | file1 contains the code up to but not including the second defmacro,  
 | and file2 contains the code starting at the second defmacro.
 | 
 | Perhaps it is too difficult to fix this bug.  However I would be  
 | quite happy with a special form to force macro expansion, i.e.  
 | something like
 | 
 |    (define f
 |      (fully-expand-now
 |        (lambda (arg1 ...)
 |           ...)))
 | 
 | Is something like this possible?

Yes, using SLIB's DEFMACRO:EXPAND*
(http://swiss.csail.mit.edu/~jaffer/slib_3.html#SEC23)

  (require 'defmacroexpand)
  (slib:eval (defmacro:expand* '(begin
  (defmacro foo (x)
     (display "expanding-foo-version1\n")
     `(list 'foo-v1 ',x))

  (define (bar1)    (foo in-bar1))
  (define (bar2) #f (foo in-bar2))
  (define (bar3)    (foo in-bar3))

  (write (bar1)) (newline)

  (defmacro foo (x)
     (display "expanding-foo-version2\n")
     `(list 'foo-v2 ',x))

  (write (bar2)) (newline)
  (write (bar3)) (newline)
  )))

SCM-5e3 Prints:

  expanding-foo-version2
  expanding-foo-version2
  expanding-foo-version2
  (foo-v2 in-bar1)
  (foo-v2 in-bar2)
  (foo-v2 in-bar3)

But Guile-1.6.7 Prints:

  expanding-foo-version1
  (foo-v1 in-bar1)
  expanding-foo-version2
  (foo-v2 in-bar2)
  expanding-foo-version2
  (foo-v2 in-bar3)

Hmm...  Lets look at how the program is transformed:

  (require 'pretty-print)
  (pretty-print (defmacro:expand* '(begin
  (defmacro foo (x)
     (display "expanding-foo-version1\n")
     `(list 'foo-v1 ',x))

  (define (bar1)    (foo in-bar1))
  (define (bar2) #f (foo in-bar2))
  (define (bar3)    (foo in-bar3))

  (write (bar1)) (newline)

  (defmacro foo (x)
     (display "expanding-foo-version2\n")
     `(list 'foo-v2 ',x))

  (write (bar2)) (newline)
  (write (bar3)) (newline)
  )))

SCM-5e3 prints:

  (begin
    (defmacro:simple-defmacro
      foo
      scm:G20
      (let ((scm:G21 scm:G20))
	(let ((x (car scm:G21)))
	  (display "expanding-foo-version1
  ")
	  `(list 'foo-v1 ',x))))
    (define (bar1) (foo in-bar1))
    (define (bar2) #f (foo in-bar2))
    (define (bar3) (foo in-bar3))
    (write (bar1))
    (newline)
    (defmacro:simple-defmacro
      foo
      scm:G22
      (let ((scm:G23 scm:G22))
	(let ((x (car scm:G23)))
	  (display "expanding-foo-version2
  ")
	  `(list 'foo-v2 ',x))))
    (write (bar2))
    (newline)
    (write (bar3))
    (newline))

Guile-1.6.7 Prints:

  (begin
    (eval-case
      ((load-toplevel)
       (define foo
	 (defmacro:transformer
	   (lambda (x)
	     (display "expanding-foo-version1
  ")
	     `(list 'foo-v1 ',x)))))
      (else (error "defmacro can only be used at the top level")))
    (define (bar1) (foo in-bar1))
    (define (bar2) #f (foo in-bar2))
    (define (bar3) (foo in-bar3))
    (write (bar1))
    (newline)
    (eval-case
      ((load-toplevel)
       (define foo
	 (defmacro:transformer
	   (lambda (x)
	     (display "expanding-foo-version2
  ")
	     `(list 'foo-v2 ',x)))))
      (else (error "defmacro can only be used at the top level")))
    (write (bar2))
    (newline)
    (write (bar3))
    (newline))

So the difference seems to be in how DEFMACRO is implemented in the
two implementations.


_______________________________________________
Bug-guile mailing list
Bug-guile@gnu.org
http://lists.gnu.org/mailman/listinfo/bug-guile


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

* Re: Bug with macros in SCM and Guile
       [not found] <5D389A9F-1903-4B48-970C-6D704EA11764@iro.umontreal.ca>
  2007-01-07  3:42 ` Bug with macros in SCM and Guile Aubrey Jaffer
@ 2007-01-07  4:12 ` Aubrey Jaffer
  1 sibling, 0 replies; 4+ messages in thread
From: Aubrey Jaffer @ 2007-01-07  4:12 UTC (permalink / raw)
  Cc: bug-guile, Radey Shouman

If we take the first DEFMACRO out of the begin, then macro expansion
works correctly in both SCM and Guile:

  bash-3.1$ slib guile
  guile> (require 'defmacroexpand)
  guile> (require 'pretty-print)
  guile> (defmacro foo (x)
     (display "expanding-foo-version1\n")
     `(list 'foo-v1 ',x))
  guile> (pretty-print (defmacro:expand* '(begin
  (define (bar1)    (foo in-bar1))
  (define (bar2) #f (foo in-bar2))
  (define (bar3)    (foo in-bar3))
  (write (bar1)) (newline)
  (defmacro foo (x)
     (display "expanding-foo-version2\n")
     `(list 'foo-v2 ',x))
  (write (bar2)) (newline)
  (write (bar3)) (newline)
  )))

Guile prints:

  expanding-foo-version1
  expanding-foo-version1
  expanding-foo-version1

  (begin
    (define (bar1) (list 'foo-v1 'in-bar1))
    (define (bar2) #f (list 'foo-v1 'in-bar2))
    (define (bar3) (list 'foo-v1 'in-bar3))
    (write (bar1))
    (newline)
    (eval-case
      ((load-toplevel)
       (define foo
	 (defmacro:transformer
	   (lambda (x)
	     (display "expanding-foo-version2
  ")
	     `(list 'foo-v2 ',x)))))
      (else (error "defmacro can only be used at the top level")))
    (write (bar2))
    (newline)
    (write (bar3))
    (newline))

SCM prints:

  expanding-foo-version1
  expanding-foo-version1
  expanding-foo-version1

  (begin
    (define (bar1) (list 'foo-v1 'in-bar1))
    (define (bar2) #f (list 'foo-v1 'in-bar2))
    (define (bar3) (list 'foo-v1 'in-bar3))
    (write (bar1))
    (newline)
    (defmacro:simple-defmacro
      foo
      scm:G21
      (let ((scm:G22 scm:G21))
	(let ((x (car scm:G22)))
	  (display "expanding-foo-version2
  ")
	  `(list 'foo-v2 ',x))))
    (write (bar2))
    (newline)
    (write (bar3))
    (newline))

In both cases, the definintions of the bar routines are expanded; so
subsequent DEFMACROs will have no effect on them.

It is disturbing that "expanding-foo-version1" is printed out when
DEFMACRO:EXPAND is expanding the code (both in SCM and Guile).  There
is no call to eval in "defmacex.scm".  How does this happen?


_______________________________________________
Bug-guile mailing list
Bug-guile@gnu.org
http://lists.gnu.org/mailman/listinfo/bug-guile


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

* Re: Bug with macros in SCM and Guile
  2007-01-07  3:42 ` Bug with macros in SCM and Guile Aubrey Jaffer
@ 2007-01-15 22:35   ` Kevin Ryde
  2007-01-16  2:26     ` Aubrey Jaffer
  0 siblings, 1 reply; 4+ messages in thread
From: Kevin Ryde @ 2007-01-15 22:35 UTC (permalink / raw)
  Cc: bug-guile

Aubrey Jaffer <agj@alum.mit.edu> writes:
>
>  | From: Marc Feeley <feeley@iro.umontreal.ca>
>  | Date: Wed, 29 Nov 2006 15:58:57 -0500
>  | 
>  | For SCM it seems that a macro call is normally expanded when an  
>  | expression is encountered in a top-down traversal of the code, but  
>  | not always.  For example, in the function bar2 below the macro call  
>  | to foo is expanded when bar2 is *called*, and at that point a new  
>  | definition of the macro foo has been introduced.

I thought that was the idea for defmacro, to expand when it runs, and
in fact to re-expand every time it's run.  A little wasteful, but it's
emulating lisp style (or is it just emacs-lisp style) in that isn't
it?


_______________________________________________
Bug-guile mailing list
Bug-guile@gnu.org
http://lists.gnu.org/mailman/listinfo/bug-guile


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

* Re: Bug with macros in SCM and Guile
  2007-01-15 22:35   ` Kevin Ryde
@ 2007-01-16  2:26     ` Aubrey Jaffer
  0 siblings, 0 replies; 4+ messages in thread
From: Aubrey Jaffer @ 2007-01-16  2:26 UTC (permalink / raw)
  To: user42; +Cc: bug-guile

 | From: Kevin Ryde <user42@zip.com.au>
 | Date: Tue, 16 Jan 2007 09:35:50 +1100
 | 
 | Aubrey Jaffer <agj@alum.mit.edu> writes:
 | >
 | >  | From: Marc Feeley <feeley@iro.umontreal.ca>
 | >  | Date: Wed, 29 Nov 2006 15:58:57 -0500
 | >  | 
 | >  | For SCM it seems that a macro call is normally expanded when
 | >  | an expression is encountered in a top-down traversal of the
 | >  | code, but not always.  For example, in the function bar2 below
 | >  | the macro call to foo is expanded when bar2 is *called*, and
 | >  | at that point a new definition of the macro foo has been
 | >  | introduced.
 | 
 | I thought that was the idea for defmacro, to expand when it runs,
 | and in fact to re-expand every time it's run.  A little wasteful,
 | but it's emulating lisp style (or is it just emacs-lisp style) in
 | that isn't it?

Looking at
http://www.cs.cmu.edu/Groups/AI/html/hyperspec/HyperSpec/Body/mac_defmacro.html
I don't see where it requires repeated evaluation.


_______________________________________________
Bug-guile mailing list
Bug-guile@gnu.org
http://lists.gnu.org/mailman/listinfo/bug-guile


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

end of thread, other threads:[~2007-01-16  2:26 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <5D389A9F-1903-4B48-970C-6D704EA11764@iro.umontreal.ca>
2007-01-07  3:42 ` Bug with macros in SCM and Guile Aubrey Jaffer
2007-01-15 22:35   ` Kevin Ryde
2007-01-16  2:26     ` Aubrey Jaffer
2007-01-07  4:12 ` Aubrey Jaffer

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