.c 	Wednesday, June 6, 1984   -*- BOLIO -*-

.chapter "What Will Break"

Various changes are anticipated for future releases of lan{nil},
just as some have taken place for this release.  This chapter
notes some of the significant implementation changes which have
already occurred, and describes some which are anticipated.

.section "What Broke Since Release 0.286"

.subsection "Conditions, Errors, and Debugging"

Since release 0.286, a new system for signalling and handling
conditions and errors has been installed.  See
(signalling-and-handling-conditions-section-page) for complete
documentation.  There are two significant user-level incompatibilities,
over and above changes to the arguments to certain error functions (
which are for the most part handled upwards compatibly).  First,
calls to the spec_i{errset} special form compiled prior to Revision
2 of Release 0.286 will not trap errors;  they must be recompiled.
(Revision 2 of that release contained redefined 3errset* with some
hacks to permit it to function in both the old and new schemes.)
Second (and less likely to be encountered), the fun_i{signal} function
has changed incompatibly.

.subsection "Variable Naming Conventions"

System variables which were supposed to have asterisks around their
names but did not in prior releases (e.g., 3*package** vs.
3package*), now do.  However, 2the old code will continue to work
correctly*.  By clever kludgery, the special value cells for these
pairs of symbols are made to point to the same place.  Thus,
3*package** and 3package* always share the same binding.  Note that
this only affects the special value;  the symbols 3*package** and
3package* may have different function definitions.  The complete list
of variables affected in this way is
.table 3 250 250 0 0 0
.item *package*
formerly var_i{package}
.item *readtable*
formerly var_i{readtable}
.item *terminal-io*
formerly var_i{terminal-io}
.item *standard-input*
formerly var_i{standard-input}
.item *standard-output*
formerly var_i{standard-output}
.item *error-output*
formerly var_i{error-output}
.item *query-io*
formerly var_i{query-io}
.item *print-base*
formerly var_i{si:standard-output-radix}
.item *read-base*
formerly var_i{si:standard-input-radix}
.item *print-length*
formerly var_i{prinlength}
.item *print-level*
formerly var_i{prinlevel}
.item *trace-conditions*
formerly var_i{trace-conditions} (but this variable did not exist in
release 0.286 anyway)
.item si:*heap-growth-pages*
formerly var_i{si:heap-growth-pages}
.item si:*print-gc-messages*
formerly var_i{si:print-gc-messages}
.item si:*lisp-debugger-on-exceptions*
formerly var_i{si:lisp-debugger-on-exceptions}
.item si:*internal-without-interrupts*
formerly var_i{si:internal-without-interrupts}
.item si:*loaded-vasl-files*
formerly var_i{si:loaded-modules}
.item si:*interrupt-bound-variables*
formerly var_i{si:interrupt-bound-variables}
.end_table
The compiler will issue an informational message if it encounters a
reference to one of the old variables;  the code, however, will
function correctly.

.subsection "Break Broken"

The fun_i{break} ((break-fun)) function is now quite different from
the way it
used to be.  Technically, it still provides a read-eval-print loop;
however, it is supplied by the new debugger instead (making it much
more useful too).  That is,
3break* is now a way to call the debugger.  The primary
incompatibility is that 3break* did not used to evaluate its first
"argument";  now, it does.  The simplest fix is normally to change
calls like 3(break barf)* to 3(break "barf")*.

In prior versions of lan{nil}, 3break* was a macro which expanded
into a call to the lan{maclisp}-compatible function 3*break*.
The 3*break* function continues to exist unmodified in lan{nil},
so calls to 3break* in code compiled in earlier releases will
function unchanged until it is recompiled.

.subsection "Time Different"

The 3time* function ((time-fun)) is no longer the same as the
3elapsed-time* function ((elapsed-time-fun)).

.subsection "Flavor System Changes"

The code underlying the lan{nil} flavor system is substantially
changed in this release.  However, the user-level interface is
basically unchanged and upwards compatible.  Code which worked in prior
releases should continue to do so.  The changes which were made are
mostly in the "bookkeeping" done by the flavor system, and improving
the internal modularity to permit some extensions to be experimented
with (e.g., method combination).  The most significant change is that
it is not necessary for all component flavors to be defined when one
calls 3defflavor*;  they only need to be defined at the time of the
first 3make-instance*.  The compiler, when it compiles methods, now
tells the flavor system the assumptions it made about what instance
variables it used and where it assumed they were stored.  As a
result, one should no longer have problems caused by methods defined on
the same flavor at different times referencing instance variables incorrectly.


.section "Future Changes"

Many of these have been anticipated since time immemorial but never
implemented.

.subsection "Default Floating-Point Format"

