These notes are covered by the GNU GFDL:
Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.1 or any later version published by the Free Software Foundation; with the Invariant Sections being this section [FIXME], with the Front-Cover Texts being this section [FIXME], and with the Back-Cover Texts being this section [FIXME]. A copy of the license is not yet [FIXME] included in the section entitled "GNU Free Documentation License".
Table of Contents
These notes discuss the CLISP implementation of Common Lisp by
and
The current maintainers areDr Michael Stoll
Westerwaldweg 22
Remagen-Oberwinter
D-53424 Germany
http://www.math.uni-duesseldorf.de/home/stoll
andDr Bruno Haible
This implementation is mostly conforming to the [ANSI CL standard] available on-line as the [Common Lisp HyperSpec] (but the printed ANSI document remains the authoritative source of information). [ANSI CL standard] supersedes the earlier specifications [CLtL1] and [CLtL2].
The first part of these notes is indexed in parallel to the [Common Lisp HyperSpec] and documents the differences between the CLISP implementation of Common Lisp and the [ANSI CL standard].
The second part documents the CLISP garbage-collection (for developers only) and the bytecodes generated by the compiler (i.e., what is printer by DISASSEMBLE).
The third part documents the CLISP extensions.
Table of Contents
Table of Contents
The final delimiter of an interactive stream: On Unix, the user has to type Ctrl-D at the beginning of a line. On DOS or Win32, the user has to type Ctrl-Z, followed by Return. This final delimiter is never actually seen by programs; no need to test for #\^D or #\^Z - use READ-CHAR-NO-HANG to check for end of stream. Calling CLEAR-INPUT on the stream removes the end-of-stream state, thus making it available for further input.
A newline character can be entered by the user by pressing the Newline key or, on the numeric keypad, the Enter key.
Safety settings are ignored; therefore where the standard uses the phrase “should signal an error”, an ERROR is signaled.
The class precedence lists of the system classes CLASS BUILT-IN-CLASS, STRUCTURE-CLASS, STANDARD-CLASS, STANDARD-METHOD contain the class STRUCTURE-OBJECT instead of the class STANDARD-OBJECT.
The 28 symbols missing from the “COMMON-LISP” package (out of 978 specified by the [ANSI CL standard]):
Table of Contents
A "reserved token", i.e., a token that has potential number syntax but cannot be interpreted as a number, is interpreted as symbol when being read.
When creating a symbol from a token, no character attributes are removed.
When a token with package markers is read, then no checking is done whether the package part and the symbol-name part do not have number syntax. (What's the purpose of this check?) So we consider tokens like USER:: or :1 or LISP::4711 or 21:3 as symbols.
The backquote read macro also works when nested. Example:
(EVAL ``(,#'(LAMBDA () ',a) ,#'(LAMBDA () ',b))) = (EVAL `(list #'(LAMBDA () ',a) #'(LAMBDA () ',b))) = (EVAL (list 'list (list 'function (list 'lambda nil (list 'quote a))) (list 'function (list 'lambda nil (list 'quote b)))))
Multiple backquote combinations like ,,@ or ,@,@ are not implemented. Their use would be confusing anyway.
Reader macros are also defined for the following:
| Macro | Meaning |
|---|---|
| #, | load-time evaluation |
| #Y | function objects and file encodings |
| #" | pathname |
Table of Contents
All the functions built by FUNCTION, COMPILE and the like are atoms. There are built-in functions written in C, compiled functions (both of type COMPILED-FUNCTION) and interpreted functions (of type FUNCTION).
EXT:THE-ENVIRONMENT As in Scheme, the macro (ext:the-environment) returns the current lexical environment. This works only in interpreted code and is not compilable!
(ext:eval-env form &OPTIONAL env) evaluates a form in a given lexical environment, just as if the form had been a part of the program that the environment came from.
Compiler macros are expanded in the compiled code only, and ignored by the interpreter.
The declarations (TYPE type variable ...), (FTYPE type function ...), (OPTIMIZE (quality value) ...) are ignored by the interpreter and the compiler.
The [ANSI CL standard] declaration (OPTIMIZE (debug ...)) is legal.
The [ANSI CL standard] declaration (IGNORABLE variable ...) affects the variable binding for the variable variable. The compiler will not warn about the variable, regardless whether it is used or not.
The declaration (compile) has the effect that the current form is compiled prior to execution. Examples:
(LOCALLY (DECLARE (compile)) form)executes a compiled version of form.
(LET ((x 0)) (FLET ((inc () (DECLARE (compile)) (INCF x)) (dec () (DECF x))) (VALUES #'inc #'dec)))returns two functions. The first is compiled and increments x, the second is interpreted (slower) and decrements the same x.
The type assertion (THE value-type form) enforces a type check in interpreted code. No type check is done in compiled code. See also the ext:ethe macro.
The initial value of an &AUX variable in a boa lambda list is the value of the corresponding slot's initial form.
(PROCLAIM '(SPECIAL variable)) declarations may not be undone. The same holds for DEFVAR, DEFPARAMETER and DEFCONSTANT declarations.
It is an error if a DEFCONSTANT variable is bound at the moment the DEFCONSTANT is executed, but DEFCONSTANT does not check this.
Constants may not be bound dynamically or lexically.
Table of Contents
The general form of the COMPLEX type specifier is (COMPLEX type-of-real-part type-of-imaginary-part). The type specifier (COMPLEX type) is equivalent to (COMPLEX type type).
The [ANSI CL standard] type specifier (REAL low high) denotes the real numbers between low and high.
DEFTYPE lambda lists are subject to destructuring (nested lambda lists are allowed, as in DEFMACRO) and may contain a &WHOLE marker, but not an &ENVIRONMENT marker.
(ext:type-expand-1 typespec) If typespec is a user-defined type, ext:type-expand-1 will expand it once and return two values: the expansion and T. If typespec is not a user-defined type, then the two values typespec and NIL are returned.
(ext:type-expand typespec) This is similar to (ext:type-expand-1 typespec), but repeatedly expands typespec until it is no longer a user-defined type. A second value of T or NIL is returned as for ext:type-expand-1, indicating whether the original typespec was a user-definedtype.
The possible results of TYPE-OF are:
FIXNUM, BIGNUM, RATIONAL, SHORT-FLOAT, SINGLE-FLOAT, DOUBLE-FLOAT, LONG-FLOAT, COMPLEX
(ARRAY element-type dimensions), (SIMPLE-ARRAY element-type dimensions)
(VECTOR T size), (SIMPLE-VECTOR size)
(STRING size), (SIMPLE-STRING size)
(BASE-STRING size), (SIMPLE-BASE-STRING size)
(BIT-VECTOR size), (SIMPLE-BIT-VECTOR size)
STREAM, FILE-STREAM, SYNONYM-STREAM, BROADCAST-STREAM, CONCATENATED-STREAM, TWO-WAY-STREAM, ECHO-STREAM, STRING-STREAM
PACKAGE, HASH-TABLE, READTABLE, PATHNAME, LOGICAL-PATHNAME, RANDOM-STATE, byte
special-operator, load-time-eval, SYMBOL-MACRO, encoding, foreign-pointer, foreign-address, foreign-variable, foreign-function
weak-pointer, read-label, frame-pointer, system-internal
address (should not occur)
any other symbol (structure types or CLOS classes)
a class (CLOS classes without proper name)
The CLOS symbols are EXPORTed from the package “CLOS” and thus normally visible in all user packages. If you do not want them (for example, if you want to use the PCL implementation of CLOS instead of the native one), do (UNUSE-PACKAGE "CLOS").
DEFCLASS It is required that the superclasses of a class be defined before the DEFCLASS form for the class is evaluated.
DEFCLASS supports the option :metaclass STRUCTURE-CLASS. This option is necessary in order to define a subclass of a DEFSTRUCT-defined structure type using DEFCLASS instead of DEFSTRUCT.
When CALL-NEXT-METHOD is called with arguments, the rule that the ordered set of applicable methods must be the same as for the original arguments is enforced by the implementation only in interpreted code.
There is a generic function clos:no-primary-method (similar to NO-APPLICABLE-METHOD) which is called when a generic function of the class STANDARD-GENERIC-FUNCTION is invoked and no primary method on that generic function is applicable.
clos:generic-flet and clos:generic-labels are implemented as macros, not as special operators. They are not imported into the packages “COMMON-LISP-USER” and “COMMON-LISP” because of the [ANSI CL standard] issue GENERIC-FLET-POORLY-DESIGNED:DELETE.
The function ENSURE-GENERIC-FUNCTION is not implemented.
ADD-METHOD can put methods into other generic functions than the one the method came from.
PRINT-OBJECT is only called on objects of type STANDARD-OBJECT and STRUCTURE-OBJECT. It is not called on other objects, like CONSes and NUMBERs, due to the performance concerns.
DOCUMENTATION still has the [CLtL1] implementation.
Among those classes listed in Figure 4-8, only the following are instances of BUILT-IN-CLASS:
DEFCLASS supports the :metaclass option. Possible values are STANDARD-CLASS (the default) and STRUCTURE-CLASS (which creates structure classes, like DEFSTRUCT does).
Redefining classes is not supported. The function UPDATE-INSTANCE-FOR-REDEFINED-CLASS is not implemented.
Table of Contents
PROG1, PROG2, AND, OR, PSETQ, WHEN, UNLESS, COND, CASE, MULTIPLE-VALUE-LIST, MULTIPLE-VALUE-BIND, MULTIPLE-VALUE-SETQ are implemented as special operators and, as such, are rather efficient.
DESTRUCTURING-BIND does not perform full error checking.
EQ compares CHARACTERs and FIXNUMs as EQL does. No unnecessary copies are made of CHARACTERs and NUMBERs. Nevertheless, one should use EQL as it is more portable across Common Lisp implementations.
(let ((x y)) (eq x x)) always returns T, regardless of y.
(SETF (SYMBOL-FUNCTION symbol) object) requires object to be either a function, a SYMBOL-FUNCTION return value or a lambda expression. The lambda expression is thereby immediately converted to a function.
Additional places:
(SETF (FUNCALL #'symbol ...) object) and (SETF (FUNCALL 'symbol ...) object) are equivalent to (SETF (symbol ...) object).
(SETF (GET-DISPATCH-MACRO-CHARACTER ...) ...) calls SET-DISPATCH-MACRO-CHARACTER.
(SETF (ext:long-float-digits) digits) sets the default mantissa length of long floats to digits bits.
(SETF (VALUES-LIST list) form) is equivalent to (VALUES-LIST (SETF list (MULTIPLE-VALUE-LIST form)))
&KEY markers in DEFSETF lambda lists are supported, but the corresponding keywords must appear literally in the program text.
(GET-SETF-EXPANSION form &OPTIONAL env), (ext:get-setf-method form &OPTIONAL env), and (ext:get-setf-method-multiple-value form &OPTIONAL env) receive as optional argument the environment necessary for macro expansions. In DEFINE-SETF-EXPANDER and ext:define-setf-method lambda lists, one can specify &ENVIRONMENT and a variable, which will be bound to the environment. This environment should be passed to all calls of GET-SETF-EXPANSION, ext:get-setf-method and ext:get-setf-method-multiple-value. If this is done, even local macros will be interpreted as places correctly.
Attempts to modify read-only data will signal an error. Program text and quoted constants loaded from files are considered read-only data. This check is only performed for strings, not for conses, other kinds of arrays, and user-defined data types.
(FUNCTION symbol) returns the local function definition established by FLET or LABELS, if it exists, otherwise the global function definition.
(SPECIAL-OPERATOR-P symbol) returns NIL or T. If it returns T, then (SYMBOL-FUNCTION symbol) returns the (useless) special operator handler.
The macro DEFINE-SYMBOL-MACRO establishes SYMBOL-MACROs with global scope (as opposed to SYMBOL-MACROs defined with SYMBOL-MACROLET, which have local scope): (DEFINE-SYMBOL-MACRO symbol expansion).
The function ext:symbol-macro-expand tests for a SYMBOL-MACRO: If symbol is defined as a SYMBOL-MACRO, (ext:symbol-macro-expand symbol) returns two values, T and the expansion, otherwise it returns NIL.
Calling BOUNDP on a symbol defined as a SYMBOL-MACRO returns T.
Calling SYMBOL-VALUE on a symbol defined as a SYMBOL-MACRO returns the value of the expansion. Calling SET on a symbol defined as a SYMBOL-MACRO calls SETF on the expansion.
Calling MAKUNBOUND on a symbol defined as a SYMBOL-MACRO removes the SYMBOL-MACRO definition.
LAMBDA-LIST-KEYWORDS (&OPTIONAL &REST &KEY &ALLOW-OTHER-KEYS &AUX &BODY &WHOLE &ENVIRONMENT)
| CPU type | 16-bit CPU | 32-bit CPU | 64-bit CPU |
|---|---|---|---|
| CALL-ARGUMENTS-LIMIT | 216=65536 | 232=4294967296 | |
| MULTIPLE-VALUES-LIMIT | 27=128 | ||
| LAMBDA-PARAMETERS-LIMIT | 216=65536 | 232=4294967296 | |
DEFUN and DEFMACRO are allowed in non-toplevel positions. As an example, consider the old ([CLtL1]) definition of GENSYM:
(let ((gensym-prefix "G")
(gensym-count 1))
(defun gensym (&optional (x nil s))
(when s
(cond ((stringp x) (setq gensym-prefix x))
((integerp x)
(if (minusp x)
(error "~S: index ~S is negative" 'gensym x)
(setq gensym-count x)))
(t (error "~S: argument ~S of wrong type" 'gensym x))))
(prog1
(make-symbol
(concatenate 'string
gensym-prefix
(write-to-string gensym-count :base 10 :radix nil)))
(incf gensym-count))))