KCL recognizes all declaration specifiers defined in the
Common Lisp Reference Manual. The syntax of each such declaration
specifier is exactly the same as defined
in the Common Lisp Reference Manual. In addition, KCL recognizes the
object declaration specifier which is specific to KCL.
special { variable-name }*[Declaration
Specifier]
- The interpreter and the compiler of KCL both treat special
declarations exactly as described in the Common Lisp Reference Manual.
type type { variable-name }*[Declaration
Specifier]
- A type proclamation (type type var1
var2 ... ) specifies that the dynamic values of the
named variables are of the type type. A local type
declaration specifies that the variables mentioned are bound by the
surrounding construct and have values of the type type during
execution of the surrounding construct. The compiler issues a warning if
one of the named variables is not bound by
the surrounding construct. The information given by
type declarations is used by the compiler to optimize
the compiled code. The behavior of the compiled code
is unpredictable if a wrong type declaration is supplied. The
compiler detects certain wrong type declarations at compile
time. For example,
>(defun foo (x y)
(declare (fixnum x) (character y))
(setq x y)
...))
foo
>(compile 'foo)
; (defun foo ...) is being compiled.
;; Warning: Type mismatches between x and y.}
- See Section 7.3 for further information on type declarations.
type {variable-name }*[Declaration
Specifier]
- (type var1 var2 ...) is equivalent to
(type type var1 var2 ... ), provided
that type is one of the symbols in Table 4-1
of the Common Lisp Reference Manual, other
than function. Declaration specifications that begin
with function are
regarded as function declarations (see below).
function function-name argument-types.
return-types[Declaration Specifier]
- A function declaration is used to obtain type
information for function call forms.
That is, a function declaration specifies
the argument and the return
types of each form that calls the named function.
(defun foo ()
(declare (function bar (character) fixnum))
(+ (bar (atcholi1)) (bar (atcholi2))))
- In this example, the function declaration
specifies that
the two functions atcholi1 and atcholi2 both return
character objects when called
within the body of foo, and that the function bar
returns fixnum objects when called within the body of foo.
The type information given by
function declarations is used by the compiler to optimize
the compiled code. The behavior of the compiled code
is unpredictable if a wrong function declaration is supplied.
The compiler detects certain wrong function declarations at compile
time. For example,
>(defun foo (x)
(declare (fixnum x)
(function bar (character) fixnum))
(bar x))
foo
>(compile 'foo)
; (defun foo ...) is being compiled.
;; Warning: The type of the form x is not character.
- However, the compiler does not check the number of arguments, and thus,
the following function definition will be compiled successfully without
any warnings.
(defun foo ()
(declare (function bar (character character) fixnum))
(+ (bar (atcholi1)) (bar (atcholi2) (atcholi3) (atcholi4))))
- For this definition, the compiler assumes that the three functions
atcholi1, atcholi2, and atcholi3 will
return fixnum objects. The return type of atcholi4 is
unknown at compile time.
- The complete syntax of a function declaration is:
(function function-name
( { type }* [ { &optional | &rest | &key } { thing }* ] )
{ (values { type }* ) | { type }* }
)
- Although &optional, &rest, and &key markers
may appear in the list of argument types, only those types are
recognized that appear before any such markers and the rest of the
list is simply ignored. Note that
functions with &optional, &rest, or &key
parameters may still be declared by function declarations because
of the use of function declarations mentioned above.
- The values construct in the specification of return types is almost
useless: (function function-name argument-types
(values type1 type2 ... )) is equivalent
to (function function-name
argment-types type1 type2 ... ) . We, the implementors of
KCL wonder why the value construct was introduced in Common Lisp.
- See Section 7.3 for further information on function declarations.
ftype function-type {function-name}*[Declaration Specifier]
- function-type must be a list whose first element
is the symbol function.
(ftype (function. rest) function-name-1 ...
function-name-n) is
equivalent to n consecutive function declarations
(function function-name-1 . rest) ...
(function function-name-n . rest).
notinline {function-name}*[Declaration
Specifier]
- (notinline function1 function2 ... ) specifies
that the compiler should not compile the named functions in-line. Calls
to the named functions can be traced and an event (see Section 5.4) is pushed
on the event stack when any one of the named functions is invoked.
inline {function-name}*[Declaration
Specifier]
- An inline proclamation cancels currently
effective notinline proclamations, and a local
inline declaration locally shadows currently effective
notinline declarations.
>(defun foo (x)
(cons (car x)
(locally (declare (inline car)) (car x))))
foo
>(defun bar (x)
(cons (car x)
(locally (declare (inline car)) (car x))))
foo
>(proclaim '(notinline car))
nil
>(compile 'foo)
...
>(proclaim '(inline car))
nil
>(compile 'bar)
...
- Usually, primitive functions such as car are
compiled in-line. Therefore, in this example, only the first
call to car within foo is compiled not in-line.
- In general, the KCL compiler compiles functions in-line
whenever possible. Thus an inline
declaration (inline function1
function2 ... ) is worthless if none of the named functions
have previously been declared to be notinline .
ignore {variable-name}*[Declaration
Specifier]
- Usually, the compiler issues a warning if a lexical variable is
never referred to. (ignore var1 ... varn )
causes the compiler not to issue a warning even if the named variables are
never referred to. The compiler issues a warning if
one of the named variables is not bound by
the surrounding construct, or if a named variable is
actually referred to. ignore proclamations are simply ignored.
optimize { { (quality value ) | quality}}*[Declaration Specifier]
- KCL supports the four optimize qualities listed in the
Common Lisp Reference Manual. speed
and compilation-speed are used to set up the optimization switch
of the C language compiler which is invoked to compile the C-language
code generated by the KCL compiler (see Chapter 6). (optimize
(speed n )) and
(optimize (compilation-speed it m )) are equivalent,
where n and m are integers between 0
and 3 , and m is equal to 3-n. When
a KCL session is started, the speed quality is set
to 3. That is, by default, the compiler generates the fastest
code in the longest compilation time. The space quality
specifies whether the code size is important or not: The compiled code
is a little bit larger and faster when compiled with the space
quality 0, than when compiled with the space quality
1, 2, or 3. When a KCL session is started,
the space quality is set to 0. The safety
quality determines how much runtime error checking code should be embedded in
the compiled code. If the safety quality is 0, the
compiled code
scarcely does runtime error checking. If
the safety quality is 1 , then the compiled code for a
function will check the number of arguments to the function
at runtime. If the safety quality is 2 or 3, then the
compiled code does full runtime error checking. In addition, the
highest quality value 3 causes the compiler to treat all
functions as if they were declared to be notinline. When a KCL
session is started, the safety quality is set to 0.
declaration {name}*[Declaration
Specifier]
- A declaration declaration is used exactly as specified in the
Common Lisp Reference Manual.
object {variable-name}*[Declaration
Specifier]
- This is the only declaration specifier that is specific to KCL.
(object var1 ... varn ) affects only variable bindings and
specifies that the named variables can be allocated in the
C stack (see Section 7.3). The compiler issues a warning if
one of the named variables is not bound by the surrounding
construct. object proclamations are simply ignored.