Declaration Specifiers

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.