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