XLISP is an experimental programming language combining some of the features of Common Lisp with an object-oriented extension capability. It was implemented to allow experimentation with object-oriented programming on small computers. Implementations of XLISP run on virtually every operating system. XLISP is completely written in the programming language C and is easily extended with user written built-in functions and classes. It is available in source form to non-commercial users. Many Common Lisp functions are built into XLISP. In addition, XLISP defines the objects object and class as primitives. Object is the only class that has no superclass and hence is the root of the class hierarchy tree. Class is the class of which all classes are instances [it is the only object that is an instance of itself].
This document is a brief description of XLISP. It assumes some knowledge of LISP and some understanding of the concepts of object-oriented programming. I recommend the book 'Lisp' by Winston and Horn and published by Addison Wesley for learning Lisp. The first edition of this book is based on MacLisp and the second edition is based on Common Lisp. You will probably also need a copy of 'Common Lisp, The Language' by Guy L. Steele, Jr., published by Digital Press to use as a reference for some of the Common Lisp functions that are described only briefly in this document.
A list with Lisp books and documents available for free in the internet can be found under Lisp Links.
If you have any problems with XLISP, feel free to contact me [David Betz] for help or advice. Please remember that since XLISP is available in source form in a high level language, many users have been making versions available on a variety of machines. If you call to report a problem with a specific version, I may not be able to help you if that version runs on a machine to which I don't have access. Please have the version number of the version that you are running readily accessible before calling me.
If you find a bug in XLISP, first try to fix the bug yourself using the source code provided. If you are successful in fixing the bug, send the bug report along with the fix to me. If you don't have access to a C compiler or are unable to fix a bug, please send the bug report to me and I'll try to fix it.
Any suggestions for improvements will be welcomed. Feel free to extend the language in whatever way suits your needs. However,
PLEASE DO NOT RELEASE ENHANCED VERSIONS WITHOUT CHECKING WITH ME FIRST!!
I would like to be the clearing house for new features added to XLISP. If you want to add features for your own personal use, go ahead. But, if you want to distribute your enhanced version, contact me first. Please remember that the goal of XLISP is to provide a language to learn and experiment with LISP and object-oriented programming on small computers. I don't want it to get so big that it requires megabytes of memory to run.
The official XLISP homepage is:
When XLISP is started, it first tries to load the workspace 'xlisp.wks' from the current directory. If that file doesn't exist, XLISP builds an initial workspace, empty except for the built-in functions and symbols. Then XLISP attempts to load 'init.lsp' from the current directory. It then loads any files named as parameters on the command line [after appending '.lsp' to their names].
XLISP then issues the following prompt:
>
This indicates that XLISP is waiting for an expression to be typed. When a complete expression has been entered, XLISP attempts to evaluate that expression. If the expression evaluates successfully, XLISP prints the result and then returns to the initial prompt waiting for another expression to be typed.
Interactive Programming
There are several symbols maintained by the
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
the expression currently being evaluated, becomes the value of + at the end of the evaluation |
These symbols are for interactive programming.
Special Characters
When XLISP is running from a console
|
executes the top-level function | ||
|
executes the clean-up function | ||
|
executes the continue function | ||
|
stops execution and enters the break command loop,
execution can be continued by typing Control-p |
||
|
turns on character echoing [Linux and |
||
|
turns off character echoing [Linux and |
||
|
evaluates the info function | ||
|
erases the entire input line |
Backspace and Delete characters erase the previous character on the input
line
When XLISP encounters an error while evaluating an expression, it attempts to handle the error in the following way:
1. If the symbol
*breakenable* is true, the
message corresponding to the error is printed.
If the symbol
*tracenable* is true, a
trace back is printed. The number of entries printed depends on the value of
the symbol *tracelimit*.
XLISP then enters a '
1> (continue)
XLISP will continue from a correctable error.
1> (clean-up)
XLISP will abort the break loop and return to the top level or the next lower numbered break loop. When in a break loop, XLISP prefixes the break level to the normal prompt with a number.
2. If the symbol *breakenable* is NIL, XLISP looks for a surrounding errset function:
If an error happened within the scope of an
errset function, XLISP examines the
value of the errset print flag.
If there is no surrounding errset function, XLISP prints the error message and returns to the top level.
There are several different data types available to XLISP programmers:
See also the
The process of evaluation in XLISP:
The following Lisp objects evaluate to themselves:
Symbols act as variables and are evaluated by retrieving the value associated with their current binding.
Lists are evaluated by examining the first element of the list and then taking one of the following actions:
If it is a symbol, the functional binding of the symbol is retrieved.
If it is a lambda expression, a closure is constructed for the function described by the lambda expression.
If it is a subr [built-in function], fsubr [special form] or closure [user defined function], it stands for itself.
Any other value is an error.
Then, the value produced by the previous step is examined:
If it is a subr
If it is an fsubr [special form], the fsubr is called using the remaining list elements as arguments [unevaluated].
If it is a macro, the macro is expanded using the remaining list elements as arguments [unevaluated]. The macro expansion is then evaluated in place of the original macro call.
The following conventions must be followed when entering XLISP programs:
Comments in XLISP code begin with a semicolon character and continue to the end of the line.
Symbol names in XLISP can consist of any sequence of non-blank printable characters except the following:
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
Uppercase and lowercase characters are not distinguished within symbol names. All lowercase characters are mapped to uppercase on input.
Integer literals consist of a sequence of digits optionally beginning
with a '+' [plus] or '-' [minus]. The range of values an integer can
represent is limited by the size of a C 'long' value on the machine on which
XLISP is running.
Floating point literals consist of a sequence of digits optionally beginning with a '+' [plus] or '-' [minus] and including an embedded decimal point. The range of values a floating point number can represent is limited by the size of a C 'float' [or 'double' on machines with 32 bit addresses] on the machine on which XLISP is running.
Literal strings are sequences of characters surrounded by double quotes. Within quoted strings the '\' [backslash] character is used to allow non-printable characters to be included. The codes recognized are:
|
\\ |
the character '\' [backslash] | |
|
\n |
newline | |
|
\t |
tab | |
|
\r |
return | |
|
\f |
form feed | |
|
\nnn |
the character whose octal code is 'nnn' |
An ASCII table is provided with this version of the XLISP manual with all octal, decimal and hexadecimal character values.
The behavior of the reader is controlled by a data structure called a 'readtable'. The reader uses the symbol *readtable* to locate the current readtable. This table controls the interpretation of input characters. It is an array with 128 entries, one for each of the ASCII character codes. Each entry contains one of the following things:
|
NIL |
|||
|
:CONSTITUENT |
|||
|
:WHITE-SPACE |
|||
|
(:TMACRO . function) |
|||
|
(:NMACRO . function) |
|||
|
:SESCAPE |
|||
|
:MESCAPE |
In the case of :tmacro and :nmacro, the 'fun' component is a function. This can either be a built-in readmacro function or a lambda expression. The function should take two parameters. The first is the input stream and the second is the character that caused the invocation of the readmacro. The readmacro function should return NIL to indicate that the character should be treated as white space or a value consed with NIL to indicate that the readmacro should be treated as an occurence of the specified value. Of course, the readmacro code is free to read additional characters from the input stream.
XLISP defines several useful read macros:
|
'expression |
||
|
#'expression |
||
|
#(expression...) |
||
|
#xdigits |
||
|
#odigits |
||
|
#bdigits |
||
|
#\character |
||
|
#| ... |# |
||
|
#:symbol |
||
|
`expression |
||
|
,expression |
||
|
,@expression |
Characters names handled by the reader:
|
#\Tab |
|||
|
#\Newline |
|||
|
#\Space |
There are several forms in XLISP that require that a
The lambda list starts with 'required' arguments. Required arguments must be specified in every call to the function.
The function '
(defun print-x (x) (print x)) (print-x 1) => 1 (print-x) => error: too few arguments (print-x 1 2) => error: too many arguments
The
It is also possible to provide the name of a 'supplied-p' variable that can be used to determine if a call provided a value for the argument or if the initialization expression was used. If specified, the 'supplied-p' variable will be bound to T if a value was specified in the call and NIL if the default value was used.
The
Known Problems with the Rest Argument
A subtle problem arises if
(defun test (&optional opt &rest rest) (format t "opt = ~a, rest = ~a~%" opt rest)) (test 1) => opt = 1, rest = NIL (test 1 2) => opt = 1, rest = (2) (test 1 2 3) => opt = 1, rest = (2 3)
Now the
&optional
argument is not optional anymore, there is no way to make the first argument
appear in the &rest
list and not in the
&optional
variable. This is not a XLISP bug, this is a general Lisp phenomenon.
If a &rest
argument is used togethter with
XLISP Bug:
(defun test (&rest rest &key (key t)) (format t "rest = ~a, key = ~a~%" rest key)) (test 1 :key 'a) => rest = (1 :KEY A), key = T ; wrong KEY value (test 1 2 :key 'a) => rest = (1 2 :KEY A), key = A ; quirk, but correct KEY value (test 1 2 3 :key 'a)) => rest = (1 2 3 :KEY A), key = T ; again wrong KEY value
The
Like &optional arguments, &key arguments can have initialization expressions and 'supplied-p' variables. In addition, it is possible to specify the keyword to be used in a function call. If no keyword is specified, the keyword obtained by adding a colon ':' to the beginning of the keyword argument symbol is used.
In other words, if the keyword argument symbol is:
foo
the keyword will be:
:foo
The
Here is the complete syntax for lambda lists:
|
||
|
|
|
|
|
|
|
|
|
|
|
where:
|
is a required argument symbol | ||
|
is an &optional argument symbol | ||
|
is the &rest argument symbol | ||
|
is a &key argument symbol | ||
|
is a keyword symbol | ||
|
is an auxiliary variable symbol | ||
|
is an initialization expression | ||
|
is a supplied-p variable symbol |