From: Howard R. Stearns
Subject: unused literals in compiles-files
Date: 
Message-ID: <361A369B.E32D74A0@elwood.com>
If a tree falls in the forest.....

Must an implementation necessarily arrange for load-forms of all
compile-file literals to be processed?  What if the literal only
appears in dead code (i.e. code that can't ever be executed)?

Consider for example:

  (defstruct foo)
  (defmethod make-load-form ((x foo) &optional env)
    `(progn (print 'hello) (make-foo)))
  (when nil #.(make-foo))

The answer would be clearer, if for example section "3.2.4.4
Additional Constraints on Externalizable Objects" of the ANSI spec
said the following, but instead, the **CAPITALIZED** words, below, are
missing:

  The file compiler calls make-load-form on any object that is
  referenced as a literal object **IN LIVE CODE** if the object is a
  generalized instance of standard-object, structure-object,
  condition, or any of a (possibly empty) implementation-dependent set
  of other classes.  The file compiler only calls make-load-form **AT
  MOST** once for any given object within a single file.

More generally, must all literals and other objects necessarilly
appear in compiled-files?  Consider, for example, an ignorable lexical
function which is never called.

How would a user ever know (except by seeing the code bloat, or
examining with a core debugger)?  Well, suppose an implementation
provides some way to do finalization on arbitrary objects -- even
system defined objects.  Suppose that a user defines a side-effecting
finalization on closures.

A related question is whether users should have any expectations of
WHEN the code for a load-form is processed by the file compiler.  For
example, suppose side-effects are executed by a MAKE-LOAD-FORM method
itself (i.e. not the forms that it produces).  Would it be all right if,
for example, all forms produced by make-load-form were produced at the
end of other file-processing?

The reason for my questions are that, while working on a new compiler,
it occured to me that the compiler code could be much simpler, and the
generated code cleaner and more compact, if we had this flexibility.

From: Kent M Pitman
Subject: Re: unused literals in compiles-files
Date: 
Message-ID: <sfwpvc5h0jw.fsf@world.std.com>
"Howard R. Stearns" <······@elwood.com> writes:

> If a tree falls in the forest.....

This is the right metaphor, I think.

> Must an implementation necessarily arrange for load-forms of all
> compile-file literals to be processed?

Suggest a conforming program that can tell the difference.

> What if the literal only
> appears in dead code (i.e. code that can't ever be executed)?

Fasl file format is not standard, and generally not even published.
How on earth could anyone care?

This kind of question came up a lot in the design of the language
and always seemed entirely pointless to me.  I was badgered
incessantly about calling the symbol-value a "slot" because of
some belief that doing so requires the allocation of extant adjacent
memory.  As if memory is ever reliably adjacent in a paged system
anyway.  As if "extant" is testable.

Someone once taught me that the "meaning" of a type is to correctly
honor the operational protocol for that type.  I like that idea. If
something is not a required action, it need not be supported.  If
something is required, it must work.  If it can't be seen, and you
don't do it, how can anyone tell the difference if you simply tell
them that it WAS done and that it's a performance optimization that it
wasn't.

Say what you're actually afraid you have to do and what sentence you
believe forces it.  It sure looks to me like you answered
your own question with the tree/forest analogy.

Incidentally, no one is empowered or authorized to tell you your
implementation either conforms or doesn't.  Even in languages that
have a "validation" group, you don't just take a test and then pass or
fail.  You get back a list of questions and then you have to justify
your decisions.  Reasonable interpretations generally prevail.  CL
doesn't have such a formal mechanism, so it relies on the market to
sort this out, but presumably there again, reasonable interpretations
are what will sell ...
From: Barry Margolin
Subject: Re: unused literals in compiles-files
Date: 
Message-ID: <7xMS1.54$8A3.1350292@burlma1-snr1.gtei.net>
In article <···············@world.std.com>,
Kent M Pitman  <······@world.std.com> wrote:
>Suggest a conforming program that can tell the difference.

As in his example, if the method has side effects, the difference can be
apparent.

-- 
Barry Margolin, ······@bbnplanet.com
GTE Internetworking, Powered by BBN, Burlington, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
From: Kent M Pitman
Subject: Re: unused literals in compiles-files
Date: 
Message-ID: <sfwbtnnnbnb.fsf@world.std.com>
Barry Margolin <······@bbnplanet.com> writes:

> In article <···············@world.std.com>,
> Kent M Pitman  <······@world.std.com> wrote:
> >Suggest a conforming program that can tell the difference.
> 
> As in his example, if the method has side effects, the difference can be
> apparent.

Being apparent is not the same as being defined.  The difference
between (random) and (random) is apparent but not defined.  CHAR-INT
can return values that are apparently different but not defined to be
different. 

I don't see that the user just because he is entitled to have a method
run on creation of an object is entitled to have the object created if
it can't be reached.

So probably I asked the wrong question.  But I still stand by my
belief that the spec creates no expectation that the user is 
entitled to assume the object will be created.  Consider a 
competing case:

(defun foobar ()
  (prog () (go tag) (print 'foo) tag (print 'bar)))

The user can certainly detect by (find-symbol "FOO") whether foo is
present as a symbol.  Is the user entitled to find that symbol
interned as a result of loading the file containing this definition?
I think not.  The question being asked is really not much different.
From: Howard R. Stearns
Subject: Re: unused literals in compiles-files
Date: 
Message-ID: <361CDDC9.46A9F817@elwood.com>
OK., let's try it this way:

 Can anyone think of any useful behavior that might encourage someone to
think that they ought to be able to get away with thinking that:

  All constructions (eg., literals, including symbols, and closures)
which are 
  apparently present/defined in a Lisp source file are, in fact, present
in the 
  compiled file.

After, all, the point should not be for me to write a compiler some
particular way and then say, "I could do this because my interpretation
of the spec (or Barry or Kent) said I could."  

We can all think of cases (some using technically conforming code,)
which make the distinction apparent.  I think that we agree that the
distinction is not defined.
What I should have asked was whether the distinction is usefull. I can't
think of any way in which it is.  I'm looking to the newsgoup as a
sanity check on this supposition.

Kent M Pitman wrote:
> 
> Barry Margolin <······@bbnplanet.com> writes:
> 
> > In article <···············@world.std.com>,
> > Kent M Pitman  <······@world.std.com> wrote:
> > >Suggest a conforming program that can tell the difference.
> >
> > As in his example, if the method has side effects, the difference can be
> > apparent.
> 
> Being apparent is not the same as being defined.  The difference
> between (random) and (random) is apparent but not defined.  CHAR-INT
> can return values that are apparently different but not defined to be
> different.
> 
> I don't see that the user just because he is entitled to have a method
> run on creation of an object is entitled to have the object created if
> it can't be reached.
> 
> So probably I asked the wrong question.  But I still stand by my
> belief that the spec creates no expectation that the user is
> entitled to assume the object will be created.  Consider a
> competing case:
> 
> (defun foobar ()
>   (prog () (go tag) (print 'foo) tag (print 'bar)))
> 
> The user can certainly detect by (find-symbol "FOO") whether foo is
> present as a symbol.  Is the user entitled to find that symbol
> interned as a result of loading the file containing this definition?
> I think not.  The question being asked is really not much different.
From: Barry Margolin
Subject: Re: unused literals in compiles-files
Date: 
Message-ID: <7B6T1.15$675.335518@burlma1-snr1.gtei.net>
In article <·················@elwood.com>,
Howard R. Stearns <······@elwood.com> wrote:
>What I should have asked was whether the distinction is usefull. I can't
>think of any way in which it is.  I'm looking to the newsgoup as a
>sanity check on this supposition.

I can't imagine why one would need to write a program that depended on the
behavior you describe.

Similar things come up in other languages.  For instance, the C
specification says that the NULL is either 0 or (void*)0.  But there's also
a general "as if" clause, that says that an implementation can do what it
wants as long as if it works equivalently to what the standard says,
i.e. so long as a conforming program can't tell the difference.  The
question then arises: can an implementation define NULL to be
__internal_null_keyword, so long as it behaves in legal expressions the
same as one of the above expressions?  It seems that this should be
allowed.  However, there's a preprocessor "stringizing" operation that
turns a macro into a string containing its expansion, so the following
command would make this internal detail visible:

printf("%s\n", ##NULL);

I believe the concensus is that this doesn't really preclude the compiler
from working this way.

-- 
Barry Margolin, ······@bbnplanet.com
GTE Internetworking, Powered by BBN, Burlington, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
From: Barry Margolin
Subject: Re: unused literals in compiles-files
Date: 
Message-ID: <yxUS1.3$675.20588@burlma1-snr1.gtei.net>
In article <·················@elwood.com>,
Howard R. Stearns <······@elwood.com> wrote:
>The answer would be clearer, if for example section "3.2.4.4
>Additional Constraints on Externalizable Objects" of the ANSI spec
>said the following, but instead, the **CAPITALIZED** words, below, are
>missing:
>
>  The file compiler calls make-load-form on any object that is
>  referenced as a literal object **IN LIVE CODE** if the object is a
>  generalized instance of standard-object, structure-object,
>  condition, or any of a (possibly empty) implementation-dependent set
>  of other classes.  The file compiler only calls make-load-form **AT
>  MOST** once for any given object within a single file.

Note that the above quote refers to when MAKE-LOAD-FORM is called.  It
doesn't say anything about when the forms it returns are evaluated.  So
even if we interpret it as saying that MAKE-LOAD-FORM will be evaluated for
objects only referenced by dead code, there's not necessarily a requirement
that side effects in the creation or initialization forms will occur.

>More generally, must all literals and other objects necessarilly
>appear in compiled-files?  Consider, for example, an ignorable lexical
>function which is never called.
>
>How would a user ever know (except by seeing the code bloat, or
>examining with a core debugger)?  Well, suppose an implementation
>provides some way to do finalization on arbitrary objects -- even
>system defined objects.  Suppose that a user defines a side-effecting
>finalization on closures.

It's difficult for a standard to make guarantees about what the effect of
implementation extensions will be.  An implementation that provides such an
extension should document how it interacts with other aspects of the
language.  An analogous area would be the relationship between special
variable bindings and threads in multi-threaded Lisps.

>A related question is whether users should have any expectations of
>WHEN the code for a load-form is processed by the file compiler.  For
>example, suppose side-effects are executed by a MAKE-LOAD-FORM method
>itself (i.e. not the forms that it produces).  Would it be all right if,
>for example, all forms produced by make-load-form were produced at the
>end of other file-processing?

The standard is intentionally very vague on the internal operations of the
file compiler.  There are virtually no constraints on how it processes the
file.  A similar question would be the order in which macro functions are
invoked (there's nothing preventing programmers from putting side effects
in macros, which would make the order apparent).

-- 
Barry Margolin, ······@bbnplanet.com
GTE Internetworking, Powered by BBN, Burlington, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.