% -*- Mode: TeX -*-

\term{Declarations} provide a way of specifying information for use by
program processors, such as the evaluator or the compiler.

\term{Local declarations} can be embedded in executable code using \misc{declare}.
\term{Global declarations} 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},
     \declref{notinline},
     \declref{safety},
 and \declref{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} 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&notinline&\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
\newterm{free declarations}.

% \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

%% 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:

\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

In the following:

\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:

\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, 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:

\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 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}
