309 lines
21 KiB
HTML
309 lines
21 KiB
HTML
|
<!-- Common Lisp HyperSpec (TM), version 7.0 generated by Kent M. Pitman on Mon, 11-Apr-2005 2:31am EDT -->
|
||
|
<HTML>
|
||
|
<HEAD>
|
||
|
<TITLE>CLHS: Issue DYNAMIC-EXTENT Writeup</TITLE>
|
||
|
<LINK HREF="../Data/clhs.css" REL="stylesheet" TYPE="text/css" />
|
||
|
<META HTTP-EQUIV="Author" CONTENT="Kent M. Pitman">
|
||
|
<META HTTP-EQUIV="Organization" CONTENT="LispWorks Ltd.">
|
||
|
<LINK REL=TOP HREF="../Front/index.htm">
|
||
|
<LINK REL=COPYRIGHT HREF="../Front/Help.htm#Legal">
|
||
|
<LINK REL=DISCLAIMER HREF="../Front/Help.htm#Disclaimer">
|
||
|
<LINK REL=PREV HREF="../Issues/iss141_w.htm">
|
||
|
<LINK REL=UP HREF="../Issues/iss142.htm">
|
||
|
<LINK REL=NEXT HREF="../Issues/iss143_w.htm">
|
||
|
</HEAD>
|
||
|
<BODY>
|
||
|
<H1><A REV=MADE HREF="http://www.lispworks.com/"><IMG WIDTH=80 HEIGHT=65 ALT="[LISPWORKS]" SRC="../Graphics/LWSmall.gif" ALIGN=Bottom></A><A REL=TOP HREF="../Front/index.htm"><IMG WIDTH=237 HEIGHT=65 ALT="[Common Lisp HyperSpec (TM)]" SRC="../Graphics/CLHS_Sm.gif" ALIGN=Bottom></A> <A REL=PREV HREF="../Issues/iss141_w.htm"><IMG WIDTH=40 HEIGHT=40 ALT="[Previous]" SRC="../Graphics/Prev.gif" ALIGN=Bottom></A><A REL=UP HREF="../Issues/iss142.htm"><IMG WIDTH=40 HEIGHT=40 ALT="[Up]" SRC="../Graphics/Up.gif" ALIGN=Bottom></A><A REL=NEXT HREF="../Issues/iss143_w.htm"><IMG WIDTH=40 HEIGHT=40 ALT="[Next]" SRC="../Graphics/Next.gif" ALIGN=Bottom></A></H1>
|
||
|
|
||
|
<HR>
|
||
|
|
||
|
|
||
|
|
||
|
<H2>Issue DYNAMIC-EXTENT Writeup</H2>
|
||
|
|
||
|
<PRE><B>Status:</B> passed, as amended, Mar 89 X3J13.<P>
|
||
|
<B>Forum:</B> Cleanup<P>
|
||
|
<B>Issue:</B> <A REL=DEFINITION HREF="../Body/d_dynami.htm#dynamic-extent"><B>DYNAMIC-EXTENT</B></A><P>
|
||
|
<B>References:</B> Scope and Extent<P>
|
||
|
<B>Category:</B> ADDITION<P>
|
||
|
<B>Edit history:</B> 27-Jun-88, Version 1 by Pitman (as issue STACK-LET)<P>
|
||
|
15-Nov-88, Version 2 by Pitman (issue renamed, major revision)<P>
|
||
|
11-Jan-89, Version 3 by Masinter (Moon's proposal)<P>
|
||
|
05-Apr-89, Version 4 by Pitman and Steele (changes per X3J13)<P>
|
||
|
Related-Issues: REST-ARGUMENT-EXTENT, WITH-DYNAMIC-EXTENT<P>
|
||
|
<P>
|
||
|
<B>Problem Description:<P>
|
||
|
</B><P>
|
||
|
Sometimes a programmer knows that a particular data <A REL=DEFINITION HREF="../Body/f_docume.htm#structure"><B>structure</B></A><P>
|
||
|
will have only dynamic extent. In some implementations, it is<P>
|
||
|
possible to allocate such structures in a way that will make them<P>
|
||
|
easier to reclaim than by general purpose garbage collection<P>
|
||
|
(eg, on the stack or in some temporary area). Currently, however,<P>
|
||
|
there is no way to request the use of such an allocation mechanism.<P>
|
||
|
<P>
|
||
|
<B>Proposal (DYNAMIC-EXTENT:NEW-DECLARATION):<P>
|
||
|
</B><P>
|
||
|
Introduce a new declaration called <A REL=DEFINITION HREF="../Body/d_dynami.htm#dynamic-extent"><B>DYNAMIC-EXTENT</B></A>. The arguments to<P>
|
||
|
this declaration are names of variables.<P>
|
||
|
<P>
|
||
|
It is permissible for an implementation to simply ignore this declaration.<P>
|
||
|
In implementations which do not ignore it, the compiler (or interpreter)<P>
|
||
|
is free to make whatever optimizations are appropriate given this<P>
|
||
|
information; the most common optimization is to stack-allocate the<P>
|
||
|
initial value of the object. What data types (if any) can have dynamic<P>
|
||
|
extent will can vary from implementation to implementation.<P>
|
||
|
<P>
|
||
|
Definition: Object <x> is an ``otherwise inaccessible part'' (OIP)<P>
|
||
|
of <y> iff making <y> inaccessible would make <x> inaccessible.<P>
|
||
|
(Note that <A REL=DEFINITION HREF="../Body/f_everyc.htm#every"><B>every</B></A> object is an OIP of itself.)<P>
|
||
|
<P>
|
||
|
Suppose that construct <c> contains a <A REL=DEFINITION HREF="../Body/d_dynami.htm#dynamic-extent"><B>DYNAMIC-EXTENT</B></A> declaration for<P>
|
||
|
variable <v> (which need not be bound by <c>). Consider the values<P>
|
||
|
<w1>, ..., <wN> taken on by <v> during the course of some execution of<P>
|
||
|
<c>. The declaration asserts that if object <x> is an OIP of <wI><P>
|
||
|
when <wI> ever becomes the value of <v>, then just after execution of<P>
|
||
|
<c> terminates <x> will be either inaccessible or still an OIP of <v>.<P>
|
||
|
<P>
|
||
|
If the assertion is ever violated, the conseqeuences are undefined.<P>
|
||
|
<P>
|
||
|
<B>Examples:<P>
|
||
|
</B><P>
|
||
|
Since stack allocation of the initial value entails knowing at the<P>
|
||
|
object's creation time that the object can be stack-allocated, it is<P>
|
||
|
not generally useful to declare <A REL=DEFINITION HREF="../Body/d_dynami.htm#dynamic-extent"><B>DYNAMIC-EXTENT</B></A> for variables for<P>
|
||
|
which have no lexically apparent initial value. For example,<P>
|
||
|
<P>
|
||
|
(<A REL=DEFINITION HREF="../Body/m_defun.htm#defun"><B>DEFUN</B></A> F ()<P>
|
||
|
(<A REL=DEFINITION HREF="../Body/s_let_l.htm#let"><B>LET</B></A> ((X (<A REL=DEFINITION HREF="../Body/a_list.htm#list"><B>LIST</B></A> 1 2 3)))<P>
|
||
|
(<A REL=DEFINITION HREF="../Body/s_declar.htm#declare"><B>DECLARE</B></A> (<A REL=DEFINITION HREF="../Body/d_dynami.htm#dynamic-extent"><B>DYNAMIC-EXTENT</B></A> X))<P>
|
||
|
...))<P>
|
||
|
<P>
|
||
|
would permit those compilers which wish to do so to stack-allocate the<P>
|
||
|
list in X. However,<P>
|
||
|
<P>
|
||
|
(<A REL=DEFINITION HREF="../Body/m_defun.htm#defun"><B>DEFUN</B></A> G (X) (<A REL=DEFINITION HREF="../Body/s_declar.htm#declare"><B>DECLARE</B></A> (<A REL=DEFINITION HREF="../Body/d_dynami.htm#dynamic-extent"><B>DYNAMIC-EXTENT</B></A> X)) ...)<P>
|
||
|
(<A REL=DEFINITION HREF="../Body/m_defun.htm#defun"><B>DEFUN</B></A> F () (G (<A REL=DEFINITION HREF="../Body/a_list.htm#list"><B>LIST</B></A> 1 2 3)))<P>
|
||
|
<P>
|
||
|
could not typically permit a similar optimization in G because it would<P>
|
||
|
be a modularity violation for the compiler to assume facts about G from<P>
|
||
|
within F. Only an implementation which was willing to be responsible for<P>
|
||
|
recompiling F if G's definition changed incompatibly could stack-allocate<P>
|
||
|
the list argument to G in F.<P>
|
||
|
<P>
|
||
|
Other interesting cases are:<P>
|
||
|
<P>
|
||
|
(<A REL=DEFINITION HREF="../Body/f_procla.htm#proclaim"><B>PROCLAIM</B></A> '(<A REL=DEFINITION HREF="../Body/d_inline.htm#inline"><B>INLINE</B></A> G))<P>
|
||
|
(<A REL=DEFINITION HREF="../Body/m_defun.htm#defun"><B>DEFUN</B></A> G (X) (<A REL=DEFINITION HREF="../Body/s_declar.htm#declare"><B>DECLARE</B></A> (<A REL=DEFINITION HREF="../Body/d_dynami.htm#dynamic-extent"><B>DYNAMIC-EXTENT</B></A> X)) ...)<P>
|
||
|
(<A REL=DEFINITION HREF="../Body/m_defun.htm#defun"><B>DEFUN</B></A> F () (G (<A REL=DEFINITION HREF="../Body/a_list.htm#list"><B>LIST</B></A> 1 2 3)))<P>
|
||
|
<P>
|
||
|
and (<A REL=DEFINITION HREF="../Body/m_defun.htm#defun"><B>DEFUN</B></A> F ()<P>
|
||
|
(<A REL=DEFINITION HREF="../Body/s_flet_.htm#flet"><B>FLET</B></A> ((G (X) (<A REL=DEFINITION HREF="../Body/s_declar.htm#declare"><B>DECLARE</B></A> (<A REL=DEFINITION HREF="../Body/d_dynami.htm#dynamic-extent"><B>DYNAMIC-EXTENT</B></A> X)) ...))<P>
|
||
|
(G (<A REL=DEFINITION HREF="../Body/a_list.htm#list"><B>LIST</B></A> 1 2 3))))<P>
|
||
|
<P>
|
||
|
where some compilers might realize the optimization was possible and others<P>
|
||
|
might not.<P>
|
||
|
<P>
|
||
|
An interesting variant of this is the so-called `stack allocated rest list'<P>
|
||
|
which can be achieved (in implementations supporting the optimization) by:<P>
|
||
|
<P>
|
||
|
(<A REL=DEFINITION HREF="../Body/m_defun.htm#defun"><B>DEFUN</B></A> F (<A REL=DEFINITION HREF="../Body/03_da.htm#AMrest"><B>&REST</B></A> X)<P>
|
||
|
(<A REL=DEFINITION HREF="../Body/s_declar.htm#declare"><B>DECLARE</B></A> (<A REL=DEFINITION HREF="../Body/d_dynami.htm#dynamic-extent"><B>DYNAMIC-EXTENT</B></A> X))<P>
|
||
|
...)<P>
|
||
|
<P>
|
||
|
Note here that although the initial value of X is not explicit, the F<P>
|
||
|
function is responsible for assembling the list X from the passed arguments,<P>
|
||
|
so the F function can be optimized by the compiler to construct a <P>
|
||
|
stack-allocated list instead of a heap-allocated list in implementations<P>
|
||
|
which support such.<P>
|
||
|
<P>
|
||
|
<P>
|
||
|
In<P>
|
||
|
(<A REL=DEFINITION HREF="../Body/s_let_l.htm#let"><B>LET</B></A> ((X (<A REL=DEFINITION HREF="../Body/a_list.htm#list"><B>LIST</B></A> 'A1 'B1 'C1))<P>
|
||
|
(Y (<A REL=DEFINITION HREF="../Body/a_cons.htm#cons"><B>CONS</B></A> 'A2 (<A REL=DEFINITION HREF="../Body/a_cons.htm#cons"><B>CONS</B></A> 'B2 (<A REL=DEFINITION HREF="../Body/a_cons.htm#cons"><B>CONS</B></A> 'C2 <A REL=DEFINITION HREF="../Body/a_nil.htm#nil"><B>NIL</B></A>)))))<P>
|
||
|
(<A REL=DEFINITION HREF="../Body/s_declar.htm#declare"><B>DECLARE</B></A> (<A REL=DEFINITION HREF="../Body/d_dynami.htm#dynamic-extent"><B>DYNAMIC-EXTENT</B></A> X Y))<P>
|
||
|
...)<P>
|
||
|
The OIP's of X are three conses, and the OIP's of Y are three other<P>
|
||
|
conses. None of the symbols A1, B1, C1, A2, B2, C2, or <A REL=DEFINITION HREF="../Body/a_nil.htm#nil"><B>NIL</B></A> is an<P>
|
||
|
OIP of X or Y. However, if a freshly allocated uninterned symbol had<P>
|
||
|
been used, it would have been an OIP.<P>
|
||
|
<P>
|
||
|
- - - - - - - -<P>
|
||
|
(<A REL=DEFINITION HREF="../Body/m_dotime.htm#dotimes"><B>DOTIMES</B></A> (I N) <P>
|
||
|
(<A REL=DEFINITION HREF="../Body/s_declar.htm#declare"><B>DECLARE</B></A> (<A REL=DEFINITION HREF="../Body/d_dynami.htm#dynamic-extent"><B>DYNAMIC-EXTENT</B></A> I))<P>
|
||
|
<P>
|
||
|
This is particularly instructive. Since I is an integer by the<P>
|
||
|
definition of <A REL=DEFINITION HREF="../Body/m_dotime.htm#dotimes"><B>DOTIMES</B></A>, but <A REL=DEFINITION HREF="../Body/f_eq.htm#eq"><B>EQ</B></A> and <A REL=DEFINITION HREF="../Body/a_eql.htm#eql"><B>EQL</B></A> are not necessarily equivalent for<P>
|
||
|
integers, what are the OIP's of I, which this declaration<P>
|
||
|
requires the body of the <A REL=DEFINITION HREF="../Body/m_dotime.htm#dotimes"><B>DOTIMES</B></A> not to "save"? If the value of I is 3,<P>
|
||
|
and the body does (<A REL=DEFINITION HREF="../Body/s_setq.htm#setq"><B>SETQ</B></A> FOO 3), is that an error? The answer is no, but<P>
|
||
|
the interesting thing is that it depends on the implementation-dependent<P>
|
||
|
behavior of <A REL=DEFINITION HREF="../Body/f_eq.htm#eq"><B>EQ</B></A> on numbers. In an implementation where <A REL=DEFINITION HREF="../Body/f_eq.htm#eq"><B>EQ</B></A> and <A REL=DEFINITION HREF="../Body/a_eql.htm#eql"><B>EQL</B></A> are<P>
|
||
|
equivalent for 3, then 3 is not an OIP because (<A REL=DEFINITION HREF="../Body/f_eq.htm#eq"><B>EQ</B></A> I (+ 2 1)) is true,<P>
|
||
|
and therefore there is another way to access the object besides<P>
|
||
|
going through I. On the other hand, in an implementation where <A REL=DEFINITION HREF="../Body/f_eq.htm#eq"><B>EQ</B></A> and<P>
|
||
|
<A REL=DEFINITION HREF="../Body/a_eql.htm#eql"><B>EQL</B></A> are not equivalent for 3, then the particular 3 that is the value of<P>
|
||
|
I is an OIP, but any other 3 is not. Thus (<A REL=DEFINITION HREF="../Body/s_setq.htm#setq"><B>SETQ</B></A> FOO 3) is valid<P>
|
||
|
but (<A REL=DEFINITION HREF="../Body/s_setq.htm#setq"><B>SETQ</B></A> FOO I) is erroneous. Since (<A REL=DEFINITION HREF="../Body/s_setq.htm#setq"><B>SETQ</B></A> FOO I) is erroneous in some<P>
|
||
|
implementations, it is erroneous in all portable programs, but some other<P>
|
||
|
implementations may not be able to detect the error.<P>
|
||
|
<P>
|
||
|
- - - - - - - -<P>
|
||
|
<P>
|
||
|
(<A REL=DEFINITION HREF="../Body/s_let_l.htm#let"><B>LET</B></A> ((X (<A REL=DEFINITION HREF="../Body/a_list.htm#list"><B>LIST</B></A> 1 2 3)))<P>
|
||
|
(<A REL=DEFINITION HREF="../Body/s_declar.htm#declare"><B>DECLARE</B></A> (<A REL=DEFINITION HREF="../Body/d_dynami.htm#dynamic-extent"><B>DYNAMIC-EXTENT</B></A> X))<P>
|
||
|
(<A REL=DEFINITION HREF="../Body/f_wr_pr.htm#print"><B>PRINT</B></A> X)<P>
|
||
|
<A REL=DEFINITION HREF="../Body/a_nil.htm#nil"><B>NIL</B></A>)<P>
|
||
|
<A REL=DEFINITION HREF="../Body/f_wr_pr.htm#print"><B>PRINT</B></A> does not "save" any part of its input.<P>
|
||
|
This prints (1 2 3)<P>
|
||
|
<P>
|
||
|
- - - - - - - -<P>
|
||
|
<P>
|
||
|
(<A REL=DEFINITION HREF="../Body/m_do_do.htm#do"><B>DO</B></A> ((L (<A REL=DEFINITION HREF="../Body/f_list_a.htm#list-all-packages"><B>LIST-ALL-PACKAGES</B></A>) (<A REL=DEFINITION HREF="../Body/f_car_c.htm#cdr"><B>CDR</B></A> L)))<P>
|
||
|
((<A REL=DEFINITION HREF="../Body/a_null.htm#null"><B>NULL</B></A> L))<P>
|
||
|
(<A REL=DEFINITION HREF="../Body/s_declar.htm#declare"><B>DECLARE</B></A> (<A REL=DEFINITION HREF="../Body/d_dynami.htm#dynamic-extent"><B>DYNAMIC-EXTENT</B></A> L))<P>
|
||
|
(<A REL=DEFINITION HREF="../Body/f_wr_pr.htm#print"><B>PRINT</B></A> (<A REL=DEFINITION HREF="../Body/f_car_c.htm#car"><B>CAR</B></A> L)))<P>
|
||
|
prints all packages; none of the newly-allocated list structures are saved.<P>
|
||
|
- - - - - - - -<P>
|
||
|
(<A REL=DEFINITION HREF="../Body/m_defun.htm#defun"><B>DEFUN</B></A> ADD (<A REL=DEFINITION HREF="../Body/03_da.htm#AMrest"><B>&REST</B></A> X) (<A REL=DEFINITION HREF="../Body/s_declar.htm#declare"><B>DECLARE</B></A> (<A REL=DEFINITION HREF="../Body/d_dynami.htm#dynamic-extent"><B>DYNAMIC-EXTENT</B></A> X)) (<A REL=DEFINITION HREF="../Body/f_apply.htm#apply"><B>APPLY</B></A> #'+ X))<P>
|
||
|
(ADD 1 2 3) => 6<P>
|
||
|
<P>
|
||
|
I.e., useful way to declare that <A REL=DEFINITION HREF="../Body/03_da.htm#AMrest"><B>&REST</B></A> lists have dynamic extent<P>
|
||
|
- - - - - - - -<P>
|
||
|
(<A REL=DEFINITION HREF="../Body/m_defun.htm#defun"><B>DEFUN</B></A> ZAP (X Y Z)<P>
|
||
|
(<A REL=DEFINITION HREF="../Body/m_do_do.htm#do"><B>DO</B></A> ((L (<A REL=DEFINITION HREF="../Body/a_list.htm#list"><B>LIST</B></A> X Y Z) (<A REL=DEFINITION HREF="../Body/f_car_c.htm#cdr"><B>CDR</B></A> L)))<P>
|
||
|
((<A REL=DEFINITION HREF="../Body/a_null.htm#null"><B>NULL</B></A> L))<P>
|
||
|
(<A REL=DEFINITION HREF="../Body/s_declar.htm#declare"><B>DECLARE</B></A> (<A REL=DEFINITION HREF="../Body/d_dynami.htm#dynamic-extent"><B>DYNAMIC-EXTENT</B></A> L))<P>
|
||
|
(<A REL=DEFINITION HREF="../Body/f_wr_pr.htm#prin1"><B>PRIN1</B></A> (<A REL=DEFINITION HREF="../Body/f_car_c.htm#car"><B>CAR</B></A> L))))<P>
|
||
|
(ZAP 1 2 3)<P>
|
||
|
prints 123<P>
|
||
|
<P>
|
||
|
- - - - - - - -<P>
|
||
|
(<A REL=DEFINITION HREF="../Body/m_defun.htm#defun"><B>DEFUN</B></A> ZAP (N M)<P>
|
||
|
;; Computes (<A REL=DEFINITION HREF="../Body/f_random.htm#random"><B>RANDOM</B></A> (+ M 1)) at relative <A REL=DEFINITION HREF="../Body/d_optimi.htm#speed"><B>speed</B></A> of roughly O(N).<P>
|
||
|
;; It may be slow, but with a good compiler at least it<P>
|
||
|
;; doesn't waste much heap storage. :-)<P>
|
||
|
(<A REL=DEFINITION HREF="../Body/s_let_l.htm#let"><B>LET</B></A> ((A (<A REL=DEFINITION HREF="../Body/f_mk_ar.htm#make-array"><B>MAKE-ARRAY</B></A> N)))<P>
|
||
|
(<A REL=DEFINITION HREF="../Body/s_declar.htm#declare"><B>DECLARE</B></A> (<A REL=DEFINITION HREF="../Body/d_dynami.htm#dynamic-extent"><B>DYNAMIC-EXTENT</B></A> A))<P>
|
||
|
(<A REL=DEFINITION HREF="../Body/m_dotime.htm#dotimes"><B>DOTIMES</B></A> (I N) <P>
|
||
|
(<A REL=DEFINITION HREF="../Body/s_declar.htm#declare"><B>DECLARE</B></A> (<A REL=DEFINITION HREF="../Body/d_dynami.htm#dynamic-extent"><B>DYNAMIC-EXTENT</B></A> I))<P>
|
||
|
(<A REL=DEFINITION HREF="../Body/a_setf.htm#setf"><B>SETF</B></A> (<A REL=DEFINITION HREF="../Body/f_aref.htm#aref"><B>AREF</B></A> A I) (<A REL=DEFINITION HREF="../Body/f_random.htm#random"><B>RANDOM</B></A> (+ I 1))))<P>
|
||
|
(<A REL=DEFINITION HREF="../Body/f_aref.htm#aref"><B>AREF</B></A> A M)))<P>
|
||
|
(< (ZAP 5 3) 3) => T<P>
|
||
|
<P>
|
||
|
- - - - - - - -<P>
|
||
|
The following are in error, since the value of X is used outside of its<P>
|
||
|
extent:<P>
|
||
|
<P>
|
||
|
(<A REL=DEFINITION HREF="../Body/f_length.htm#length"><B>LENGTH</B></A> (<A REL=DEFINITION HREF="../Body/a_list.htm#list"><B>LIST</B></A> (<A REL=DEFINITION HREF="../Body/s_let_l.htm#let"><B>LET</B></A> ((X (<A REL=DEFINITION HREF="../Body/a_list.htm#list"><B>LIST</B></A> 1 2 3))) (<A REL=DEFINITION HREF="../Body/s_declar.htm#declare"><B>DECLARE</B></A> (<A REL=DEFINITION HREF="../Body/d_dynami.htm#dynamic-extent"><B>DYNAMIC-EXTENT</B></A> X)) X)))<P>
|
||
|
<P>
|
||
|
(<A REL=DEFINITION HREF="../Body/s_progn.htm#progn"><B>PROGN</B></A> (<A REL=DEFINITION HREF="../Body/s_let_l.htm#let"><B>LET</B></A> ((X (<A REL=DEFINITION HREF="../Body/a_list.htm#list"><B>LIST</B></A> 1 2 3))) (<A REL=DEFINITION HREF="../Body/s_declar.htm#declare"><B>DECLARE</B></A> (<A REL=DEFINITION HREF="../Body/d_dynami.htm#dynamic-extent"><B>DYNAMIC-EXTENT</B></A> X)) X)<P>
|
||
|
<A REL=DEFINITION HREF="../Body/a_nil.htm#nil"><B>NIL</B></A>)<P>
|
||
|
<P>
|
||
|
- - - - - - - -<P>
|
||
|
<P>
|
||
|
<B>Rationale:<P>
|
||
|
</B><P>
|
||
|
This permits a programmer to offer advice to an implementation about<P>
|
||
|
what may be stack-allocated for efficiency.<P>
|
||
|
<P>
|
||
|
It may be difficult or impossible for a compiler to infer this<P>
|
||
|
same information statically.<P>
|
||
|
<P>
|
||
|
Since a number of implementations offer this capability and there<P>
|
||
|
is demand from users for access to the capability, this ``codifies<P>
|
||
|
existing practice.''<P>
|
||
|
<P>
|
||
|
Because this approach is purely lexical, it does not interact badly with<P>
|
||
|
other programs in the way that the macro WITH-DYNAMIC-EXTENT (see issue<P>
|
||
|
by same name) would.<P>
|
||
|
<P>
|
||
|
<B>Current Practice:<P>
|
||
|
</B><P>
|
||
|
Symbolics Genera and Symbolics Cloe offer stack allocation, though not<P>
|
||
|
in this strategy.<P>
|
||
|
<P>
|
||
|
[KMP thinks that] Lucid supports the proposal.<P>
|
||
|
<P>
|
||
|
<B>Cost to Implementors:<P>
|
||
|
</B><P>
|
||
|
No cost is forced since implementations are permitted to simply<P>
|
||
|
ignore the <A REL=DEFINITION HREF="../Body/d_dynami.htm#dynamic-extent"><B>DYNAMIC-EXTENT</B></A> declaration.<P>
|
||
|
<P>
|
||
|
<B>Cost to Users:<P>
|
||
|
</B><P>
|
||
|
None. This change is upward compatible.<P>
|
||
|
<P>
|
||
|
There may be some hidden costs to debugging using this declaration (or any<P>
|
||
|
feature which permits the user to access dynamic extent objects without<P>
|
||
|
the compiler proving that they are appropriate). If the user misdeclares<P>
|
||
|
something and returns a pointer into the stack (or stores it in the heap),<P>
|
||
|
an undefined situation may result and the integrity of the Lisp storage<P>
|
||
|
mechanism may be compromised. Debugging these situations may be tricky,<P>
|
||
|
but users who have asked for this feature have indicated a willingness<P>
|
||
|
to deal with such costs. Nevertheless, the perils should be clearly<P>
|
||
|
documented and casual users should not be encouraged to use this<P>
|
||
|
declaration.<P>
|
||
|
<P>
|
||
|
<B>Cost of Non-Adoption:<P>
|
||
|
</B><P>
|
||
|
Some portable code would be forced to run more slowly (due to<P>
|
||
|
GC overhead), or to use non-portable language features.<P>
|
||
|
<P>
|
||
|
<B>Benefits:<P>
|
||
|
</B><P>
|
||
|
The cost of non-adoption is avoided.<P>
|
||
|
<P>
|
||
|
<B>Aesthetics:<P>
|
||
|
</B><P>
|
||
|
This declaration allows a fairly low level optimization to work<P>
|
||
|
by asking the user to <A REL=DEFINITION HREF="../Body/f_provid.htm#provide"><B>provide</B></A> only very high level information.<P>
|
||
|
The alternatives (sharpsign conditionals, some of which may<P>
|
||
|
lead to more bit-picky abstractions) are far less aesthetic.<P>
|
||
|
<P>
|
||
|
<B>Discussion:<P>
|
||
|
</B><P>
|
||
|
A previous version of this proposal suggested primitives STACK-LET<P>
|
||
|
and STACK-LET*. Consensus was that the more general declaration facility<P>
|
||
|
would be more popular.<P>
|
||
|
<P>
|
||
|
Moon came up with a description of something called a "proper part" which<P>
|
||
|
Steele formalized into the idea of an "otherwise inaccessible part". The<P>
|
||
|
two are essentially interchangeable, but Steele's description was more<P>
|
||
|
rigorous.<P>
|
||
|
<P>
|
||
|
KMP: ... it still raises the question of whether we should define <P>
|
||
|
per-function for every CL function whether any of the arguments is<P>
|
||
|
permitted to be "saved" so that CL programs don't get any funny<P>
|
||
|
surprises. If we don't, it ends up being implementor's discretion how<P>
|
||
|
to resolve cases ... and everyone might not agree that all cases are<P>
|
||
|
... obvious ...<P>
|
||
|
<P>
|
||
|
JonL: PDP10 MacLisp had a similar problem w.r.t pdlnums. That is why<P>
|
||
|
"identity" functions were so troublsome for it -- in order to<P>
|
||
|
return a guaranteed safe value, it typically had to copy it's<P>
|
||
|
pdlnum argument, thereby making some cases of "fast arithmetic" <P>
|
||
|
code much worse than interpreted code! [Remember <A REL=DEFINITION HREF="../Body/f_wr_pr.htm#print"><B>PRINT</B></A> in MacLisp?<P>
|
||
|
it returns T rather than it's argument for just this reason.]<P>
|
||
|
<P>
|
||
|
It is necessary for an optimizing compiler to know something about<P>
|
||
|
what happens to the data it passes along to "system" functions; for<P>
|
||
|
example, it could assume that <A REL=DEFINITION HREF="../Body/f_get.htm#get"><B>GET</B></A> doesn't clobber the list given<P>
|
||
|
to it, nor does it retain pointers to any part of it [what was the<P>
|
||
|
terminology in the revised proposal? "saved"? and "proper part"?]<P>
|
||
|
The issue <A HREF="iss214.htm">LISP-SYMBOL-REDEFINITION</A> might help here, in that an<P>
|
||
|
implementation's compilers could depend upon it's own internal<P>
|
||
|
database. But it wouldn't hurt at all to have some of these<P>
|
||
|
requirements "up front" in the <A REL=DEFINITION HREF="../Body/07_ffb.htm#standard"><B>standard</B></A>.<P>
|
||
|
<P>
|
||
|
It was generally agreed that we would also like to consider a proposal<P>
|
||
|
on dynamic extent functions at the next meeting. (Sandra said she would<P>
|
||
|
prepare one, and has already done so. See issue <A HREF="iss141.htm">DYNAMIC-EXTENT-FUNCTION</A>.)<P>
|
||
|
</PRE>
|
||
|
<HR>
|
||
|
|
||
|
<A REL=NAVIGATOR HREF="../Front/StartPts.htm"><IMG WIDTH=80 HEIGHT=40 ALT="[Starting Points]" SRC="../Graphics/StartPts.gif" ALIGN=Bottom></A><A REL=TOC HREF="../Front/Contents.htm"><IMG WIDTH=80 HEIGHT=40 ALT="[Contents]" SRC="../Graphics/Contents.gif" ALIGN=Bottom></A><A REL=INDEX HREF="../Front/X_Master.htm"><IMG WIDTH=80 HEIGHT=40 ALT="[Index]" SRC="../Graphics/Index.gif" ALIGN=Bottom></A><A REL=INDEX HREF="../Front/X_Symbol.htm"><IMG WIDTH=80 HEIGHT=40 ALT="[Symbols]" SRC="../Graphics/Symbols.gif" ALIGN=Bottom></A><A REL=GLOSSARY HREF="../Body/26_a.htm"><IMG WIDTH=80 HEIGHT=40 ALT="[Glossary]" SRC="../Graphics/Glossary.gif" ALIGN=Bottom></A><A HREF="../Front/X3J13Iss.htm"><IMG WIDTH=80 HEIGHT=40 ALT="[Issues]" SRC="../Graphics/Issues.gif" ALIGN=Bottom></A><BR>
|
||
|
|
||
|
<A REL=COPYRIGHT HREF="../Front/Help.htm#Legal"><I>Copyright 1996-2005, LispWorks Ltd. All rights reserved.</I></A><P>
|
||
|
</BODY>
|
||
|
</HTML>
|