The default floating point format is going to change from the current
3double-float* to 3single-float*.  (Last release, I claimed it
would almost certainly happen in this release.  However, it is likely
that this will be postponed until after the release of the
garbage-collector.)
The format of course could not be
changed with this release and maintain any semblance of upwards
compatibility, because the 2previous* release did not support
3single-float* format.  Because of contagion rules, there are
really just two ways one might start generating single-floats instead
of double-floats:  when reading, and when performing some irrational,
transcendental, or otherwise awful function on rational inputs.
If in fact the change matters at all for an application (it might not
if only generic arithmetic was being used), then one could avoid
problems by judicious use of explicit conversion to floating point,
and by being careful to explicitly specify the exponentiation
character in lan{lisp} source files so that the datatype will be
explicit;  that is, write 31.0d0* or 31.0f0* rather than just
31.0* or 31.0e0*.

.subsection "New Package Facility"

The lan{common lisp} package definition is finally final.  Contrary to
predictions, it has not been implemented for this release.  Like the
change in floating-point format, the installation of the new package
system is probably now 2two* releases away, given the expectation
that the garbage collector will be the major change in the next release.
It is unlikely that anything other than code which operates on or with
packages explicitly will have to be changed, with the possible
exception of references to symbols "internal" in one package made
from another package.

.subsection "Multiple Values"
.setq multiple-values-breaking-section-page section-page

In the future, lan{nil} will "natively" support a multiple-value
return mechanism.  For it to do so requires that the compiler
understand them at a moderately low level;  it will be producing code
for receipt of them from function calls, it will have to flag function
calls which will be passing them back to another caller, and it must
recognize and compile away all local multiple-value passing.

The mechanism, which has only been designed at a fairly high level, is
this.

Given the compiler behaviour described above, the only place which
compiled code can receive multiple values from is a function call (or
a non-lexical 3throw*, but we will ignore this for the sake of
simplicity in this description).  This means, that when multiple
values are being passed back (returned or generated), if we can
recognize those function calls which are simply being made to pass
back any values to their callers (and thus also recognize those which
are expecting some value or values in particular), we can trace up the
stack to find the call which is ultimately expecting the multiple
values.  (The function call frames are quite formal and stylized in
lan{nil}.)

So what we do is to have the caller which is expecting multiple values
allocate a place for them on the stack and put a marker there, before
it allocates the call frame for the function it is about to call.

We have all function calls which simply pass back their values as the
value of the function they are contained in, marked as such, so that
examination of the call can determine this.  In the following, the
calls to 3foo* and 3bar* would be so marked, but 3baz*
would not:
.lisp
(defun frobnicate (x y)
   (if (zerop x) (foo y)
       (mvprog1 (bar x (sub1 y))
		(baz (sub1 x) y))))
.end_lisp
If (say) within 3bar* there is a call 3(values 2this*
2that*)*, then a special subroutine goes looking up the stack,
finds the frame where 3bar* is called, sees that it passes back
its values out of its calling function, so traces the function frame
pointer to the caller of 3frobnicate*, etc.

If, on the other hand, with 3baz* there is a similar 3values*
call, tracing back to that call to 3baz* reveals that 3baz* is
expected to return only one value (of interest, at most), so no
further tracing is done.

There are two further points of interest about this scheme.  By
appropriate use of specialized markers where multiple values 2are*
expected, fast dispatching may be performed for dealing with various
situations, such as multiple-value-list, for instance.

A somewhat
kludgey extension is to use this for things like "number calling"--one
routine calling another for (say) flonum value.  The one producing the
flonum, instead of consing it, looks back and if the final destination
is expecting a flonum in some special way (having, for instance,
pre-allocated a space on the stack for it), then the representation is
stored there without consing, otherwise the value is consed in the
heap and passed back via the normal value return mechanism.  The
kludge involved here is that if the producer is interpreted code,
someone has to coerce the 2normal* value return into the hacked
one.  This only is necessary when such a compiled routine is calling
into interpreted code, so will probably be done by the
interpreter-trapping subroutine.

The interpreter-trap wrapper must be capable of recognizing when a
value 2has* been stored "properly" into the compiled receiver,
because if the 2producer* is compiled and the interpreter has
produced the value such that it got passed back "naturally", then it
has been stored already without being consed, even with intervening
interpretation!

It is of note that this stack-searching is not directly analogous to a
deep-binding variable-binding scheme, in terms of efficiency and
paging overhead etc., because in the variable binding scheme the
searching must be done up the entire stack (or alist or whatever)
every time, the time for each search growing in proportion to the
depth of the stack, but for this the search terminates whenever values
are not being passed back to the previous caller.
