From: Stephan BRUNESSAUX
Subject: Common Lisp Problems with Hash-table in Macros
Date: 
Message-ID: <698@crin.crin.fr>
Hi,

Is there anybody out there who can explain me
what is wrong with this example which correctly
runs in both interpreted and compiled mode on
Symbolics 3620 (Genera 7.2)
and correctly ONLY in interpreted mode on TI Explorer II
and on VAX running KCL (June 3, 1987) but not in compiled
mode !?... 

First Part:

Here is the code of a macro-function (TEST)
generating a list and a function (AUX)
to manipulate it.
Everything is okay.

   |   >(defmacro test (a b)
   |       (let ((my-list (list a b)))
   |         `(defun aux ()
   |             (mapc #'print ',my-list))))
   |   TEST
   |   
   |   >(ed "test.lsp")
   |   
   |        (test c b)   ; macro call to compile
   |   
   |        "test.lsp" [New file] 2 lines, 14 characters 
   |   
   |   >(compile-file "test")
   |   Compiling test.lsp.
   |   End of Pass 1.  
   |   End of Pass 2.  
   |   OPTIMIZE levels: Safety=0 (No runtime error checking), Space=0, Speed=3
   |   Finished compiling test.lsp.
   |   
   |   >(load "test")
   |   Loading test.o
   |   Finished loading test.o
   |   276
   |   
   |   >(aux)
   |   
   |   C
   |   B
   |   (C B)

SECOND PART:
Here come the problems. 
Now, we generate a hash-table
instead of a list.

   |   >(defmacro test (a b)  
   |      (let ((table (make-hash-table :size 1)))
   |        (setf (gethash a table) b)
   |        `(defun aux () 
   |           (maphash #'(lambda (key val) 
   |                        (format t "key: ~a - val: ~a~%" key val)) 
   |                    ',table))))
   |   TEST
   |   
   
Just try before compile.
   
   |   >(test f e)
   |   AUX
   |   
   |   >(aux)
   |   key: F - val: E					
   |   NIL            

(aux) returns :
NIL with KCL and with SYMBOLICS
#<EQL-HASH-TABLE 3625625> on TI EXPLORER


On kcl :

   |   >(compile-file "test")
   |   Compiling test.lsp.
   |   End of Pass 1.  
   |   End of Pass 2.  
   |   OPTIMIZE levels: Safety=0 (No runtime error checking), Space=0, Speed=3
   |   Finished compiling test.lsp.
   |   
   |   >(load "test")
   |   Loading test.o
   |   
   |   Error: The default dispatch macro signalled an error.
   |   Error signalled by LOAD.
   |   
   |   Broken at LOAD.  Type :H for Help.
   |   >>:b
   |   Backtrace:  > eval > LOAD
   |   
   |   >>:q

On Explorer II :

   |   > (aux)
   |   
   |   >>Trap #o50151 (WRITE-READ-ONLY M-T)
   |   There was an attempt to write into 3031065, which is a read-only address;
   |   the code was probably trying to modify a program constant.


On Symbolics :

   |   >(aux)key: F - val: G
   |   NIL

From: Bruce Krulwich
Subject: Answer to the Macro question
Date: 
Message-ID: <45230@yale-celray.yale.UUCP>
In article <···@crin.crin.fr>, ·······@crin (Stephan BRUNESSAUX) writes:
>Is there anybody out there who can explain me what is wrong with this example
>which correctly runs in both interpreted and compiled mode on Symbolics 3620
>(Genera 7.2) and correctly ONLY in interpreted mode on TI Explorer II and on
>VAX running KCL (June 3, 1987) but not in compiled mode !?...
...
>Here come the problems. 
>Now, we generate a hash-table
>instead of a list.
>   |   >(defmacro test (a b)  
>   |      (let ((table (make-hash-table :size 1)))
>   |        (setf (gethash a table) b)
>   |        `(defun aux () 
>   |           (maphash #'(lambda (key val) 
>   |                        (format t "key: ~a - val: ~a~%" key val)) 
>   |                    ',table))))
>   |   TEST
 [ A transcript showing it working interpreted but not compiled ]

I think that your problem is that you're creating the hash table at macro
expansion time instead of at execution time.  Obviously this will (almost
definitely) work in interpreted mode, because the two environments are the
same.  However, when compiling a file, the compiler is expected to create
the object at COMPILE time, save it into the file (perhaps including any 
other information that's associated with it), and load it correctly when 
loading the file.  I'm just impressed that Symbolics was able to handle it.

As a fix, I suggest that you change the above macro to:

   |    (defmacro test (a b)  
   |      `(let ((table (make-hash-table :size 1)))
   |         (setf (gethash ,a table) ,b)
   |         (defun aux () 
   |           (maphash #'(lambda (key val) 
   |                        (format t "key: ~a - val: ~a~%" key val)) 
   |                    ',table))))

For interpreted code this will make no difference.  For compiled code it will
cause the hash table to be generated at load time, and thus the references
to the table from within the compiled code will be correct.


Bruce Krulwich
From: Sandra J Loosemore
Subject: Re: Common Lisp Problems with Hash-table in Macros
Date: 
Message-ID: <739@wasatch.UUCP>
In article <···@crin.crin.fr> ·······@crin.crin.fr (Stephan BRUNESSAUX) writes:
>
>Is there anybody out there who can explain me
>what is wrong with this example which correctly
>runs in both interpreted and compiled mode on
>Symbolics 3620 (Genera 7.2)
>and correctly ONLY in interpreted mode on TI Explorer II
>and on VAX running KCL (June 3, 1987) but not in compiled
>mode !?... 
>
>   |   >(defmacro test (a b)  
>   |      (let ((table (make-hash-table :size 1)))
>   |        (setf (gethash a table) b)
>   |        `(defun aux () 
>   |           (maphash #'(lambda (key val) 
>   |                        (format t "key: ~a - val: ~a~%" key val)) 
>   |                    ',table))))
>   |   TEST
>   |   
>   

As it happens, this exact problem is under discussion on the
cl-compiler mailing list.  The problem is that your macro expansion
includes a quoted hash table, and not all Common Lisp implementations
currently know how to compile constant hash tables.  There is also a
fundamental problem involved: since the compiler is allowed to
"collapse" or coalesce EQUAL substructures, there is a possibility
that an EQ or EQL hash table may compile into one with fewer entries!
Another complication is that (as I understand it) KCL's compiler works
by PRINTing constant data structures to a file, and CLtL does not
require hash tables to print in such a way that they can be read in
again.  

In short, you'll have to treat it as "an error" to compile quoted hash
tables.  The ANSI Common Lisp standard may end up specifying some
other, more useful behavior, but that won't be of much use to you in
the near term. 

-Sandra Loosemore (······@cs.utah.edu)
From: Jeff Dalton
Subject: Re: Common Lisp Problems with Hash-table in Macros
Date: 
Message-ID: <393@aipna.ed.ac.uk>
In article <···@crin.crin.fr> ·······@crin.crin.fr (Stephan BRUNESSAUX) writes:
>Is there anybody out there who can explain me what is wrong with this
>example which correctly runs in both interpreted and compiled mode on
>Symbolics 3620 (Genera 7.2) and correctly ONLY in interpreted mode on
>TI Explorer II and on VAX running KCL (June 3, 1987) but not in compiled
>mode !?... 

>    >(defmacro test (a b)  
>       (let ((table (make-hash-table :size 1)))
>         (setf (gethash a table) b)
>         `(defun aux () 
>            (maphash #'(lambda (key val) 
>                         (format t "key: ~a - val: ~a~%" key val)) 
>                     ',table))))

The problem is that you're trying to compile some code that contains
aquoted hash table.  So, the compiler has to put a representation of
that hash table into the ".o" file.  In KCL, the hash table just gets
PRINTed and so looks like this:

   #<hash-table 0017a310>

When LOAD tries to read this, it calls READ which sees the # and calls
the reader for the # dispatching character macro.  It then sees the <
and signals an error.

I don't know what happens on the Explorer.
From: Michael R Hall
Subject: Re: Common Lisp Problems with Hash-table in Macros
Date: 
Message-ID: <290@nvuxh.UUCP>
In article <···@crin.crin.fr> ·······@crin.crin.fr (Stephan BRUNESSAUX) writes:
>Is there anybody out there who can explain me what is wrong with
>this example which correctly runs in both interpreted and compiled mode on
>Symbolics 3620 (Genera 7.2) and correctly ONLY in interpreted mode on TI 
>Explorer II and on VAX running KCL (June 3, 1987) but not in compiled 
>mode !?... [Example omitted]

The example works fine, both interpreted and compiled, in Sun
(Lucid) Common Lisp version 3.4.  The problem, therefore, is KCL. 
Many Common Lisp implementations have buggy lexical closures,
especially compiled.  I don't know why, since they're not all that
hard to implement.  I suspect the KCL compiler cannot generate proper
lexical closure code, even though the lexical closure in question
references no variables outside its body.  The first example
uses #'print, which works fine in KCL; the second example uses
#'(lambda (key val) [body omitted]) and the KCL compiler barfs.  I
suggest defining a function like this
   (defun foo (key val) [body omitted])
and then referencing it as #'foo.
This, of course, should not make a difference, but it may make all
the difference to a buggy version of Common Lisp.

If all else fails, simply leave part of the code uncompiled.
-- 
Michael R. Hall              |"I live in a country that I hate.  I live in a
···············@bellcore.COM | country where I want to shoot the politicians."
bellcore!nvuxh!hall          | - Peter Buck of R.E.M.
From: Bruce Krulwich
Subject: Re: Common Lisp Problems with Hash-table in Macros
Date: 
Message-ID: <45602@yale-celray.yale.UUCP>
In article <···@nvuxh.UUCP>, ····@nvuxh (Michael R Hall) writes:
>The example works fine, both interpreted and compiled, in Sun
>(Lucid) Common Lisp version 3.4.  The problem, therefore, is KCL. 
>Many Common Lisp implementations have buggy lexical closures,
>especially compiled.  I don't know why, since they're not all that
>hard to implement.  I suspect the KCL compiler cannot generate proper
>lexical closure code, even though the lexical closure in question
>references no variables outside its body.  The first example
>uses #'print, which works fine in KCL; the second example uses
>#'(lambda (key val) [body omitted]) and the KCL compiler barfs.  I
>suggest defining a function like this
>   (defun foo (key val) [body omitted])
>and then referencing it as #'foo.
>This, of course, should not make a difference, but it may make all
>the difference to a buggy version of Common Lisp.

I believe that the problem has nothing to do with references out of the
closure, or really anything to do with the closure handling itself.  I think
that the problem lies in creating a hash table (or possibly another complex
data structure) at COMPILE-TIME and loading it in with the compiled code.

This is slightly related to a discussion a while ago about the environment in
which code is compiled, and the effect of compilation on the environment.  In
this case you creating the hash table in the environment in which macros are
expanded, and then saving it into a file, referencing it from code compiled in
a seperate environment in the process.  It is much more straightforward to
move the creation into the expanded macro, thus creating the table at load
time (as I showed in my previous post).

Does anyone remember the outcome of the previous discussion on compiler
environments??  Is the example that started this discussion correct within
CL??


Bruce Krulwich
From: Jeff Dalton
Subject: Re: Common Lisp Problems with Hash-table in Macros
Date: 
Message-ID: <405@aipna.ed.ac.uk>
In article <···@nvuxh.UUCP> ···············@bellcore.COM (Michael R Hall) writes:
>The example works fine, both interpreted and compiled, in Sun
>(Lucid) Common Lisp version 3.4.  The problem, therefore, is KCL. 

That isn't necessarily so.  This is an area in which different
Common Lisps differ and also one that is not well-defined by 
CLtL.  Besides, it is not true, in general, that when two
Common Lisp agree they are necessarily right.  KCL tends to
be a fairly minimal Common Lisp, in that it doesn't do much
beyond what's explicitly said in CLtL, and was developed by
people who knew less of the "shared cultural background"
that informs many American Common Lisps.  (For example, Mac
Lisp stored compiled constants in non-printed form, but I
don't think anything in CLtL says that is necessary.) So KCL
sometimes differs without necessarily being wrong.

>Many Common Lisp implementations have buggy lexical closures,
>especially compiled.  I don't know why, since they're not all that
>hard to implement.  I suspect the KCL compiler cannot generate proper
>lexical closure code, even though the lexical closure in question
>references no variables outside its body.  

As far as I can tell, KCL can compile code with #'(lambda ...) in
it.  Besides, I know the problem is due to something else, as
explained in an earlier message.  Your suspicion was a reasonable
one but happens to be wrong as far as KCL is concerned.