From mboxrd@z Thu Jan 1 00:00:00 1970 Path: main.gmane.org!not-for-mail From: Dirk Herrmann Newsgroups: gmane.lisp.guile.devel Subject: preparation for hygienic macro expansion Date: Sun, 24 Nov 2002 12:56:00 +0100 (CET) Sender: guile-devel-admin@gnu.org Message-ID: NNTP-Posting-Host: main.gmane.org Mime-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII X-Trace: main.gmane.org 1038139596 1287 80.91.224.249 (24 Nov 2002 12:06:36 GMT) X-Complaints-To: usenet@main.gmane.org NNTP-Posting-Date: Sun, 24 Nov 2002 12:06:36 +0000 (UTC) Return-path: Original-Received: from monty-python.gnu.org ([199.232.76.173]) by main.gmane.org with esmtp (Exim 3.35 #1 (Debian)) id 18FvX0-0000Kb-00 for ; Sun, 24 Nov 2002 13:06:34 +0100 Original-Received: from localhost ([127.0.0.1] helo=monty-python.gnu.org) by monty-python.gnu.org with esmtp (Exim 4.10) id 18FvP6-0007gt-00; Sun, 24 Nov 2002 06:58:24 -0500 Original-Received: from list by monty-python.gnu.org with tmda-scanned (Exim 4.10) id 18FvMv-0006gh-00 for guile-devel@gnu.org; Sun, 24 Nov 2002 06:56:09 -0500 Original-Received: from mail by monty-python.gnu.org with spam-scanned (Exim 4.10) id 18FvMq-0006cj-00 for guile-devel@gnu.org; Sun, 24 Nov 2002 06:56:08 -0500 Original-Received: from sallust.ida.ing.tu-bs.de ([134.169.132.52]) by monty-python.gnu.org with esmtp (Exim 4.10) id 18FvMp-0006bt-00 for guile-devel@gnu.org; Sun, 24 Nov 2002 06:56:03 -0500 Original-Received: from localhost (dirk@localhost) by sallust.ida.ing.tu-bs.de (8.9.3+Sun/8.9.1) with ESMTP id MAA28227; Sun, 24 Nov 2002 12:56:00 +0100 (CET) Original-To: Marius Vollmer , guile-devel@gnu.org Errors-To: guile-devel-admin@gnu.org X-BeenThere: guile-devel@gnu.org X-Mailman-Version: 2.0.11 Precedence: bulk List-Help: List-Post: List-Subscribe: , List-Id: Developers list for Guile, the GNU extensibility library List-Unsubscribe: , List-Archive: Xref: main.gmane.org gmane.lisp.guile.devel:1751 X-Report-Spam: http://spam.gmane.org/gmane.lisp.guile.devel:1751 Hi folks, [those who already know about Marius #:module-ref suggestion can skip the first half of this message ...] Guile up to now uses forms like the following (taken from boot-9.scm): (define define-private define) which is not legal R5RS scheme. A correct implementation would be (defmacro define-private args '(define ,@args)) I had attempted to rewrite all macro definitions into the defmacro form. However, with the CVS version of guile this does not work, as Mikael has pointed out: The problem is, that the defmacro syntax expansion does not work hygienically. If in some other module "foo" someone wants to use an own version of define, the following would break: (defmacro define args (if top-level `(define-public ,@args) `(define-private ,@args)) The expansion would work endlessly, since with the defmacro definition of define-private, define-private expands _literally_ to define, and not to the binding of define that was visible during the definition of define-private. That is, in module foo the expansion of define would be self-referential. This is not a theoretical example, but actually occurs in slib.scm. Currently, we don't have a solution for this. It requires to implement a hygienic macro expansion mechanism, which can cope with the existence of different modules. However, Marius has already suggested a mechanism which will support hygienic macro expansion as soon as it is available. Marius suggests to extend the input language accepted by guile, such that guile will understand the following expression: (#:module-ref ) This indicates that the binding for should be taken from the module . Note that #:module-ref is a _keyword_, that is, a special object type distinct from symbols. Therefore, the syntax above will not conflict with any other scheme expression. And, since the mechanism is hard-coded into the memoizer/evaluator, there is no chance for the user to shadow it by own definitions. The idea behind the special syntax above is, that the macro expander could issue such lookup-commands in order to make sure that symbols are looked up in the correct module. However, as long as the macro expander does not work hygienically and does not make use of this feature, it would be possible to instrument code manually with the corresponding instructions. For the example above, this would look like the following code: (defmacro define-private args '((#:module-ref (guile) define) ,@args)) that is, the binding for define shall be looked up in module (guile). During memoization, whenever such a #:module-ref instruction is detected, the memoizer checks, if the identifier is bound to a macro in the corresponding module. If so, macro expansion is performed. I have implemented the above instruction in my local version of guile, in the memoizer code. Here are some examples of how it works: A) guile> (#:module-ref (guile) define) ERROR: In procedure memoization: ERROR: In line 0: Misplaced syntactic keyword (#:module-ref (guile) define). ABORT: (syntax-error) This example shows, how during memoization the memoizer runs over the #:module-ref expression and does the corresponding lookup. Since in module (guile) the symbol define is a syntactic keyword, the code looks to the memoizer as if the following had been entered: guile> define and here the syntactic keyword appears at a place where an expression was expected. Thus, the error message about the misplaced syntactic keyword is issued. B) guile> (#:module-ref (guile) identity) # In this case, the symbol identity is looked up in module (guile), and guile's identity function is found. C) guile> (defmacro original-define args ... `((#:module-ref (guile) define) ,@args)) guile> (defmacro define args ... `(original-define ,@args)) guile> (define (foo) (display "foo works") (newline)) guile> (foo) foo works Try the same with: guile> (defmacro original-define args `(define ,@args)) guile> (defmacro define args `(original-define ,@args)) guile> (define (foo) (display "foo works") (newline)) and you will see :-) Now, I am wondering if one would need to distinguish between #:module-ref and #:module-syntax-ref. This would help a hygienc macro system to cope with the situation that in the referenced module after the definition of the macro the binding for the variable changes from macro to value or vice versa. Assume in the following examples that defmacro would work hygienically. in module foo: (define bar ) (defmacro baz args `(bar ,@args)) ;; baz should expand using the function-binding of bar (defmacro bar args #t) ;; baz should still expand using the function binding of bar, right? in module bla (assume that baz is imported): (baz #t) ;; this would in a first step be expanded to: ((#:module-ref (foo) bar) #t) ;; And now, we would like to make sure that the function-binding is ;; found, and not the syntax transformer. However, this does not seem ;; to be possible if there is only #:module-ref. In my current implementation, there is only #:module-ref. It would be simple, however, to add a #:module-syntax-ref directive as well. Marius, what do you think? Do we need two directives instead of one? Best regards, Dirk Herrmann _______________________________________________ Guile-devel mailing list Guile-devel@gnu.org http://mail.gnu.org/mailman/listinfo/guile-devel