From: Larry Clapp
Subject: Unexpected behavior in CMU CL for Linux
Date: 
Message-ID: <99iiva.bgq.ln@127.0.0.1>
Under CMUCL 18c for Linux:

* (eq "x" "x")
NIL

* (let () (eq "x" "x"))
T

Any ideas as to why?

-- Larry



-----= Posted via Newsfeeds.Com, Uncensored Usenet News =-----
http://www.newsfeeds.com - The #1 Newsgroup Service in the World!
-----==  Over 80,000 Newsgroups - 16 Different Servers! =-----

From: Paul F. Dietz
Subject: Re: Unexpected behavior in CMU CL for Linux
Date: 
Message-ID: <lbOcnbUntbBbUoGjXTWc3g@dls.net>
Larry Clapp wrote:
> Under CMUCL 18c for Linux:
> 
> * (eq "x" "x")
> NIL
> 
> * (let () (eq "x" "x"))
> T
> 
> Any ideas as to why?

It's probably compiling it:

* (funcall (compile nil `(lambda () (eq ,(copy-seq "x") ,(copy-seq "x")))))
Compiling LAMBDA NIL:
Compiling Top-Level Form:

T
* (setq *x* `(lambda () (eq ,(copy-seq "x") ,(copy-seq "x"))))
Warning:  Declaring *X* special.

(LAMBDA () (EQ "x" "x"))
* *x*

(LAMBDA () (EQ "x" "x"))
* (funcall (compile nil *x*))
Compiling LAMBDA NIL:
Compiling Top-Level Form:

T
*

Note that in ANSI CL, compile (but not file compilation) is supposed
to preserve object identity, but many lisps don't do that.

Why LET should cause compilation I'm not clear on.  Byte compilation,
perhaps?  (block nil (eq "x" "x")) also evals to T.

	Paul
From: Christopher C. Stacy
Subject: Re: Unexpected behavior in CMU CL for Linux
Date: 
Message-ID: <uiswz554f.fsf@dtpq.com>
>>>>> On Wed, 8 Jan 2003 20:12:09 -0500, Larry Clapp ("Larry") writes:

 Larry> Under CMUCL 18c for Linux:
 Larry> * (eq "x" "x")
 Larry> NIL

 Larry> * (let () (eq "x" "x"))
 Larry> T

 Larry> Any ideas as to why?

Because there's nothing wrong with it doing constant folding,
but it is optional that it do so.  It is not sensible for you
to ask if two constant strings are the same, because: they
might be; then again, they might not.
From: Steven M. Haflich
Subject: Re: Unexpected behavior in CMU CL for Linux
Date: 
Message-ID: <3E1D23DE.2050200@alum.mit.edu>
Christopher C. Stacy wrote:
>>>>>>On Wed, 8 Jan 2003 20:12:09 -0500, Larry Clapp ("Larry") writes:
> 
> 
>  Larry> Under CMUCL 18c for Linux:
>  Larry> * (eq "x" "x")
>  Larry> NIL
> 
>  Larry> * (let () (eq "x" "x"))
>  Larry> T
> 
>  Larry> Any ideas as to why?
> 
> Because there's nothing wrong with it doing constant folding,
> but it is optional that it do so.  It is not sensible for you
> to ask if two constant strings are the same, because: they
> might be; then again, they might not.

Chris, your statements are somewhat inaccurate.  According to the
ANS, compile and eval are _prohibited_ from doing any constant
folding:

   Literal objects appearing in code processed by the compile
   function are neither copied nor coalesced. The code resulting
   from the execution of compile references objects that are eql
   to the corresponding objects in the source code.

Regardless whether the print-eval-read loop of the top level is
implemented by a compiler, it should have the semantics of eval.

compile-file is not _required_ to do constant folding, but it is
allowed to do so.  However, it _is_ required to preserve eqness of
substructure within a compile file.

   Objects containing circular references can be externalizable
   objects. The file compiler is required to preserve eqlness of
   substructures within a file. Preserving eqlness means that
   objects that are the same in the source code must be the same
   in the corresponding compiled code.

The notion of substructure WITHIN A FILE (as opposed to "within a
single constant") is important.  For example:

   (defmacro circle () '#1=(a . #1#))
   (defun foo () (circle))
   (defun bar () (circle))

after compiling and loading into a fresh image, it is clearly
required that

   (eq (cdr (foo)) (cddr (bar))) ==> t

But I would also maintain that it is also required that

   (eq (foo) (bar)) ==> t

or in other words, that all _similar_ constants _must_ be coalesced.
Otherwise constant objects that are the same in the source code
would _not_ be the same when the compiled file is loaded.  But I'll
admit the odd qualification of SUBstructure makes the scope of this
requirement murky, and elsewhere the ANS speaks of "may coalesce"....
From: Steven M. Haflich
Subject: Re: Unexpected behavior in CMU CL for Linux
Date: 
Message-ID: <3E1D253A.6010600@alum.mit.edu>
I want to correct a simple miswording before everyone jumps on it:

Steven M. Haflich wrote:
...
> But I would also maintain that it is also required that
> 
>   (eq (foo) (bar)) ==> t
> 
> or in other words, that all _eql_ constants _must_ be coalesced.
                [was "similar"  ^^^]
> Otherwise constant objects that are the same in the source code
> would _not_ be the same when the compiled file is loaded.  But I'll
> admit the odd qualification of SUBstructure makes the scope of this
> requirement murky, and elsewhere the ANS speaks of "may coalesce"....
From: Steven M. Haflich
Subject: Re: Unexpected behavior in CMU CL for Linux
Date: 
Message-ID: <jY9T9.1150$p93.70422706@newssvr21.news.prodigy.com>
I want to correct a simple miswording before everyone jumps on it:

Steven M. Haflich wrote:
...
> But I would also maintain that it is also required that
> 
>   (eq (foo) (bar)) ==> t
> 
> or in other words, that all _eql_ constants _must_ be coalesced.
                [was "similar"  ^^^]
> Otherwise constant objects that are the same in the source code
> would _not_ be the same when the compiled file is loaded.  But I'll
> admit the odd qualification of SUBstructure makes the scope of this
> requirement murky, and elsewhere the ANS speaks of "may coalesce"....
From: Kaz Kylheku
Subject: Re: Unexpected behavior in CMU CL for Linux
Date: 
Message-ID: <cf333042.0301090948.3e17178b@posting.google.com>
"Steven M. Haflich" <·················@alum.mit.edu> wrote in message news:<················@alum.mit.edu>...
> Christopher C. Stacy wrote:
> >>>>>>On Wed, 8 Jan 2003 20:12:09 -0500, Larry Clapp ("Larry") writes:
> > 
> > 
> >  Larry> Under CMUCL 18c for Linux:
> >  Larry> * (eq "x" "x")
> >  Larry> NIL
> > 
> >  Larry> * (let () (eq "x" "x"))
> >  Larry> T
> > 
> >  Larry> Any ideas as to why?
> > 
> > Because there's nothing wrong with it doing constant folding,
> > but it is optional that it do so.  It is not sensible for you
> > to ask if two constant strings are the same, because: they
> > might be; then again, they might not.
> 
> Chris, your statements are somewhat inaccurate.  According to the
> ANS, compile and eval are _prohibited_ from doing any constant
> folding:

Maybe it's the reader doing it.  One difference between 

  (eq "x" "x")

and

  (let () (eq "x" "x"))

is that the "x" tokens are read in an inner nesting level. There could
be some behavior in the reader which depends on that difference.
From: Kalle Olavi Niemitalo
Subject: Re: Unexpected behavior in CMU CL for Linux
Date: 
Message-ID: <87u1gi6p00.fsf@Astalo.y2000.kon.iki.fi>
"Steven M. Haflich" <·················@alum.mit.edu> writes:

>    (defmacro circle () '#1=(a . #1#))
>    (defun foo () (circle))
>    (defun bar () (circle))

Do you mean (defmacro circle () ''#1=(a . #1#))?
From: Steven M. Haflich
Subject: Re: Unexpected behavior in CMU CL for Linux
Date: 
Message-ID: <avm2qi$cs3$1@news.franz.com>
Kalle Olavi Niemitalo wrote:
> "Steven M. Haflich" <·················@alum.mit.edu> writes:
> 
>>   (defmacro circle () '#1=(a . #1#))
>>   (defun foo () (circle))
>>   (defun bar () (circle))
> 
> Do you mean (defmacro circle () ''#1=(a . #1#))?

Right.  This obvious mistake shows how programs that are
mostly punctuation are not necessarily a good thing.
From: Eric Marsden
Subject: Re: Unexpected behavior in CMU CL for Linux
Date: 
Message-ID: <wziwulewqpb.fsf@melbourne.laas.fr>
>>>>> "lc" == Larry Clapp <·····@theclapp.org> writes:

  lc> Under CMUCL 18c for Linux:
  lc> * (eq "x" "x")
  lc> NIL
  lc> 
  lc> * (let () (eq "x" "x"))
  lc> T
  lc> 
  lc> Any ideas as to why?

in CMUCL, forms can be evaluated in a number of different ways:

   - the stub interpreter
   - the grownup interpreter
   - the byte-code interpreter
   - execution of native code
  
Forms entered into the listener are evaluated using EVAL, a function
that is provided by the stub interpreter. This interpreter has very
limited capabilities: it can handle simple funcalls, SETQ, QUOTE,
PROGN, EVAL-WHEN. Anything more complicated (including LET) is passed
on to the grownup interpreter (function EVAL:INTERNAL-EVAL).

,----
| USER> (trace eval:internal-eval)
| USER> (eq "x" "x")
| nil
| USER> (let () (eq "x" "x"))
|   0: (eval:internal-eval (let () (eq "x" "x")) nil nil)
|   0: eval:internal-eval returned t
| t
| USER> (the boolean (eq "x" "x"))
|   0: (eval:internal-eval (the boolean (eq "x" "x")) nil nil)
|   0: eval:internal-eval returned t
| t
`----

The grownup interpreter is fairly sophisticated, and operates on the
IR1 intermediate representation that is output by the first stages of
the compiler. [The grownup interpreter thus requires the compiler to
be present, which means that it can't be used to bootstrap the build
of CMUCL; this is why there's also a stub interpreter.] It's during
IR1 analysis that CMUCL recognizes that the two arguments to EQ
represent the same constant:

,---- 
| COMPILER> (trace ir1-convert)
| COMPILER> (trace make-constant)
| COMPILER> (trace compile-for-eval :encapsulate t)
| COMPILER> (the boolean (eq "x" "x"))
|   0: (compile-for-eval (the boolean (eq "x" "x")) nil nil)
|     1: (ir1-convert #<Continuation c1> #<Continuation c2> (the boolean (eq "x" "x")))
|       2: (ir1-convert #<Continuation c1> #<Continuation c2> (eq "x" "x"))
|         3: (ir1-convert #<Continuation c3> #<Continuation c4> "x")
|           4: (make-constant :type #<array-type (simple-base-string 1)>
|                             :value "x")
|           4: make-constant returned #<constant #x485BCE6D  value= "x">
|         3: ir1-convert returned nil
|         3: (ir1-convert #<Continuation c4> #<Continuation c5> "x")
|         3: ir1-convert returned nil
|       2: ir1-convert returned nil
|     1: ir1-convert returned nil
|   0: compile-for-eval returned
|        #<lambda #x485B2B4D
|            name= "Top-Level Form"
|            type= #<built-in-class function (read-only) {2803FAC5}>
|            where-from= :defined
|            vars= nil>
| t
`---- (slightly edited for clarity) ---

It's not possible to trace what's going on in detail, because the
compiler uses inline functions, but while building the IR1 graph for
this expression, each of the arguments to the EQ function is converted
into a leaf node of type constant. The first time that "x" is
converted, the function MAKE-CONSTANT is called. In the second
conversion, the compiler notices that it already has a leaf node of
type constant with the same value, so it reuses that instead of
creating a new node.

There's a summary of the differences between the different types of
evaluation in CMUCL at 
  
  <URL:http://www2.cons.org/cmucl/doc/different-compilers.html>
  
-- 
Eric Marsden                          <URL:http://www.laas.fr/~emarsden/>
From: Larry Clapp
Subject: Re: Unexpected behavior in CMU CL for Linux
Date: 
Message-ID: <8gbkva.tnh.ln@127.0.0.1>
Eric,

Thank you for your enlightening reply.

In article <···············@melbourne.laas.fr>, Eric Marsden wrote:
<much snippage ...>
> The grownup interpreter is fairly sophisticated, and operates on the
> IR1 intermediate representation that is output by the first stages
> of the compiler. [The grownup interpreter thus requires the compiler
> to be present, which means that it can't be used to bootstrap the
> build of CMUCL; this is why there's also a stub interpreter.] It's
> during IR1 analysis that CMUCL recognizes that the two arguments to
> EQ represent the same constant:
> 
> ,---- 
>| COMPILER> (trace ir1-convert)
>| COMPILER> (trace make-constant)
>| COMPILER> (trace compile-for-eval :encapsulate t)
>| COMPILER> (the boolean (eq "x" "x"))
>|   0: (compile-for-eval (the boolean (eq "x" "x")) nil nil)
>|     1: (ir1-convert #<Continuation c1> #<Continuation c2> (the boolean (eq "x" "x")))
>|       2: (ir1-convert #<Continuation c1> #<Continuation c2> (eq "x" "x"))
>|         3: (ir1-convert #<Continuation c3> #<Continuation c4> "x")
>|           4: (make-constant :type #<array-type (simple-base-string 1)>
>|                             :value "x")
>|           4: make-constant returned #<constant #x485BCE6D  value= "x">
>|         3: ir1-convert returned nil
>|         3: (ir1-convert #<Continuation c4> #<Continuation c5> "x")
>|         3: ir1-convert returned nil
>|       2: ir1-convert returned nil
>|     1: ir1-convert returned nil
>|   0: compile-for-eval returned
>|        #<lambda #x485B2B4D
>|            name= "Top-Level Form"
>|            type= #<built-in-class function (read-only) {2803FAC5}>
>|            where-from= :defined
>|            vars= nil>
>| t
> `---- (slightly edited for clarity) ---
> 
> It's not possible to trace what's going on in detail, because the
> compiler uses inline functions, but while building the IR1 graph for
> this expression, each of the arguments to the EQ function is
> converted into a leaf node of type constant. The first time that "x"
> is converted, the function MAKE-CONSTANT is called. In the second
> conversion, the compiler notices that it already has a leaf node of
> type constant with the same value, so it reuses that instead of
> creating a new node.
> 
> There's a summary of the differences between the different types of
> evaluation in CMUCL at 
>   
>  <URL:http://www2.cons.org/cmucl/doc/different-compilers.html>

I read all of this (and I think I even understand it :).  I do not
understand why this doesn't conflict with the Hyperspec's definition
of EVAL, quoted by Steven M. Haflich previously:

    Constants appearing in code processed by eval are not copied nor
    coalesced. The code resulting from the execution of eval references
    objects that are eql to the corresponding objects in the source code. 

In particular, as you said, "In the second conversion, the compiler
notices that it already has a leaf node of type constant with the same
value, so it reuses that instead of creating a new node."

Can you elaborate?

Thank you again for your detailed response.

-- Larry Clapp
From: Eric Marsden
Subject: Re: Unexpected behavior in CMU CL for Linux
Date: 
Message-ID: <wziel7l2tpt.fsf@melbourne.laas.fr>
>>>>> "lc" == Larry Clapp <·····@theclapp.org> writes:

  lc> I read all of this (and I think I even understand it :). I do
  lc> not understand why this doesn't conflict with the Hyperspec's
  lc> definition of EVAL, quoted by Steven M. Haflich previously:
  lc> 
  lc> Constants appearing in code processed by eval are not copied nor
  lc> coalesced. The code resulting from the execution of eval
  lc> references objects that are eql to the corresponding objects in
  lc> the source code.

as Paul Dietz has said, it looks like CMUCL's behaviour is
non-conforming in this regard. I think that this should be easy to
fix, however (two lines of code to add). 
  
-- 
Eric Marsden                          <URL:http://www.laas.fr/~emarsden/>
From: Hannah Schroeter
Subject: Re: Unexpected behavior in CMU CL for Linux
Date: 
Message-ID: <avkq2v$7d4$1@c3po.schlund.de>
Hello!

Eric Marsden  <········@laas.fr> wrote:
>[...]

>It's not possible to trace what's going on in detail, because the
>compiler uses inline functions, but while building the IR1 graph for
>this expression, each of the arguments to the EQ function is converted
>into a leaf node of type constant. The first time that "x" is
>converted, the function MAKE-CONSTANT is called. In the second
>conversion, the compiler notices that it already has a leaf node of
>type constant with the same value, so it reuses that instead of
>creating a new node.

>[...]

And how does that interact with the statement in another part of this
thread, that mere evaluation (or #'compile) may NOT coalesce similar
constants?

Kind regards,

Hannah.
From: Paul F. Dietz
Subject: Re: Unexpected behavior in CMU CL for Linux
Date: 
Message-ID: <S3SdnVE7yfF3vIOjXTWcqA@dls.net>
Hannah Schroeter wrote:

> And how does that interact with the statement in another part of this
> thread, that mere evaluation (or #'compile) may NOT coalesce similar
> constants?

It shows a place where CMU CL isn't ANSI CL compliant.

(This is a known issue.)

	Paul