% -*- Mode: TeX -*- \newtermidx{Declarations}{declaration} provide a way of specifying information for use by program processors, such as the evaluator or the compiler. \newtermidx{Local declarations}{local declaration} can be embedded in executable code using \misc{declare}. \newtermidx{Global declarations}{global declaration}, or \newtermidx{proclamations}{proclamation}, are established by \funref{proclaim} or \macref{declaim}. %% 9.3.0 1 \Thespecform{the} provides a shorthand notation for making a \term{local declaration} about the \term{type} of the \term{value} of a given \term{form}. %% 9.0.0 4 % This is redundant with the next sentence. --sjl 3 Mar 92 % The consequences are undefined if a program violates a type declaration. %% 9.2.0 1 %% 9.2.0 6 The consequences are undefined if a program violates a \term{declaration} or a \term{proclamation}. \beginSubsection{Minimal Declaration Processing Requirements} In general, an \term{implementation} is free to ignore \term{declaration specifiers} except for the \declref{declaration}\idxref{declaration}, \declref{notinline}\idxref{notinline}, \declref{safety}\idxref{safety}, and \declref{special}\idxref{special} \term{declaration specifiers}. A \declref{declaration} \term{declaration} must suppress warnings about unrecognized \term{declarations} of the kind that it declares. If an \term{implementation} does not produce warnings about unrecognized declarations, it may safely ignore this \term{declaration}. A \declref{notinline} \term{declaration} must be recognized by any \term{implementation} that supports inline functions or \term{compiler macros} in order to disable those facilities. An \term{implementation} that does not use inline functions or \term{compiler macros} may safely ignore this \term{declaration}. A \declref{safety} \term{declaration} that increases the current safety level must always be recognized. An \term{implementation} that always processes code as if safety were high may safely ignore this \term{declaration}. A \declref{special} \term{declaration} must be processed by all \term{implementations}. \endSubsection%{Minimal Declaration Processing Requirements} \beginSubsection{Declaration Specifiers} A \newterm{declaration specifier} is an \term{expression} that can appear at top level of a \misc{declare} expression or a \macref{declaim} form, or as the argument to \funref{proclaim}. It is a \term{list} whose \term{car} is a \term{declaration identifier}, and whose \term{cdr} is data interpreted according to rules specific to the \term{declaration identifier}. \endSubsection%{Declaration Specifiers} \beginSubsection{Declaration Identifiers} \Thenextfigure\ shows a list of all \term{declaration identifiers}\idxterm{declaration identifier} defined by this standard. \issue{DECLARE-FUNCTION-AMBIGUITY:DELETE-FTYPE-ABBREVIATION} \displaythree{Common Lisp Declaration Identifiers}{ declaration&ignore&special\cr dynamic-extent&inline&type\cr ftype¬inline&\cr ignorable&optimize&\cr } %FUNCTION removed. \endissue{DECLARE-FUNCTION-AMBIGUITY:DELETE-FTYPE-ABBREVIATION} %% 9.2.0 20 An implementation is free to support other (\term{implementation-defined}) \term{declaration identifiers} as well. % Sections 3.2.2.3 and 3.2.5 both classify this as an ordinary warning. % --sjl 3 Mar 92 % A warning \oftype{style-warning} might be issued A warning might be issued if a \term{declaration identifier} is not among those defined above, %Added for Barmar: -kmp 11-Jan-91 is not defined by the \term{implementation}, is not a \term{type} \term{name}, and has not been declared in a \declref{declaration} \term{proclamation}. % I can't figure out where this paragraph came from, and I'm convinced % it's wrong. Issue DECLARATION-SCOPE was intended to assign consistent % scoping rules to all declarations based only on whether they are ``bound'' % or ``free''. Allowing random scoping rules will also totally defeat % the proposed define-declaration extensions. --sjl 7 Mar 92 %For \term{implementation-defined} \term{declaration identifiers}, %the \term{scope} of \term{free declarations} and \term{bound declarations} %is \term{implementation-defined}. \beginsubsubsection{Shorthand notation for Type Declarations} %Barrett says class objects are ok here, too. A \term{type specifier} can be used as a \term{declaration identifier}. \f{(\param{type-specifier} \starparam{var})} is taken as shorthand for \f{(type \param{type-specifier} \starparam{var})}. \endsubsubsection%{Shorthand notation for Type Declarations} \endSubsection%{Declaration Identifiers} \beginSubsection{Declaration Scope} \DefineSection{DeclScope} % Declarations can be divided into two kinds: those that concern % the \term{bindings} of variables, and those that do not. % The \declref{special} declaration falls into both classes. % Declarations that concern \term{variable} \term{bindings} apply % only to the \term{bindings} made by the \term{form} at the head of % whose body they appear. % % All declarations introduced with \misc{declare} fall into two classes: % \term{bound declarations} and \term{free declarations}. % \term{Bound declarations} affect both a binding and any references; % \term{free declarations} affect only references. % Some declarations may be used in either way, depending on context. % %% The above rewritten with help from Sandra and Moon. -kmp 22-Aug-91 \term{Declarations} can be divided into two kinds: those that apply to the \term{bindings} of \term{variables} or \term{functions}; and those that do not apply to \term{bindings}. A \term{declaration} that appears at the head of a binding \term{form} and applies to a \term{variable} or \term{function} \term{binding} made by that \term{form} is called a \newterm{bound declaration}; such a \term{declaration} affects both the \term{binding} and any references within the \term{scope} of the \term{declaration}. \term{Declarations} that are not \term{bound declarations} are called \newtermidx{free declarations}{free declaration}. % \term{Free declarations} that apply to % \term{bindings} affect only references to those \term{bindings}. A \term{free declaration} in a \term{form} $F1$ that applies to a \term{binding} for a \term{name} $N$ \term{established} by some \term{form} $F2$ of which $F1$ is a \term{subform} affects only references to $N$ within $F1$; it does not to apply to other references to $N$ outside of $F1$, nor does it affect the manner in which the \term{binding} of $N$ by $F2$ is \term{established}. \term{Declarations} that do not apply to \term{bindings} can only appear as \term{free declarations}. % Common Lisp prohibits binding the same name twice in the same binding form. % It has been proposed that multiple bindings be permitted for LET*, DO*, PROG* % forms and for &AUX variables in lambda expressions, but never approved. % In an implementation which permits multiple bindings, `bound' declarations % should probably be treated as if there were a separate `bound' declaration % for each of the bindings, but for us to say so would really go beyond the % scope of this document. As such, we'll just not say anything and leave it to % any implementation which defines that circumstance to also define the relationship % to bound declarations. -kmp 22-Aug-91 %% Rewritten by Sandra in response to Margolin #7, Dalton #3, Moon #7 (First Public Review) % %% 9.1 % Some \term{forms} contain pieces of code that, properly speaking, % are not part of the body of the \term{form}. Examples of this % are initialization forms that provide values for bound variables, % and the result forms of iteration \term{forms}. % % \issue{DECLARATION-SCOPE:NO-HOISTING} % % The \term{scope} of a \term{declaration} located at the head of % a \term{special form}, \term{macro form}, or \term{lambda expression} is as follows: % \beginlist % \itemitem{1.} % It always includes the body forms as well as any \term{step} or exit \term{forms}. % \itemitem{2.} % It also includes the \term{scope} of the name binding, if any, to which % it applies (\specref{let}, \misc{lambda}, \specref{flet}, \macref{do}, etc. % introduce name bindings; \specref{locally} does not). % \endlist % % %!!!! RPG: I'm tired but this doesn't make sense to me at all. % This prescription depends on the fact that the \term{scope} of name bindings % is already well-defined. % Whether or not a particular declaration affects an initialization form % (such as for \specref{let} or \specref{let*}) % depends solely on whether it is % applied to a variable or function name being bound whose \term{scope} % includes such \term{forms}. % In this sense, the above specification limits the % \term{scope} of declarations for name bindings to be exactly the % \term{scope} of the % name binding itself. % There is no ``hoisting'' for declarations in \term{special forms} or % \term{lambda expressions}; % the only initialization forms affected by a declaration % are those included indirectly, by the effect, if any, that a % declaration has on a name binding. % Thus there is no % ``hoisting'' of the special declarations in the following example: % % % \code % % (defun bar (x y) ;[1] 1st occurrence of x % % (let ((old-x x) ;[2] 2nd occurrence of x % % (x y)) ;[3] 3rd occurrence of x % % (declare (special x)) % % (list old-x x))) % % \endcode % % % % Laubsch: ? % % Barmar: Say what [the above] example is supposed to return. % % RPG: Also, say explicitly which bindings and references are special. % % \code % (let ((x 1)) ;[1] 1st occurrence of x % (declare (special x)) ;[2] 2nd occurrence of x % (let ((x 2)) ;[3] 3rd occurrence of x % (let ((old-x x) ;[4] 4th occurrence of x % (x 3)) ;[5] 5th occurrence of x % (declare (special x)) ;[6] 6th occurrence of x % (list old-x x)))) ;[7] 7th occurrence of x % \EV (2 3) % \endcode % % The first occurrence of \f{x} \term{establishes} a \term{dynamic binding} % of \f{x} because of the \declref{special} \term{declaration} for \f{x} % in the second line. The third occurrence of \f{x} \term{establishes} a % \term{lexical binding} of \f{x} (because there is no \declref{special} % \term{declaration} in the corresponding \macref{let} \term{form}). % The fourth occurrence of \f{x} \term{x} is a reference to the % \term{lexical binding} of \f{x} established in the third line. % The fifth occurrence of \f{x} \term{establishes} a \term{dynamic binding} % of \term{x} for the body of the \macref{let} \term{form} that begins on % that line because of the \declref{special} \term{declaration} for \f{x} % in the sixth line. The reference to \f{x} in the fourth line is not % affected by the \declref{special} \term{declaration} in the sixth line % because that reference is not within the ``would-be \term{lexical scope}'' % of the \term{variable} \f{x} in the fifth line. The reference to \f{x} % in the seventh line is a reference to the \term{dynamic binding} of \term{x} % \term{established} in the fifth line. % % Those declarations not correlated with any name \term{binding} do % not cover any of the initialization forms; their \term{scope} only % includes the body as well as any ``stepper'' or result forms. In a % sense, the above specification limits the \term{scope} of these % kinds of declarations to be the same as an arbitrary name % \term{binding} in a \specref{let}, \specref{flet}, % \issue{WITH-ADDED-METHODS:DELETE} % %\macref{with-added-methods}, % \endissue{WITH-ADDED-METHODS:DELETE} % \issue{GENERIC-FLET-POORLY-DESIGNED:DELETE} % %\specref{generic-flet}, % %\specref{generic-labels}, % \endissue{GENERIC-FLET-POORLY-DESIGNED:DELETE} % and \specref{labels} % \term{form}. % %[See also the issue DECLARE-TYPE-FREE.] % % In the following:\idxref{notinline} % % \code % (lambda (&optional (x (foo 1))) ;[1] % (declare (notinline foo)) ;[2] % (foo x)) ;[3] % \endcode % % the \term{call} to \f{foo} in the first line might be % compiled inline even though the \term{call} to \f{foo} in % the third line must not be. This is because % the \declref{notinline} \term{declaration} % for \f{foo} in the second line applies only to the body on the % third line. In order to suppress inlining for both \term{calls}, % one might write:\idxref{notinline} % % \code % (locally (declare (notinline foo)) ;[1] % (lambda (&optional (x (foo 1))) ;[2] % (foo x))) ;[3] % \endcode % % or, alternatively:\idxref{notinline} % % \code % (lambda (&optional ;[1] % (x (locally (declare (notinline foo)) ;[2] % (foo 1)))) ;[3] % (declare (notinline foo)) ;[4] % (foo x)) ;[5] % \endcode % % In the following:\idxterm{type declaration} % % \code % (defun foo (x) ;[1] % (if (typep x 'integer) ;[2] % (list (let ((y (+ x 42))) ;[3] % (declare (fixnum x y)) ;[4] % y) ;[5] % (+ x 42)) ;[6] % `(foo ,x))) ;[7] % \endcode % % \f{x} is not initially (\eg in the first line) known to be a \term{fixnum} % since the scope of the \declref{fixnum} \term{declaration} for \f{x} in the fourth line % covers only the body of the \macref{let} form in the fifth line, but not the % \term{initialization form} for \f{y} in the third line. The compiler can assume that % \f{x} is not greater than the value of \f{(- most-positive-fixnum 42)} because \f{y} % has been declared to be a \term{fixnum} in the fourth line. % Even so, neither the \term{call} to \funref{+} in the third line % nor the one in the sixth line % may be optimized into \term{calls} to \term{implementation-dependent} % \term{fixnum}-only arithmetic operators, % just in case the call to \f{foo} looks something like: % % \code % (foo (- most-negative-fixnum 1)) % \endcode % % In following:\idxterm{type declaration} % % \code % (defun foo (x) ;[1] % (if (typep x 'integer) ;[2] % (list (let ((y (+ x 42))) ;[3] % (declare (fixnum x)) ;[4] % x ;[5] % y) ;[6] % (+ x 42)) ;[7] % `(foo ,x))) ;[8] % \endcode % % \f{x} can be determined to be a \term{fixnum} throughout % the third through seventh lines, but only by inference % from the fact that the reference to \f{x} in the fifth line % (the only reference to which the \declref{fixnum} \term{declaration} % in the fourth line applies) % is known to be a \term{fixnum}. Since the compiler is capable of detecting that % there are no \term{assignments} to \f{x}, it may reason that \f{x} is a \term{fixnum} % throughout even though there is no explicit \term{declaration}. % However, since there is no \declref{fixnum} \term{declaration} for \f{y} (as there % was in the previous example), the compiler may not assume that the result of the % addition in the third line is a \term{fixnum}. Therefore, % neither \term{call} to \funref{+} (one the third and seventh lines) % may be optimized into \term{calls} to \term{implementation-dependent} % \term{fixnum}-only arithmetic operators, % just in case the call to \term{foo} looks something like: % % \code % (foo most-positive-fixnum) % \endcode % % However, in the following:\idxterm{type declaration} % % \code % (defun foo (x) ;[1] % (if (typep x 'integer) ;[2] % (list (let ((y (the fixnum (+ x 42)))) ;[3] % (declare (fixnum x y)) ;[4] % x ;[5] % y) ;[6] % (+ x 42)) ;[7] % `(foo ,x))) ;[8] % \endcode % % the compiler can infer that \f{x} is a \term{fixnum} throughout % the third through seventh lines by reasoning similar % to that for the previous example. Further, it can infer that the result of the % call to \funref{+} in the third line is a \term{fixnum} because of the \declref{fixnum} % \term{declaration} in the fourth line. Consequently, that \term{call} to \funref{+} % may be optimized into a \term{call} to an \term{implementation-dependent} % \term{fixnum}-only arithmetic operator. Further, the \term{call} to \funref{+} % in the seventh line may be similarly optimized because the compiler can prove that % the \f{x} in that line has the same \term{value}. % % \endissue{DECLARATION-SCOPE:NO-HOISTING} \issue{DECLARATION-SCOPE:NO-HOISTING} \issue{WITH-ADDED-METHODS:DELETE} \issue{GENERIC-FLET-POORLY-DESIGNED:DELETE} The \term{scope} of a \term{bound declaration} is the same as the %% Per X3J13. -kmp 5-Oct-93 %\term{scope} \term{lexical scope} of the \term{binding} to which it applies; %% Added per X3J13. -kmp 5-Oct-93 for \term{special variables}, this means the \term{scope} that the \term{binding} would have had had it been a \term{lexical binding}. Unless explicitly stated otherwise, the \term{scope} of a \term{free declaration} includes only the body \term{subforms} of the \term{form} at whose head it appears, and no other \term{subforms}. The \term{scope} of \term{free declarations} specifically does not include \term{initialization forms} for \term{bindings} established by the \term{form} containing the \term{declarations}. Some \term{iteration forms} include step, end-test, or result \term{subforms} that are also included in the \term{scope} of \term{declarations} that appear in the \term{iteration form}. Specifically, the \term{iteration forms} and \term{subforms} involved are: \beginlist \item{\bull} \macref{do}, \macref{do*}: \param{step-forms}, \param{end-test-form}, and \param{result-forms}. \item{\bull} \macref{dolist}, \macref{dotimes}: \param{result-form} \item{\bull} \macref{do-all-symbols}, \macref{do-external-symbols}, \macref{do-symbols}: \param{result-form} \endlist \endissue{GENERIC-FLET-POORLY-DESIGNED:DELETE} \endissue{WITH-ADDED-METHODS:DELETE} \beginsubsubsection{Examples of Declaration Scope} Here is an example illustrating the \term{scope} of \term{bound declarations}. \code (let ((x 1)) ;[1] 1st occurrence of x (declare (special x)) ;[2] 2nd occurrence of x (let ((x 2)) ;[3] 3rd occurrence of x (let ((old-x x) ;[4] 4th occurrence of x (x 3)) ;[5] 5th occurrence of x (declare (special x)) ;[6] 6th occurrence of x (list old-x x)))) ;[7] 7th occurrence of x \EV (2 3) \endcode The first occurrence of \f{x} \term{establishes} a \term{dynamic binding} of \f{x} because of the \declref{special} \term{declaration} for \f{x} in the second line. The third occurrence of \f{x} \term{establishes} a \term{lexical binding} of \f{x} (because there is no \declref{special} \term{declaration} in the corresponding \macref{let} \term{form}). The fourth occurrence of \f{x} \term{x} is a reference to the \term{lexical binding} of \f{x} established in the third line. The fifth occurrence of \f{x} \term{establishes} a \term{dynamic binding} of \term{x} for the body of the \macref{let} \term{form} that begins on that line because of the \declref{special} \term{declaration} for \f{x} in the sixth line. The reference to \f{x} in the fourth line is not affected by the \declref{special} \term{declaration} in the sixth line because that reference is not within the ``would-be \term{lexical scope}'' of the \term{variable} \f{x} in the fifth line. The reference to \f{x} in the seventh line is a reference to the \term{dynamic binding} of \term{x} \term{established} in the fifth line. Here is another example, to illustrate the \term{scope} of a \term{free declaration}. In the following: \code (lambda (&optional (x (foo 1))) ;[1] (declare (notinline foo)) ;[2] (foo x)) ;[3] \endcode the \term{call} to \f{foo} in the first line might be compiled inline even though the \term{call} to \f{foo} in the third line must not be. This is because the \declref{notinline} \term{declaration} for \f{foo} in the second line applies only to the body on the third line. In order to suppress inlining for both \term{calls}, one might write: \code (locally (declare (notinline foo)) ;[1] (lambda (&optional (x (foo 1))) ;[2] (foo x))) ;[3] \endcode or, alternatively: \code (lambda (&optional ;[1] (x (locally (declare (notinline foo)) ;[2] (foo 1)))) ;[3] (declare (notinline foo)) ;[4] (foo x)) ;[5] \endcode Finally, here is an example that shows the \term{scope} of \term{declarations} in an \term{iteration form}. \code (let ((x 1)) ;[1] (declare (special x)) ;[2] (let ((x 2)) ;[3] (dotimes (i x x) ;[4] (declare (special x))))) ;[5] \EV 1 \endcode In this example, the first reference to \f{x} on the fourth line is to the \term{lexical binding} of \f{x} established on the third line. However, the second occurrence of \f{x} on the fourth line lies within the \term{scope} of the \term{free declaration} on the fifth line (because this is the \param{result-form} of the \macref{dotimes}) and therefore refers to the \term{dynamic binding} of \f{x}. \endissue{DECLARATION-SCOPE:NO-HOISTING} \endsubsubsection%{Examples of Declaration Scope} \endSubsection%{Declaration Scope}