Next: Type specifiers, Previous: Declarations, Up: Declarations
ECL recognizes all declaration specifiers defined in [see Steele:84].
The syntax of each such declaration specifier is exactly the same as defined in
[see Steele:84]. In addition, ECL recognizes the object
declaration specifier which is specific to ECL.
The interpreter and the compiler of ECL both treat special declarations exactly as described in [see Steele:84].
A
type
proclamation(type
type var1 var2...)
specifies that the dynamic values of the named variables are of the type type. A localtype
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 bytype
declarations is used by the compiler to optimize the compiled code. The behavior of the compiled code is unpredictable if a wrongtype
declaration is supplied. The compiler detects certain wrongtype
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 var1 var2 ...) is equivalent to
(type
type var1 var2...)
, provided that type is one of the symbols in Table 4-1 of [see Steele:84], other thanfunction
. Declaration specifications that begin withfunction
are regarded asfunction
declarations (see below).
A
function
declaration is used to obtain type information for function call forms. That is, afunction
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 ...)
.
See Section 7.3 for further information on function
declarations.
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 consecutivefunction
declarations(function
function-name-1.
rest)
...(function
function-name-n.
rest)
.
(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.
An
inline
proclamation cancels currently effectivenotinline
proclamations, and a localinline
declaration locally shadows currently effectivenotinline
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 ECL 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
.
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.
ECL supports the four
optimize
qualities listed in the [see Steele:84].
speed
andcompilation-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 ECL compiler (see Chapter 6).(optimize (speed
n))
and(optimize (compilation-speed
m))
are equivalent, where n and m are integers between 0 and 3, and m is equal to 3-n. When a ECL session is started, thespeed
quality is set to 3. That is, by default, the compiler generates the fastest code in the longest compilation time. Thespace
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 ECL session is started, thespace
quality is set to 0. Thesafety
quality determines how much runtime error checking code should be embedded in the compiled code. If thesafety
quality is 0, the compiled code scarcely does runtime error checking. If thesafety
quality is 1, then the compiled code for a function will check the number of arguments to the function at runtime. If thesafety
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 benotinline
. When a ECL session is started, thesafety
quality is set to 0.
A
declaration
declaration is used exactly as specified in the [see Steele:84].
This is the only declaration specifier that is specific to ECL.
(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.