0.8.14.28:

"not when there is nothing more to add, but when there is
	nothing more to be taken away"
	deleted old DocBook manual sources
	deleted references to DocBook manual sources (in DOCDOC and
		clean.sh and so forth)
	minor tidying of doc-building and doc/-cleaning machinery
		(hopefully leaving it working basically as before)
This commit is contained in:
William Harold Newman 2004-09-19 19:38:55 +00:00
parent 547cfec95e
commit d336ca31c5
18 changed files with 12 additions and 3277 deletions

View file

@ -1,9 +1,8 @@
#!/bin/sh
# Create a binary distribution. (make.sh should be run first to create
# the various binary files, and make-doc.sh, or possibly some other
# DocBook-to-HTML converter, should also be run to create the
# HTML version of the documentation.)
# the various binary files, and make-doc.sh should also be run to
# create the HTML version of the documentation.)
# (Before sbcl-0.6.10, this was run in the sbcl/ directory and created
# a tar file with no directory prefixes. Since sbcl-0.6.10, we've

View file

@ -13,16 +13,9 @@
# this script (including "gmake clean" in the src/runtime directory)
# several times in a row without failure.. so we leave the output/
# directory in place.)
rm -rf obj/* output/* src/runtime/genesis/ doc/user-manual \
doc/user-manual.junk doc/DBTOHTML_OUTPUT_DIR*
# (The doc/user-manual.junk and doc/DBTOHTML_OUTPUT_DIR* directories
# are created by the Cygnus db2html script when it formats the the
# user manual, and since this db2html script is the one which is
# currently used to format the manual for the standard binary
# distribution, we automatically clean up after it here in the
# standard clean.sh file.)
rm -rf obj/* output/* src/runtime/genesis/
# Ensure we know GNUMAKE
# Ensure that we know GNUMAKE.
. ./find-gnumake.sh
find_gnumake
@ -38,6 +31,7 @@ for d in tools-for-build; do
$GNUMAKE -I ../src/runtime -s clean
cd $original_pwd > /dev/null
done
( cd ./doc ; sh ./clean.sh )
# Within all directories, remove things which don't look like source
# files. Some explanations:
@ -50,8 +44,6 @@ done
# created by running GENESIS
# Config, target
# architecture-dependent or OS-dependent symlinks
# *.htm, *.html
# probably machine-generated translation of DocBook (*.sgml) files
# core
# probably a Unix core dump -- not part of the sources anyway
# *.o, *.so, *.lib, *.nm, a.out
@ -66,7 +58,8 @@ done
# .#*, *.orig, .*.orig, *.rej
# rubbish left behind by CVS updates
# *.htm, *.html
# The system doc sources are SGML, any HTML is
# The system doc sources are mostly texinfo, plus various odds
# and ends like docstrings embedded in .lisp sources; any HTML is
# automatically-generated output.
# depend
# made by "make depend" (or "gmake depend" or some such thing)
@ -110,5 +103,3 @@ find . \( \
-name 'tags' -o \
-name 'test-passed' -o \
-name 'local-target-features.lisp-expr' \) -print | xargs rm -f
cd ./doc && sh ./clean.sh

View file

@ -1,78 +0,0 @@
Metadocumentation: documentation for generating SBCL's Documentation
Overview
========
SBCL's documentation is written in XML DocBook which is a semantically
marked document not meant for humans to read directly. Rather, a
DocBook file is meant to be transformed into presentation formats such
as HTML, PDF, and plain text. To perform such translation, you'll need
tools beyond what is included in the SBCL distribution:
1) To verify the correctness of the XML documentation, you'll need the
DocBook DTD files and an XML verification tool.
2) To transform the main XML DocBook file (user-manual.xml), you need
an XSL Transformer and the Docbook XSL Stylesheets. The stylesheets
provide output in HTML, XHTML, and FO (formatted objects) formats.
3) If you want to create PDF or Postscript output, you'll need an FO
processor.
Catalog Files
=============
Catalog files are used to map URLs used in the SBCL Docbook and
stylesheet files into local file names. By using a catalog, processing
is faster and a network connection is not necessary. Catalog files are
specific to an operating system since they embed file locations. The
SBCL Makefile attempts to determine the correct catalog for your
system. If SBCL does not supply a catalog for your system, processing
the DocBook files will require a network connection.
Default Processing
==================
A shell script (make-doc.sh) is provided which creates the default
HTML documentation. This shell scripts invokes the GNU make tool to
create the HTML target. The Makefile assumes the existance of a
standard set of tools: the xsltproc XSL transformer and, ideally, the
DocBook XML DTDs and XSL stylesheets.
Tools for Debian
----------------
You will the below binary packages, and their dependencies, installed.
xsltproc (XSLT engine)
docbook-xml (XML DTDs)
docbook-xsl (stylesheets)
libxml2-utils (provides the xmllint verifier) [optional]
libfop-java (provides a FO processor for generating PDF output) [optiona]
The easiest way to do this is with the command:
apt-get install xsltproc docbook-xsl docbook-xml libxml2-utils libfop-java
Tools for SuSE
--------------
You will the below binary packages, and their dependencies, installed.
libxslt (xsltproc)
docbook_4 (XML DTDs)
docbook-xsl-stylesheets (stylesheets)
libxml2 (xmllint) [optional]
Tools for Fink
--------------
libxslt (xsltproc)
docbook-dtd (XML DTDs)
docbook-xsl (stylesheets)
libxml2-bin (xmllint) [optional]
The easiest way to do this is with the command:
fink install libxslt docbook-dtd docbook-xsl libxml2-bin
Tools Web Home
--------------
xsltproc http://xmlsoft.org/XSLT/
DocBook DTD http://www.docbook.org/xml/
DocBook XSL http://sourceforge.net/projects/docbook
xmllint http://xmlsoft.org/
FOP http://xml.apache.org/fop/

View file

@ -1,129 +0,0 @@
# Makefile for SBCL document generation
# This file is part of the SBCL system. It was copied from UFFI and
# placed into the public domain by the original author, Kevin
# Rosenberg.
DOCFILE_BASE_DEFAULT:=user-manual
DOCFILE_EXT_DEFAULT:=xml
SYSTEM:=$(shell uname)
ifeq ($(SYSTEM),Linux)
ifneq ($(shell expr "`cat /etc/issue`" : '.*Debian.*'),0)
# Old Debian used /usr/share/sgml/docbook, new Debian uses
# /usr/share/xml/docbook.
ifneq ($(shell expr "`ls -d /usr/share/xml`" : '.*/usr/share/xml.*'),0)
OS:=debian
else
# Evidently it's not a new-style Debian DocBook setup, ergo:
OS:=debian-old
endif
else
ifneq ($(shell expr "`cat /etc/issue`" : '.*SuSE.*'),0)
OS=suse
else
ifneq ($(shell expr "`cat /etc/issue`" : 'Red Hat Linux release 9'),0)
OS=redhat9
else
ifneq ($(shell expr "`cat /etc/issue`" : '.*Yarrow.*'),0)
OS=fedora1
endif
endif
endif
endif
endif
ifeq ($(SYSTEM),Darwin)
OS:=fink
endif
ifndef DOCFILE_BASE
DOCFILE_BASE=${DOCFILE_BASE_DEFAULT}
endif
ifndef DOCFILE_EXT
DOCFILE_EXT=${DOCFILE_EXT_DEFAULT}
endif
DOCFILE:=${DOCFILE_BASE}.${DOCFILE_EXT}
FOFILE:=${DOCFILE_BASE}.fo
PDFFILE:=${DOCFILE_BASE}.pdf
PSFILE:=${DOCFILE_BASE}.ps
DVIFILE:=${DOCFILE_BASE}.dvi
TXTFILE:=${DOCFILE_BASE}.txt
HTMLFILE:=${DOCFILE_BASE}.html
TMPFILES:=${DOCFILE_BASE}.aux ${DOCFILE_BASE}.out ${DOCFILE_BASE}.log
DOCFILES:=$(shell echo *.xml *.xsl)
ifeq ($(XSLTPROC),)
XSLTPROC:=xsltproc
endif
CATALOG:=`pwd`/catalogs/catalog-${OS}.xml
CHECK:=XML_CATALOG_FILES="$(CATALOG)" xmllint --noout --xinclude --postvalid $(DOCFILE) || exit 1
.PHONY: all
all: html
.PHONY: dist
dist: html pdf
.PHONY: doc
doc: html pdf
.PHONY: check
check:
@echo "Operating system detected: ${OS}"
@$(CHECK)
.PHONY: html
html: html-stamp
html-stamp: $(DOCFILES) Makefile
@rm -rf html
@mkdir html
@XML_CATALOG_FILES="$(CATALOG)" $(XSLTPROC) --stringparam chunker.output.encoding ISO-8859-1 \
--xinclude --output html/ html_chunk.xsl $(DOCFILE)
touch html-stamp
.PHONY: fo
fo: ${FOFILE}
${FOFILE}: $(DOCFILES) Makefile
@XML_CATALOG_FILES="$(CATALOG)" $(XSLTPROC) --xinclude --output $(FOFILE) fo.xsl $(DOCFILE)
.PHONY: pdf
pdf: ${PDFFILE}
${PDFFILE}: ${DOCFILES} Makefile
@$(MAKE) fo
@fop $(FOFILE) -pdf $(PDFFILE) > /dev/null
.PHONY: dvi
dvi: ${DVIFILE}
.PHONY: ps
ps: ${PSFILE}
${PSFILE}: ${DOCFILES} Makefile
@$(MAKE) fo
@fop $(FOFILE) -ps $(PSFILE) > /dev/null
.PHONY: txt
txt: ${TXTFILE}
${TXTFILE}: ${FOFILE}
@XML_CATALOG_FILES="$(CATALOG)" $(XSLTPROC) --xinclude --output ${HTMLFILE} html.xsl $(DOCFILE)
lynx -dump ${HTMLFILE} > ${TXTFILE}
.PHONY: clean
clean:
@rm -f *~ *.bak *.orig \#*\# .\#* texput.log
@rm -rf html $(PSFILE) $(HTMLFILE) $(PDFFILE) html-stamp
@rm -f $(TMPFILES) $(FOFILE)
@rm -f $(DVIFILE) $(TXTFILE)
.PHONY: distclean
distclean: clean

View file

@ -3,11 +3,9 @@ I say? Help with documentation might not be refused.:-)
There is a Unix man page, sbcl.1.
There is a user manual in DocBook format, in user-manual.sgml. (In
There is a user manual in texinfo format, in doc/manual/. (In
binary distributions, the compiled-into-HTML translations are also
included.) Several free software packages are available to compile
DocBook into HTML or other formats. The commands to use 'jade' to
translate the manual into HTML are in make-doc.sh.
included.)
Much of the documentation for supported extensions is in their Lisp
doc strings. For example, to find out how to use the SAVE-LISP-AND-DIE

View file

@ -1,391 +0,0 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1//EN"
"http://www.oasis-open.org/docbook/xml/4.1/docbookx.dtd" [
<!ENTITY % myents SYSTEM "entities.inc">
%myents;
]>
<chapter id="beyond-ansi"><title>Beyond The &ANSI; Standard</title>
<para>&SBCL; is mostly an implementation of the &ANSI; standard for
Common Lisp. However, there's some important behavior which extends
or clarifies the standard, and various behavior which outright
violates the standard.
</para>
<sect1 id="non-conformance"><title>Non-Conformance With The &ANSI; Standard</title>
<para>
Essentially every type of non-conformance is considered a bug.
(The exceptions involve internal inconsistencies in the standard.)
In &SBCL; 0.7.6, the master record of known bugs is in
the <filename>BUGS</filename> file in the distribution.
Some highlight information about bugs may also be found in the
manual page. The recommended way to report bugs is through the sbcl-help or
sbcl-devel mailings lists.
</para>
</sect1>
<sect1 id="idiosyncrasies"><title>Idiosyncrasies</title>
<para>The information in this section describes some of the ways
that &SBCL; deals with choices that the &ANSI; standard
leaves to the implementation.</para>
<para>Declarations are generally treated as assertions. This general
principle, and its implications, and the bugs which still keep the
compiler from quite satisfying this principle, are discussed in the
<link linkend="compiler">chapter on the compiler</link>.</para>
<para>&SBCL; is essentially a compiler-only implementation of
&CommonLisp;. That is, for all but a few special cases,
<function>eval</function> creates a
lambda expression, calls <function>compile</function> on the lambda
expression to create a compiled function, and then calls
<function>funcall</function> on the resulting function object. This
is explicitly allowed by the &ANSI; standard, but leads to some
oddities, e.g. collapsing <function>functionp</function> and
<function>compiled-function-p</function> into the same predicate.</para>
<para>&SBCL; is quite strict about ANSI's definition of
<function>defconstant</function>. ANSI says that doing <function>defconstant</function>
of the same symbol more than once is undefined unless the new value
is <function>eql</function> to the old value. Conforming to this specification
is a nuisance when the "constant" value is only constant under some
weaker test like <function>string=</function> or <function>equal</function>. It's
especially annoying because, in &SBCL;, <function>defconstant</function> takes effect
not only at load time but also at compile time, so that just
compiling and loading reasonable code like
<programlisting>(defconstant +foobyte+ '(1 4))</programlisting>
runs into this undefined behavior. Many
implementations of Common Lisp try to help the programmer around
this annoyance by silently accepting the undefined code and
trying to do what the programmer probably meant. &SBCL; instead
treats the undefined behavior as an error. Often
such code can be rewritten
in portable &ANSI; Common Lisp which has the desired behavior.
E.g., the code above can be given an exactly defined meaning by replacing
<function>defconstant</function> either with <function>defparameter</function> or
with a customized macro which does the right thing, possibly along the
lines of the <function>defconstant-eqx</function> macro used internally in the
implementation of &SBCL; itself. In circumstances where this is not
appropriate, the programmer can handle the condition type
<errortype>sb-ext:defconstant-uneql</errortype>, and choose either the
<action>continue</action> or <action>abort</action> restart as
appropriate.</para>
<para>&SBCL; gives style warnings about various kinds of perfectly
legal code, e.g.
<itemizedlist>
<listitem><para><function>defmethod</function> without
<function>defgeneric</function></para></listitem>
<listitem><para>multiple <function>defun</function>s of the same
symbol</para></listitem>
<listitem><para>special variables not named in the conventional
<varname>*foo*</varname> style, and lexical variables unconventionally named
in the <varname>*foo*</varname> style</para></listitem>
</itemizedlist>
This causes friction with people
who point out that other ways of organizing code (especially
avoiding the use of <function>defgeneric</function>)
are just as aesthetically stylish.
However, these warnings should be read not
as "warning, bad aesthetics detected, you have no style" but
"warning, this style keeps the compiler from understanding
the code as well as you might like." That is,
unless the compiler warns about such conditions, there's no
way for the compiler to warn
about some programming errors which would otherwise be
easy to overlook. (related bug: The warning about
multiple <function>defun</function>s is pointlessly annoying when you compile
and then load a function containing <function>defun</function> wrapped
in <function>eval-when</function>, and ideally should be suppressed in
that case, but still isn't as of &SBCL; 0.7.6.)</para>
</sect1>
<sect1 id="extensions"><title>Extensions</title>
<para>&SBCL; is derived from &CMUCL;, which implements many extensions
to the &ANSI; standard. &SBCL; doesn't support as many extensions as
&CMUCL;, but it still has quite a few.</para>
<sect2><title>Things Which Might Be In The Next &ANSI; Standard</title>
<para>&SBCL; provides extensive support for
calling external C code, described
<link linkend="ffi">in its own chapter</link>.</para>
<para>&SBCL; provides additional garbage collection functionality not
specified by &ANSI;. Weak pointers allow references to objects to be
maintained without keeping them from being GCed. And "finalization"
hooks are available to cause code to be executed when an object has been
GCed.</para> <!-- FIXME: Actually documenting these would be good.:-| -->
<para>&SBCL; supports Gray streams, user-overloadable CLOS classes
whose instances can be used as Lisp streams (e.g. passed as the
first argument to <function>format</function>). Additionally, the
bundled contrib module <interface>sb-simple-streams</interface>
implements a subset of the Franz Allegro simple-streams proposal.</para>
<para>&SBCL; supports a MetaObject Protocol which is intended to be
compatible with &AMOP;; present exceptions to this (as distinct from
current bugs) are:</para>
<itemizedlist>
<listitem><para>the abstract <classname>metaobject</classname> class is not
present in the class hierarchy;</para></listitem>
<listitem><para>the <classname>standard-object</classname> and
<classname>funcallable-standard-object</classname> classes are
disjoint;</para></listitem>
<listitem><para><function>compute-effective-method</function> only returns
one value, not two;</para></listitem>
<listitem><para>the system-supplied <property>:around</property> method for
<function>compute-slots</function> specialized on
<classname>funcallable-standard-class</classname> does not respect the
requested order from a user-supplied primary method.</para>
</listitem>
</itemizedlist>
</sect2>
<sect2><title>Threading (a.k.a Multiprocessing)</title>
<para>&SBCL; (as of version 0.8.3, on Linux x86 only) supports a
fairly low-level threading interface that maps onto the host operating
system's concept of threads or lightweight processes. </para>
<sect3><title>Lisp-level view</title>
<para>A rudimentary interface to creating and managing multiple threads
can be found in the <literal>sb-thread</literal> package. This is
intended for public consumption, so look at the exported symbols and
their documentation strings.
</para>
<para>Dynamic bindings to symbols are per-thread. Signal handlers
are per-thread.
</para>
<para>Mutexes and condition variables are available for
managing access to shared data: see
<itemizedlist>
<listitem>
<programlisting>(apropos "mutex" :sb-thread)</programlisting>
</listitem>
<listitem>
<programlisting>(apropos "condition" :sb-thread)</programlisting>
</listitem>
<listitem> <para>and the <structname>waitqueue</structname> structure
</para>
</listitem>
</itemizedlist>
and poke around in their documentation strings.</para>
<sect4><title>Sessions</title>
<para>If the user has multiple views onto the same Lisp image (for
example, using multiple terminals, or a windowing system, or network
access) they are typically set up as multiple `sessions' such that
each view has its own collection of foreground/background/stopped
threads. A thread which wishes to create a new session can use the
<function>sb-thread:with-new-session</function> to remove itself from
the current session (which it shares with its parent and siblings) and
create a fresh one. See also
<function>sb-thread:make-listener-thread</function>.</para>
<para>Within a single session, threads arbitrate between themselves
for the user's attention. A thread may be in one of three notional
states: foreground, background, or stopped. When a background process
attempts to print a repl prompt or to enter the debugger, it will stop
and print a message saying that it has stopped. The user at his
leisure may switch to that thread to find out what it needs. If a
background thread enters the debugger, selecting any restart will put
it back into the background before it resumes. Arbitration for the
input stream is managed by calls to
<function>sb-thread:get-foreground</function> (which may block) and
<function>sb-thread:release-foreground</function>.</para>
<para><function>sb-ext:quit</function> terminates all threads in the
current session, but leaves other sessions running</para>
</sect4>
</sect3>
<sect3><title>Implementation (Linux x86)</title>
<para>On Linux x86, this is implemented using
<function>clone()</function> and does not involve pthreads. This is
not because there is anything wrong with pthreads <emphasis>per
se</emphasis>, but there is plenty wrong (from our perspective) with
LinuxThreads. &SBCL; threads are mapped 1:1 onto Linux tasks which
share a VM but nothing else - each has its own process id and can be
seen in e.g. <command>ps</command> output.
</para>
<para>Per-thread local bindings for special variables is achieved
using the %fs segment register to point to a per-thread storage area.
This may cause interesting results if you link to foreign code that
expects threading or creates new threads, and the thread library in
question uses %fs in an incompatible way.
</para>
<para>There are two implementation mechanisms for queueing. If SBCL
was built on an NPTL-capable Linux system (2.6 or some vendor 2.4
ports) with the :SB-FUTEX feature, queuing will be done using the
<function>sys_futex()</function> system call if it's available at
runtime. Otherwise it will fall back to using
<function>sigtimedwait()</function> to sleep and a signal
(SIG_DEQUEUE, one of the POSIX RT signals) to wake.</para>
<para>Garbage collection is done with the existing Conservative
Generational GC. Allocation is done in small (typically 8k) regions :
each thread has its own region so this involves no stopping. However,
when a region fills, a lock must be obtained while another is
allocated, and when a collection is required, all processes are
stopped. This is achieved by sending them signals, which may make for
interesting behaviour if they are interrupted in system calls. The
streams interface is believed to handle the required system call
restarting correctly, but this may be a consideration when making
other blocking calls e.g. from foreign library code.
</para>
<para>Large amounts of the &SBCL; library have not been inspected for
thread-safety. Some of the obviously unsafe areas have large locks
around them, so compilation and fasl loading, for example, cannot be
parallelized. Work is ongoing in this area.
</para>
<para>A new thread by default is created in the same POSIX process
group and session as the thread it was created by. This has an impact
on keyboard interrupt handling: pressing your terminal's intr key
(typically Control-C) will interrupt all processes in the foreground
process group, including Lisp threads that &SBCL; considers to be
notionally `background'. This is undesirable, so background threads
are set to ignore the SIGINT signal.</para>
<para><function>sb-thread:make-listener-thread</function> in addition
to creating a new Lisp session makes a new POSIX session, so that
pressing Control-C in one window will not interrupt another listener -
this has been found to be embarrassing.
</para>
</sect3>
</sect2>
<sect2><title>Support For Unix</title>
<para>The UNIX command line can be read from the variable
<varname>sb-ext:*posix-argv*</varname>. The UNIX environment can be queried with the
<function>sb-ext:posix-getenv</function> function.</para>
<para>The &SBCL; system can be terminated with
<function>sb-ext:quit</function>, (but see notes above about threads
and sessions) optionally returning a specified numeric value to the
calling Unix process. The normal Unix idiom of terminating on end of
file on input is also supported.</para>
</sect2>
<sect2><title>Customization Hooks for Users</title>
<para>The behaviour of <function>require</function> when called with only
one argument is implementation-defined. In &SBCL; it calls functions
on the user-settable list <varname>sb-ext:*module-provider-functions*</varname>
- see the <function>require</function> documentation string for details.
</para>
<para>The toplevel repl prompt may be customized, and the function
that reads user input may be replaced completely. <!-- FIXME but I
don't currently remember how -->
</para>
</sect2>
<sect2><title>Tools To Help Developers</title>
<para>&SBCL; provides a profiler and other extensions to the &ANSI;
<function>trace</function> facility. See the online function documentation for
<function>trace</function> for more information.</para>
<para>The debugger supports a number of options. Its documentation is
accessed by typing <userinput>help</userinput> at the debugger prompt.</para>
<!-- FIXME:
A true debugger section in the manual would be good. Start
with CMU CL's debugger section, but remember:
* no QUIT command (TOPLEVEL restart instead)
* no GO command (CONTINUE restart instead)
* Limitations of the x86 port of the debugger should be
documented or fixed where possible.
* Discuss TRACE and its unification with PROFILE. -->
<para>Documentation for <function>inspect</function> is accessed by typing
<userinput>help</userinput> at the <function>inspect</function> prompt.</para>
</sect2>
<sect2><title>Interface To Low-Level &SBCL; Implementation</title>
<para>&SBCL; has the ability to save its state as a file for later
execution. This functionality is important for its bootstrapping
process, and is also provided as an extension to the user See the
documentation for <function>sb-ext:save-lisp-and-die</function> for more
information.</para>
<note><para>&SBCL; has inherited from &CMUCL; various hooks to allow
the user to tweak and monitor the garbage collection process. These
are somewhat stale code, and their interface might need to be cleaned
up. If you have urgent need of them, look at the code in
<filename>src/code/gc.lisp</filename> and bring it up on the
developers' mailing list.</para></note>
<note><para>&SBCL; has various hooks inherited from &CMUCL;, like
<function>sb-ext:float-denormalized-p</function>, to allow a program to take
advantage of &IEEE; floating point arithmetic properties which aren't
conveniently or efficiently expressible using the &ANSI; standard. These
look good, and their interface looks good, but &IEEE; support is
slightly broken due to a stupid decision to remove some support for
infinities (because it wasn't in the &ANSI; spec and it didn't occur to
me that it was in the &IEEE; spec). If you need this stuff, take a look
at the code and bring it up on the developers' mailing
list.</para></note>
</sect2>
<sect2><title>Efficiency Hacks</title>
<para>The <function>sb-ext:purify</function> function causes &SBCL;
first to collect all garbage, then to mark all uncollected objects as
permanent, never again attempting to collect them as garbage. This can
cause a large increase in efficiency when using a primitive garbage
collector, or a more moderate increase in efficiency when using a more
sophisticated garbage collector which is well suited to the program's
memory usage pattern. It also allows permanent code to be frozen at
fixed addresses, a precondition for using copy-on-write to share code
between multiple Lisp processes. is less important with modern
generational garbage collectors. </para>
<para>The <function>sb-ext:truly-the</function> declares the type of the
result of the operations, producing its argument; the declaration is
not checked. In short: don't use it.</para>
<para>The <function>sb-ext:freeze-type</function> declaration declares that a
type will never change, which can make type testing
(<function>typep</function>, etc.) more efficient for structure types.</para>
<para>The <function>sb-ext:constant-function</function> declaration specifies
that a function will always return the same value for the same
arguments, which may allow the compiler to optimize calls
to it. This is appropriate for functions like <function>sqrt</function>, but
is <emphasis>not</emphasis> appropriate for functions like <function>aref</function>,
which can change their return values when the underlying data are
changed.</para>
<!-- FIXME: This declaration does not seem to be supported in the
current compiler. -->
</sect2>
</sect1>
</chapter>

View file

@ -1,7 +1,3 @@
#!/bin/sh
. ../find-gnumake.sh
find_gnumake
$GNUMAKE clean
(cd manual; sh clean.sh)

View file

@ -1,942 +0,0 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1//EN"
"http://www.oasis-open.org/docbook/xml/4.1/docbookx.dtd" [
<!ENTITY % myents SYSTEM "entities.inc">
%myents;
]>
<chapter id="compiler"><title>The Compiler</title>
<para>This chapter will discuss most compiler issues other than
efficiency, including compiler error messages, the &SBCL; compiler's
unusual approach to type safety in the presence of type declarations,
the effects of various compiler optimization policies, and the way
that inlining and open coding may cause optimized code to differ from
a naive translation. Efficiency issues are sufficiently varied and
separate that they have <link linkend="efficiency">their own
chapter</link>.</para>
<sect1 id="error-messages"><title>Error Messages</title>
<!--INDEX {error messages}{compiler}-->
<!--INDEX {compiler error messages}-->
<para>The compiler supplies a large amount of source location
information in error messages. The error messages contain a lot of
detail in a terse format, so they may be confusing at first. Error
messages will be illustrated using this example program:
<programlisting>(defmacro zoq (x)
`(roq (ploq (+ ,x 3))))
(defun foo (y)
(declare (symbol y))
(zoq y))</programlisting>
The main problem with this program is that it is trying to add
<literal>3</literal> to a symbol. Note also that the functions
<function>roq</function> and <function>ploq</function> aren't defined anywhere.
</para>
<sect2><title>The Parts of the Error Message</title>
<para>When processing this program, the compiler will produce this
warning:
<screen>file: /tmp/foo.lisp
in: DEFUN FOO
(ZOQ Y)
--> ROQ PLOQ +
==>
Y
caught WARNING:
Result is a SYMBOL, not a NUMBER.</screen>
In this example we see each of the six possible parts of a compiler error
message:
<orderedlist>
<listitem><para><computeroutput>File: /tmp/foo.lisp</computeroutput>
This is the name of the file that the compiler read the relevant
code from. The file name is displayed because it may not be
immediately obvious when there is an error during compilation of a
large system, especially when
<function>with-compilation-unit</function> is used to delay
undefined warnings.</para></listitem>
<listitem><para><computeroutput>in: DEFUN FOO</computeroutput> This is the
definition top level form responsible for the error. It is
obtained by taking the first two elements of the enclosing form
whose first element is a symbol beginning with <quote><literal>def</literal></quote>.
If there is no such enclosing <quote><literal>def</literal></quote> form, then the
outermost form is used. If there are multiple <literal>def</literal>
forms, then they are all printed from the outside in, separated by
<literal>=></literal>'s. In this example, the problem was in the
<function>defun</function> for <function>foo</function>.</para></listitem>
<listitem><para><computeroutput>(ZOQ Y)</computeroutput> This is the
<emphasis>original source</emphasis> form responsible for the error.
Original source means that the form directly appeared in the
original input to the compiler, i.e. in the lambda passed to
<function>compile</function> or in the top level form read from the
source file. In this example, the expansion of the <function>zoq</function>
macro was responsible for the error.</para></listitem>
<listitem><para><computeroutput>--> ROQ PLOQ +</computeroutput> This is the
<emphasis>processing path</emphasis> that the compiler used to produce
the errorful code. The processing path is a representation of
the evaluated forms enclosing the actual source that the
compiler encountered when processing the original source.
The path is the first element of each form, or the form itself
if the form is not a list. These forms result from the
expansion of macros or source-to-source transformation done
by the compiler. In this example, the enclosing evaluated forms
are the calls to <function>roq</function>, <function>ploq</function> and
<function>+</function>. These calls resulted from the expansion of
the <function>zoq</function> macro.</para></listitem>
<listitem><para><computeroutput>==> Y</computeroutput> This is the
<emphasis>actual source</emphasis> responsible for the error. If
the actual source appears in the explanation, then
we print the next enclosing evaluated form, instead of
printing the actual source twice. (This is the form
that would otherwise have been the last form of the processing
path.) In this example, the problem is with the evaluation of
the reference to the variable <varname>y</varname>.</para></listitem>
<listitem><para>
<computeroutput>caught WARNING: Result is a SYMBOL, not a NUMBER.</computeroutput>
This is the <emphasis>explanation</emphasis> of the problem. In this
example, the problem is that <varname>y</varname> evaluates to a symbol,
but is in a context where a number is required (the argument
to <function>+</function>).</para></listitem>
</orderedlist>
Note that each part of the error message is distinctively marked:
<itemizedlist>
<listitem><para> <computeroutput>file:</computeroutput> and <computeroutput>in:</computeroutput>
mark the file and definition, respectively.</para></listitem>
<listitem><para> The original source is an indented form with no
prefix.</para></listitem>
<listitem><para> Each line of the processing path is prefixed with
<computeroutput>--></computeroutput></para></listitem>
<listitem><para> The actual source form is indented like the original
source, but is marked by a preceding <computeroutput>==></computeroutput> line.
</para></listitem>
<listitem><para> The explanation is prefixed with the error
severity, which can be <computeroutput>caught ERROR:</computeroutput>,
<computeroutput>caught WARNING:</computeroutput>,
<computeroutput>caught STYLE-WARNING:</computeroutput>, or
<computeroutput>note:</computeroutput>. </para></listitem>
</itemizedlist>
</para>
<para>Each part of the error message is more specific than the preceding
one. If consecutive error messages are for nearby locations, then the
front part of the error messages would be the same. In this case, the
compiler omits as much of the second message as in common with the
first. For example:
<screen>file: /tmp/foo.lisp
in: DEFUN FOO
(ZOQ Y)
--> ROQ
==>
(PLOQ (+ Y 3))
caught STYLE-WARNING:
undefined function: PLOQ
==>
(ROQ (PLOQ (+ Y 3)))
caught STYLE-WARNING:
undefined function: ROQ</screen>
In this example, the file, definition and original source are
identical for the two messages, so the compiler omits them in the
second message. If consecutive messages are entirely identical, then
the compiler prints only the first message, followed by:
<computeroutput>[Last message occurs <replaceable>repeats</replaceable> times]</computeroutput>
where <replaceable>repeats</replaceable> is the number of times the message
was given.</para>
<para>If the source was not from a file, then no file line is printed.
If the actual source is the same as the original source, then the
processing path and actual source will be omitted. If no forms
intervene between the original source and the actual source, then the
processing path will also be omitted.</para>
</sect2>
<sect2><title>The Original and Actual Source</title>
<para>The <emphasis>original source</emphasis> displayed will almost always be
a list. If the actual source for an error message is a symbol, the
original source will be the immediately enclosing evaluated list form.
So even if the offending symbol does appear in the original source,
the compiler will print the enclosing list and then print the symbol
as the actual source (as though the symbol were introduced by a
macro.)</para>
<para>When the <emphasis>actual source</emphasis> is displayed
(and is not a symbol), it will always
be code that resulted from the expansion of a macro or a source-to-source
compiler optimization. This is code that did not appear in the original
source program; it was introduced by the compiler.</para>
<para>Keep in mind that when the compiler displays a source form
in an error message, it always displays the most specific (innermost)
responsible form. For example, compiling this function
<programlisting>(defun bar (x)
(let (a)
(declare (fixnum a))
(setq a (foo x))
a))</programlisting>
gives this error message
<screen>in: DEFUN BAR
(LET (A) (DECLARE (FIXNUM A)) (SETQ A (FOO X)) A)
caught WARNING: The binding of A is not a FIXNUM:
NIL</screen>
This error message is not saying <quote>there is a problem somewhere in
this <function>let</function></quote> &mdash; it is saying that there is a
problem with the <function>let</function> itself. In this example, the problem
is that <varname>a</varname>'s <literal>nil</literal> initial value is not a
<type>fixnum</type>.</para>
</sect2>
<sect2><title>The Processing Path</title>
<!--INDEX processing path-->
<!--INDEX macroexpansion-->
<!--INDEX source-to-source transformation-->
<para>The processing path is mainly useful for debugging macros, so if
you don't write macros, you can probably ignore it. Consider this
example:
<programlisting>(defun foo (n)
(dotimes (i n *undefined*)))
</programlisting>
Compiling results in this error message:
<screen>in: DEFUN FOO
(DOTIMES (I N *UNDEFINED*))
--> DO BLOCK LET TAGBODY RETURN-FROM
==>
(PROGN *UNDEFINED*)
caught STYLE-WARNING:
undefined variable: *UNDEFINED*</screen>
Note that <function>do</function> appears in the processing path. This is because
<function>dotimes</function> expands into:
<programlisting>(do ((i 0 (1+ i)) (#:g1 n))
((>= i #:g1) *undefined*)
(declare (type unsigned-byte i)))</programlisting>
The rest of the processing path results from the expansion
of <function>do</function>:
<programlisting>
(block nil
(let ((i 0) (#:g1 n))
(declare (type unsigned-byte i))
(tagbody (go #:g3)
#:g2 (psetq i (1+ i))
#:g3 (unless (>= i #:g1) (go #:g2))
(return-from nil (progn *undefined*)))))
</programlisting>
In this example, the compiler descended into the <function>block</function>,
<function>let</function>, <function>tagbody</function> and <function>return-from</function> to
reach the <function>progn</function> printed as the actual source. This is a
place where the <quote>actual source appears in explanation</quote> rule
was applied. The innermost actual source form was the symbol
<varname>*undefined*</varname> itself, but that also appeared in the
explanation, so the compiler backed out one level.</para>
</sect2>
<sect2><title>Error Severity</title>
<!--INDEX severity of compiler errors -->
<!--INDEX compiler error severity -->
<para>There are four levels of compiler error severity:
<wordasword>error</wordasword>, <wordasword>warning</wordasword>, <wordasword>style
warning</wordasword>, and <wordasword>note</wordasword>. The first three levels correspond
to condition classes which are defined in the &ANSI; standard for
&CommonLisp; and which have special significance to the
<function>compile</function> and <function>compile-file</function> functions. These
levels of compiler error severity occur when the compiler handles
conditions of these classes. The fourth level of compiler error
severity, <wordasword>note</wordasword>, is used for problems which are too mild
for the standard condition classes, typically hints about how
efficiency might be improved.</para>
</sect2>
<sect2><title>Errors During Macroexpansion</title>
<!--INDEX {macroexpansion}{errors during}-->
<para>The compiler handles errors that happen during macroexpansion,
turning them into compiler errors. If you want to debug the error (to
debug a macro), you can set <varname>*break-on-signals*</varname> to
<literal>error</literal>. For example, this definition:
<programlisting>(defun foo (e l)
(do ((current l (cdr current))
((atom current) nil))
(when (eq (car current) e) (return current))))</programlisting>
gives this error:
<screen>in: DEFUN FOO
(DO ((CURRENT L #) (# NIL)) (WHEN (EQ # E) (RETURN CURRENT)) )
caught ERROR:
(in macroexpansion of (DO # #))
(hint: For more precise location, try *BREAK-ON-SIGNALS*.)
DO step variable is not a symbol: (ATOM CURRENT)</screen>
</para>
</sect2>
<sect2><title>Read Errors</title>
<!--INDEX {read errors}{compiler}-->
<para>&SBCL;'s compiler (unlike &CMUCL;'s) does not attempt to recover
from read errors when reading a source file, but instead just reports
the offending character position and gives up on the entire source
file.</para>
</sect2>
<!-- FIXME: How much control over error messages is in SBCL?
_ How much should be? How much of this documentation should
_ we save or adapt?
_
_ %%\node Error Message Parameterization, , Read Errors, Interpreting Error Messages
_ \subsection{Error Message Parameterization}
_ \cpsubindex{error messages}{verbosity}
_ \cpsubindex{verbosity}{of error messages}
_
_ There is some control over the verbosity of error messages. See also
_ \varref{undefined-warning-limit}, \code{*efficiency-note-limit*} and
_ \varref{efficiency-note-cost-threshold}.
_
_ \begin{defvar}{}{enclosing-source-cutoff}
_
_ This variable specifies the number of enclosing actual source forms
_ that are printed in full, rather than in the abbreviated processing
_ path format. Increasing the value from its default of \code{1}
_ allows you to see more of the guts of the macroexpanded source,
_ which is useful when debugging macros.
_ \end{defvar}
_
_ \begin{defvar}{}{error-print-length}
_ \defvarx{error-print-level}
_
_ These variables are the print level and print length used in
_ printing error messages. The default values are \code{5} and
_ \code{3}. If null, the global values of \code{*print-level*} and
_ \code{*print-length*} are used.
_ \end{defvar}
_
_ \begin{defmac}{extensions:}{define-source-context}{%
_ \args{\var{name} \var{lambda-list} \mstar{form}}}
_
_ This macro defines how to extract an abbreviated source context from
_ the \var{name}d form when it appears in the compiler input.
_ \var{lambda-list} is a \code{defmacro} style lambda-list used to
_ parse the arguments. The \var{body} should return a list of
_ subforms that can be printed on about one line. There are
_ predefined methods for \code{defstruct}, \code{defmethod}, etc. If
_ no method is defined, then the first two subforms are returned.
_ Note that this facility implicitly determines the string name
_ associated with anonymous functions.
_ \end{defmac}
_
_ -->
</sect1>
<sect1 id="compiler-types"><title>The Compiler's Handling of Types</title>
<para>The most unusual features of the &SBCL; compiler (which is
very similar to the original &CMUCL; compiler, also known as
&Python;) is its unusually sophisticated understanding of the
&CommonLisp; type system and its unusually conservative approach to
the implementation of type declarations. These two features reward the
use of type declarations throughout development, even when high
performance is not a concern. (Also, as discussed <link
linkend="efficiency">in the chapter on performance</link>, the use of
appropriate type declarations can be very important for performance as
well.)</para>
<para>The &SBCL; compiler, like the related compiler in &CMUCL;,
treats type declarations much differently than other Lisp compilers.
By default (<emphasis>i.e.</emphasis>, at ordinary levels of the
<parameter>safety</parameter> compiler optimization parameter), the compiler
doesn't blindly believe most type declarations; it considers them
assertions about the program that should be checked.</para>
<para>The &SBCL; compiler also has a greater knowledge of the
&CommonLisp; type system than other compilers. Support is incomplete
only for the <type>not</type>, <type>and</type> and <type>satisfies</type>
types.
<!-- FIXME: See also sections \ref{advanced-type-stuff}
and \ref{type-inference}, once we snarf them from the
CMU CL manual. -->
</para>
<sect2 id="compiler-impl-limitations"><title>Implementation Limitations</title>
<para>
Ideally, the compiler would consider <emphasis>all</emphasis> type declarations to
be assertions, so that adding type declarations to a program, no
matter how incorrect they might be, would <emphasis>never</emphasis> cause
undefined behavior. As of &SBCL; version 0.8.1, the compiler is known to
fall short of this goal in two areas:
<itemizedlist>
<listitem><para><function>Proclaim</function>ed constraints on argument and
result types of a function are supposed to be checked by the
function. If the function type is proclaimed before function
definition, type checks are inserted by the compiler, but the
standard allows the reversed order, in which case the compiler
will trust the declaration.</para></listitem>
<listitem><para>The compiler cannot check types of an unknown number
of values; if the number of generated values is unknown, but the
number of consumed is known, only consumed values are
checked.</para></listitem>
<listitem><para>There are a few poorly characterized but apparently
very uncommon situations where a type declaration in an unexpected
location will be trusted and never checked by the
compiler.</para></listitem>
</itemizedlist></para>
<para>These are important bugs, but are not necessarily easy to fix,
so they may, alas, remain in the system for a while.</para>
</sect2>
<sect2><title>Type Errors at Compile Time</title>
<!--INDEX compile time type errors-->
<!--INDEX type checking}{at compile time}-->
<para>If the compiler can prove at compile time that some portion of
the program cannot be executed without a type error, then it will give
a warning at compile time. It is possible that the offending code
would never actually be executed at run-time due to some higher level
consistency constraint unknown to the compiler, so a type warning
doesn't always indicate an incorrect program. For example, consider
this code fragment:
<programlisting>(defun raz (foo)
(let ((x (case foo
(:this 13)
(:that 9)
(:the-other 42))))
(declare (fixnum x))
(foo x)))
</programlisting>
Compilation produces this warning:
<screen>in: DEFUN RAZ
(CASE FOO (:THIS 13) (:THAT 9) (:THE-OTHER 42))
--> LET COND IF COND IF COND IF
==>
(COND)
caught WARNING: This is not a FIXNUM:
NIL</screen>
In this case, the warning means that if <varname>foo</varname> isn't any of
<literal>:this</literal>, <literal>:that</literal> or <literal>:the-other</literal>, then
<varname>x</varname> will be initialized to <literal>nil</literal>, which the
<type>fixnum</type> declaration makes illegal. The warning will go away if
<function>ecase</function> is used instead of <function>case</function>, or if
<literal>:the-other</literal> is changed to <literal>t</literal>.</para>
<para>This sort of spurious type warning happens moderately often in
the expansion of complex macros and in inline functions. In such
cases, there may be dead code that is impossible to correctly execute.
The compiler can't always prove this code is dead (could never be
executed), so it compiles the erroneous code (which will always signal
an error if it is executed) and gives a warning.</para>
<para>
Type warnings are inhibited when the
<parameter>sb-ext:inhibit-warnings</parameter> optimization quality is
<literal>3</literal>. (See <link linkend="compiler-policy">the section
on compiler policy</link>.) This can be used in a local declaration
to inhibit type warnings in a code fragment that has spurious
warnings.</para>
</sect2>
<sect2 id="precisetypechecking"><title>Precise Type Checking</title>
<!--INDEX precise type checking-->
<!--INDEX {type checking}{precise}-->
<para>With the default compilation policy, all type declarations are
precisely checked, except in a few situations where they are simply
ignored instead. Precise checking means that the check is done as
though <function>typep</function> had been called with the exact type
specifier that appeared in the declaration. In &SBCL;, adding type
declarations makes code safer. (Except that as noted <link
linkend="compiler-impl-limitations">elsewhere</link>, remaining bugs
in the compiler's handling of types unfortunately provide some
exceptions to this rule.)</para>
<para>If a variable is declared to be
<type>(integer 3 17)</type> then its value must always be an integer
between <literal>3</literal> and <literal>17</literal>. If multiple type
declarations apply to a single variable, then all the declarations
must be correct; it is as though all the types were intersected
producing a single <type>and</type> type specifier.</para>
<para>Argument and result type declarations are automatically
enforced. If you declare the type of a function argument, a type check
will be done when that function is called. In a function call, the
called function does the argument type checking.</para>
<para>The types of structure slots are also checked. The value of a
structure slot must always be of the type indicated in any
<literal>:type</literal> slot option. </para>
<para>In traditional &CommonLisp; compilers, not all type assertions
are checked, and type checks are not precise. Traditional compilers
blindly trust explicit type declarations, but may check the argument
type assertions for built-in functions. Type checking is not precise,
since the argument type checks will be for the most general type legal
for that argument. In many systems, type declarations suppress what
little type checking is being done, so adding type declarations makes
code unsafe. This is a problem since it discourages writing type
declarations during initial coding. In addition to being more error
prone, adding type declarations during tuning also loses all the
benefits of debugging with checked type assertions.</para>
<para>To gain maximum benefit from the compiler's type checking, you
should always declare the types of function arguments and structure
slots as precisely as possible. This often involves the use of
<type>or</type>, <type>member</type>, and other list-style type specifiers.</para>
</sect2>
<sect2 id="weakened-type-checking"><title>Weakened Type Checking</title>
<!--INDEX weakened type checking-->
<!--INDEX {type checking}{weakened}-->
<para>At one time, &CMUCL; supported another level of type checking,
<quote>weakened type checking</quote>, when the value for the
<parameter>speed</parameter> optimization quality is greater than
<parameter>safety</parameter>, and <parameter>safety</parameter> is not <literal>0</literal>.
The &CMUCL; manual still has a description of it, but even the CMU CL
code no longer corresponds to the manual. Some of this partial safety
checking lingers on in SBCL, but it's not a supported feature, and
should not be relied on. If you ask the compiler to optimize
<parameter>speed</parameter> to a higher level than <parameter>safety</parameter>,
your program is performing without a safety net, because &SBCL; may
at its option believe any or all type declarations with either partial
or nonexistent runtime checking.</para>
</sect2>
<sect2><title>Getting Existing Programs to Run</title>
<!--INDEX {existing programs}{to run}-->
<!--INDEX {types}{portability}-->
<!--INDEX {compatibility with other Lisps}
(should also have an entry in the non-&ANSI;-isms section)-->
<para>Since &SBCL;'s compiler, like &CMUCL;'s compiler, does much more
comprehensive type checking than most Lisp compilers, &SBCL; may
detect type errors in programs that have been debugged using other
compilers. These errors are mostly incorrect declarations, although
compile-time type errors can find actual bugs if parts of the program
have never been tested.</para>
<para>Some incorrect declarations can only be detected by run-time
type checking. It is very important to initially compile a program
with full type checks (high <parameter>safety</parameter> optimization) and
then test this safe version. After the checking version has been
tested, then you can consider weakening or eliminating type checks.
<emphasis>This applies even to previously debugged
programs,</emphasis> because the &SBCL; compiler does much more type
inference than other &CommonLisp; compilers, so an incorrect
declaration can do more damage.</para>
<para>The most common problem is with variables whose constant initial
value doesn't match the type declaration. Incorrect constant initial
values will always be flagged by a compile-time type error, and they
are simple to fix once located. Consider this code fragment:
<programlisting>(prog (foo)
(declare (fixnum foo))
(setq foo ...)
...)</programlisting>
Here <varname>foo</varname> is given an initial value of <literal>nil</literal>, but
is declared to be a <type>fixnum</type>. Even if it is never read, the
initial value of a variable must match the declared type. There are
two ways to fix this problem. Change the declaration
<programlisting>(prog (foo)
(declare (type (or fixnum null) foo))
(setq foo ...)
...)</programlisting>
or change the initial value
<programlisting>(prog ((foo 0))
(declare (fixnum foo))
(setq foo ...)
...)</programlisting>
It is generally preferable to change to a legal initial value rather
than to weaken the declaration, but sometimes it is simpler to weaken
the declaration than to try to make an initial value of the
appropriate type.</para>
<para>Another declaration problem occasionally encountered is
incorrect declarations on <function>defmacro</function> arguments. This can happen
when a function is converted into a macro. Consider this macro:
<programlisting>(defmacro my-1+ (x)
(declare (fixnum x))
`(the fixnum (1+ ,x)))</programlisting>
Although legal and well-defined &CommonLisp; code, this meaning of
this definition is almost certainly not what the writer intended. For
example, this call is illegal:
<programlisting>(my-1+ (+ 4 5))</programlisting>
This call is illegal because the argument to the macro is
<literal>(+ 4 5)</literal>, which is a <type>list</type>, not a
<type>fixnum</type>. Because of
macro semantics, it is hardly ever useful to declare the types of
macro arguments. If you really want to assert something about the
type of the result of evaluating a macro argument, then put a
<function>the</function> in the expansion:
<programlisting>(defmacro my-1+ (x)
`(the fixnum (1+ (the fixnum ,x))))</programlisting>
In this case, it would be stylistically preferable to change this
macro back to a function and declare it inline.
<!--FIXME: <xref>inline-expansion, once we crib the
relevant text from the CMU CL manual.-->
</para>
<para>
Some more subtle problems are caused by incorrect declarations that
can't be detected at compile time. Consider this code:
<programlisting>(do ((pos 0 (position #\a string :start (1+ pos))))
((null pos))
(declare (fixnum pos))
...)</programlisting>
Although <varname>pos</varname> is almost always a <varname>fixnum</varname>, it is
<literal>nil</literal> at the end of the loop. If this example is compiled
with full type checks (the default), then running it will signal a
type error at the end of the loop. If compiled without type checks,
the program will go into an infinite loop (or perhaps
<function>position</function> will complain because <literal>(1+ nil)</literal> isn't
a sensible start.) Why? Because if you compile without type checks,
the compiler just quietly believes the type declaration. Since the
compiler believes that <varname>pos</varname> is always a <type>fixnum</type>, it
believes that <varname>pos</varname> is never <literal>nil</literal>, so
<literal>(null pos)</literal> is never true, and the loop exit test is
optimized away. Such errors are sometimes flagged by unreachable code
notes, but it is still important to initially compile and test any
system with full type checks, even if the system works fine when
compiled using other compilers.</para>
<para>In this case, the fix is to weaken the type declaration to
<type>(or fixnum null)</type>.
<footnote><para>Actually, this declaration is
unnecessary in &SBCL;, since it already knows that <function>position</function>
returns a non-negative <type>fixnum</type> or <literal>nil</literal>.
</para></footnote>
Note that there is usually little performance penalty for weakening a
declaration in this way. Any numeric operations in the body can still
assume that the variable is a <type>fixnum</type>, since <literal>nil</literal>
is not a legal numeric argument. Another possible fix would be to say:
<programlisting>(do ((pos 0 (position #\a string :start (1+ pos))))
((null pos))
(let ((pos pos))
(declare (fixnum pos))
...))</programlisting>
This would be preferable in some circumstances, since it would allow a
non-standard representation to be used for the local <varname>pos</varname>
variable in the loop body.
<!-- FIXME: <xref>ND-variables, once we crib the text from the
CMU CL manual. -->
</para>
</sect2>
</sect1>
<sect1 id="compiler-policy"><title>Compiler Policy</title>
<para>As of version 0.6.4, &SBCL; still uses most of the &CMUCL; code
for compiler policy. The &CMUCL; code has many features and high-quality
documentation, but the two unfortunately do not match. So this area of
the compiler and its interface needs to be cleaned up. Meanwhile, here
is some rudimentary documentation on the current behavior of the
system.</para>
<para>Compiler policy is controlled by the <parameter>optimize</parameter>
declaration. The compiler supports the &ANSI; optimization qualities,
and also an extension <parameter>sb-ext:inhibit-warnings</parameter>.</para>
<para>Ordinarily, when the <parameter>speed</parameter> quality is high, the
compiler emits notes to notify the programmer about its inability to
apply various optimizations. Setting
<parameter>sb-ext:inhibit-warnings</parameter> to a value at least as large as
the <parameter>speed</parameter> quality inhibits this notification. This can
be useful to suppress notes about code which is known to be
unavoidably inefficient. (For example, the compiler issues notes about
having to use generic arithmetic instead of fixnum arithmetic, which
is not helpful for code which by design supports arbitrary-sized
integers instead of being limited to fixnums.)</para>
<note><para>The basic functionality of the <parameter>optimize
inhibit-warnings</parameter> extension will probably be supported in all future
versions of the system, but it will probably be renamed when the
compiler and its interface are cleaned up. The current name is
misleading, because it mostly inhibits optimization notes, not
warnings. And making it an optimization quality is misleading, because
it shouldn't affect the resulting code at all. It may become a
declaration identifier with a name like
<parameter>sb-ext:inhibit-notes</parameter>, so that what's currently written
<programlisting>(declaim (optimize (sb-ext:inhibit-warnings 2)))</programlisting>
would become something like
<programlisting>(declaim (sb-ext:inhibit-notes 2))</programlisting>
</para></note>
<para> (In early versions of SBCL, a <parameter>speed</parameter> value of zero
was used to enable byte compilation, but since version 0.7.0, SBCL
only supports native compilation.)</para>
<para>When <parameter>safety</parameter> is zero, almost all runtime checking
of types, array bounds, and so forth is suppressed.</para>
<para>When <parameter>safety</parameter> is less than <parameter>speed</parameter>, any
and all type checks may be suppressed. At some point in the past,
&CMUCL; had <link linkend="weakened-type-checking">a more nuanced
interpretation of this</link>. However, &SBCL; doesn't support that
interpretation, and setting <parameter>safety</parameter> less than
<parameter>speed</parameter> may have roughly the same effect as setting
<parameter>safety</parameter> to zero.</para>
<para>The value of <parameter>space</parameter> mostly influences the
compiler's decision whether to inline operations, which tend to
increase the size of programs. Use the value <literal>0</literal> with
caution, since it can cause the compiler to inline operations so
indiscriminately that the net effect is to slow the program by causing
cache misses or swapping.</para>
<!-- FIXME: old CMU CL compiler policy, should perhaps be adapted
_ for SBCL. (Unfortunately, the CMU CL docs are out of sync with the
_ CMU CL code, so adapting this requires not only reformatting
_ the documentation, but rooting out code rot.)
_
_<sect2 id="compiler-policy"><title>Compiler Policy</1000
_ INDEX {policy}{compiler}
_ INDEX compiler policy
_
_<para>The policy is what tells the compiler <emphasis>how</emphasis> to
_compile a program. This is logically (and often textually) distinct
_from the program itself. Broad control of policy is provided by the
_<parameter>optimize</parameter> declaration; other declarations and variables
_control more specific aspects of compilation.</para>
_
_\begin{comment}
_* The Optimize Declaration::
_* The Optimize-Interface Declaration::
_\end{comment}
_
_%%\node The Optimize Declaration, The Optimize-Interface Declaration, Compiler Policy, Compiler Policy
_\subsection{The Optimize Declaration}
_\label{optimize-declaration}
_\cindex{optimize declaration}
_\cpsubindex{declarations}{\code{optimize}}
_
_The \code{optimize} declaration recognizes six different
_\var{qualities}. The qualities are conceptually independent aspects
_of program performance. In reality, increasing one quality tends to
_have adverse effects on other qualities. The compiler compares the
_relative values of qualities when it needs to make a trade-off; i.e.,
_if \code{speed} is greater than \code{safety}, then improve speed at
_the cost of safety.
_
_The default for all qualities (except \code{debug}) is \code{1}.
_Whenever qualities are equal, ties are broken according to a broad
_idea of what a good default environment is supposed to be. Generally
_this downplays \code{speed}, \code{compile-speed} and \code{space} in
_favor of \code{safety} and \code{debug}. Novice and casual users
_should stick to the default policy. Advanced users often want to
_improve speed and memory usage at the cost of safety and
_debuggability.
_
_If the value for a quality is \code{0} or \code{3}, then it may have a
_special interpretation. A value of \code{0} means ``totally
_unimportant'', and a \code{3} means ``ultimately important.'' These
_extreme optimization values enable ``heroic'' compilation strategies
_that are not always desirable and sometimes self-defeating.
_Specifying more than one quality as \code{3} is not desirable, since
_it doesn't tell the compiler which quality is most important.
_
_
_These are the optimization qualities:
_\begin{Lentry}
_
_\item[\code{speed}] \cindex{speed optimization quality}How fast the
_ program should is run. \code{speed 3} enables some optimizations
_ that hurt debuggability.
_
_\item[\code{compilation-speed}] \cindex{compilation-speed optimization
_ quality}How fast the compiler should run. Note that increasing
_ this above \code{safety} weakens type checking.
_
_\item[\code{space}] \cindex{space optimization quality}How much space
_ the compiled code should take up. Inline expansion is mostly
_ inhibited when \code{space} is greater than \code{speed}. A value
_ of \code{0} enables indiscriminate inline expansion. Wide use of a
_ \code{0} value is not recommended, as it may waste so much space
_ that run time is slowed. \xlref{inline-expansion} for a discussion
_ of inline expansion.
_
_\item[\code{debug}] \cindex{debug optimization quality}How debuggable
_ the program should be. The quality is treated differently from the
_ other qualities: each value indicates a particular level of debugger
_ information; it is not compared with the other qualities.
_ \xlref{debugger-policy} for more details.
_
_\item[\code{safety}] \cindex{safety optimization quality}How much
_ error checking should be done. If \code{speed}, \code{space} or
_ \code{compilation-speed} is more important than \code{safety}, then
_ type checking is weakened (\pxlref{weakened-type-checks}). If
_ \code{safety} if \code{0}, then no run time error checking is done.
_ In addition to suppressing type checks, \code{0} also suppresses
_ argument count checking, unbound-symbol checking and array bounds
_ checks.
_
_\item[\code{extensions:inhibit-warnings}] \cindex{inhibit-warnings
_ optimization quality}This is a CMU extension that determines how
_ little (or how much) diagnostic output should be printed during
_ compilation. This quality is compared to other qualities to
_ determine whether to print style notes and warnings concerning those
_ qualities. If \code{speed} is greater than \code{inhibit-warnings},
_ then notes about how to improve speed will be printed, etc. The
_ default value is \code{1}, so raising the value for any standard
_ quality above its default enables notes for that quality. If
_ \code{inhibit-warnings} is \code{3}, then all notes and most
_ non-serious warnings are inhibited. This is useful with
_ \code{declare} to suppress warnings about unavoidable problems.
_\end{Lentry}
_
_%%\node The Optimize-Interface Declaration, , The Optimize Declaration, Compiler Policy
_\subsection{The Optimize-Interface Declaration}
_\label{optimize-interface-declaration}
_\cindex{optimize-interface declaration}
_\cpsubindex{declarations}{\code{optimize-interface}}
_
_The \code{extensions:optimize-interface} declaration is identical in
_syntax to the \code{optimize} declaration, but it specifies the policy
_used during compilation of code the compiler automatically generates
_to check the number and type of arguments supplied to a function. It
_is useful to specify this policy separately, since even thoroughly
_debugged functions are vulnerable to being passed the wrong arguments.
_The \code{optimize-interface} declaration can specify that arguments
_should be checked even when the general \code{optimize} policy is
_unsafe.
_
_Note that this argument checking is the checking of user-supplied
_arguments to any functions defined within the scope of the
_declaration, \code{not} the checking of arguments to \llisp{}
_primitives that appear in those definitions.
_
_The idea behind this declaration is that it allows the definition of
_functions that appear fully safe to other callers, but that do no
_internal error checking. Of course, it is possible that arguments may
_be invalid in ways other than having incorrect type. Functions
_compiled unsafely must still protect themselves against things like
_user-supplied array indices that are out of bounds and improper lists.
_See also the \kwd{context-declarations} option to
_\macref{with-compilation-unit}.
_
_(end of section on compiler policy)
_-->
</sect1>
<sect1 id="open-coding"><title>Open Coding and Inline Expansion</title>
<!--INDEX open-coding-->
<!--INDEX inline expansion-->
<!--INDEX static functions-->
<para>Since &CommonLisp; forbids the redefinition of standard
functions, the compiler can have special knowledge of these standard
functions embedded in it. This special knowledge is used in various
ways (open coding, inline expansion, source transformation), but the
implications to the user are basically the same:
<itemizedlist>
<listitem><para> Attempts to redefine standard functions may
be frustrated, since the function may never be called. Although
it is technically illegal to redefine standard functions, users
sometimes want to implicitly redefine these functions when they
are debugging using the <function>trace</function> macro. Special-casing
of standard functions can be inhibited using the
<parameter>notinline</parameter> declaration.</para></listitem>
<listitem><para> The compiler can have multiple alternate
implementations of standard functions that implement different
trade-offs of speed, space and safety. This selection is
based on the <link linkend="compiler-policy">compiler policy</link>.
</para></listitem>
</itemizedlist>
</para>
<para>When a function call is <emphasis>open coded</emphasis>, inline code whose
effect is equivalent to the function call is substituted for that
function call. When a function call is <emphasis>closed coded</emphasis>, it
is usually left as is, although it might be turned into a call to a
different function with different arguments. As an example, if
<function>nthcdr</function> were to be open coded, then
<programlisting>(nthcdr 4 foobar)</programlisting>
might turn into
<programlisting>(cdr (cdr (cdr (cdr foobar))))</programlisting>
or even
<programlisting>(do ((i 0 (1+ i))
(list foobar (cdr foobar)))
((= i 4) list))</programlisting>
If <function>nth</function> is closed coded, then
<programlisting>
(nth x l)
</programlisting>
might stay the same, or turn into something like
<programlisting>
(car (nthcdr x l))
</programlisting>
</para>
<para>In general, open coding sacrifices space for speed, but some
functions (such as <function>car</function>) are so simple that they are always
open-coded. Even when not open-coded, a call to a standard function
may be transformed into a different function call (as in the last
example) or compiled as <emphasis>static call</emphasis>. Static function call
uses a more efficient calling convention that forbids
redefinition.</para>
</sect1>
</chapter>

View file

@ -1,139 +0,0 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1//EN"
"http://www.oasis-open.org/docbook/xml/4.1/docbookx.dtd" [
<!ENTITY % myents SYSTEM "entities.inc">
%myents;
]>
<chapter id="efficiency"><title>Efficiency</title>
<para>FIXME: The material in the &CMUCL; manual about getting good
performance from the compiler should be reviewed, reformatted in
DocBook, lightly edited for &SBCL;, and substituted into this
manual. In the meantime, the original &CMUCL; manual is still 95+%
correct for the &SBCL; version of the &Python; compiler. See the
sections
<itemizedlist>
<listitem><para>Advanced Compiler Use and Efficiency Hints</para></listitem>
<listitem><para>Advanced Compiler Introduction</para></listitem>
<listitem><para>More About Types in Python</para></listitem>
<listitem><para>Type Inference</para></listitem>
<listitem><para>Source Optimization</para></listitem>
<listitem><para>Tail Recursion</para></listitem>
<listitem><para>Local Call</para></listitem>
<listitem><para>Block Compilation</para></listitem>
<listitem><para>Inline Expansion</para></listitem>
<listitem><para>Object Representation</para></listitem>
<listitem><para>Numbers</para></listitem>
<listitem><para>General Efficiency Hints</para></listitem>
<listitem><para>Efficiency Notes</para></listitem>
</itemizedlist>
</para>
<para>Besides this information from the &CMUCL; manual, there are a
few other points to keep in mind.
<itemizedlist>
<listitem><para>The &CMUCL; manual doesn't seem to state it explicitly,
but &Python; has a mental block about type inference when
assignment is involved. &Python; is very aggressive and clever
about inferring the types of values bound with <function>let</function>,
<function>let*</function>, inline function call, and so forth. However,
it's much more passive and dumb about inferring the types of
values assigned with <function>setq</function>, <function>setf</function>, and
friends. It would be nice to fix this, but in the meantime don't
expect that just because it's very smart about types in most
respects it will be smart about types involved in assignments.
(This doesn't affect its ability to benefit from explicit type
declarations involving the assigned variables, only its ability to
get by without explicit type declarations.)</para></listitem>
<!-- FIXME: Python dislikes assignments, but not in type
inference. The real problems are loop induction, closed over
variables and aliases. -->
<listitem><para>Since the time the &CMUCL; manual was written,
&CMUCL; (and thus &SBCL;) has gotten a generational garbage
collector. This means that there are some efficiency implications
of various patterns of memory usage which aren't discussed in the
&CMUCL; manual. (Some new material should be written about
this.)</para></listitem>
<listitem><para>&SBCL; has some important known efficiency problems.
Perhaps the most important are
<itemizedlist>
<listitem><para>There is no support for the &ANSI;
<parameter>dynamic-extent</parameter> declaration, not even for
closures or <parameter>&amp;rest</parameter> lists.</para></listitem>
<listitem><para>The garbage collector is not particularly
efficient.</para></listitem>
<listitem><para>Various aspects of the PCL implementation
of CLOS are more inefficient than necessary.</para></listitem>
</itemizedlist>
</para></listitem>
</itemizedlist>
</para>
<para>Finally, note that &CommonLisp; defines many constructs which, in
the infamous phrase, <quote>could be compiled efficiently by a
sufficiently smart compiler</quote>. The phrase is infamous because
making a compiler which actually is sufficiently smart to find all
these optimizations systematically is well beyond the state of the art
of current compiler technology. Instead, they're optimized on a
case-by-case basis by hand-written code, or not optimized at all if
the appropriate case hasn't been hand-coded. Some cases where no such
hand-coding has been done as of &SBCL; version 0.6.3 include
<itemizedlist>
<listitem><para><literal>(reduce #'f x)</literal>
where the type of <varname>x</varname> is known at compile
time</para></listitem>
<listitem><para>various bit vector operations, e.g.
<literal>(position 0 some-bit-vector)</literal></para></listitem>
</itemizedlist>
If your system's performance is suffering because of some construct
which could in principle be compiled efficiently, but which the &SBCL;
compiler can't in practice compile efficiently, consider writing a
patch to the compiler and submitting it for inclusion in the main
sources. Such code is often reasonably straightforward to write;
search the sources for the string <quote><function>deftransform</function></quote>
to find many examples (some straightforward, some less so).</para>
<sect1 id="modular-arithmetic"><title>Modular arithmetic</title>
<para>
Some numeric functions have a property: <varname>N</varname> lower bits of
the result depend only on <varname>N</varname> lower bits of (all or some)
arguments. If the compiler sees an expression of form <literal>(logand
exp mask)</literal>, where <varname>exp</varname> is a tree of such "good" functions
and <varname>mask</varname> is known to be of type <type>(unsigned-byte
w)</type>, where <varname>w</varname> is a "good" width, all intermediate results
will be cut to <varname>w</varname> bits (but it is not done for variables
and constants!). This often results in an ability to use simple
machine instructions for the functions.
</para>
<para>
Consider an example.
<programlisting>
(defun i (x y)
(declare (type (unsigned-byte 32) x y))
(ldb (byte 32 0) (logxor x (lognot y))))
</programlisting>
The result of <literal>(lognot y)</literal> will be negative and of
type <type>(signed-byte 33)</type>, so a naive implementation on a 32-bit
platform is unable to use 32-bit arithmetic here. But modular
arithmetic optimizer is able to do it: because the result is cut down
to 32 bits, the compiler will replace <function>logxor</function>
and <function>lognot</function> with versions cutting results to 32 bits, and
because terminals (here---expressions <literal>x</literal> and <literal>y</literal>)
are also of type <type>(unsigned-byte 32)</type>, 32-bit machine
arithmetic can be used.
</para>
<note><para> As of &SBCL; 0.8.5 "good" functions
are <function>+</function>, <function>-</function>; <function>logand</function>, <function>logior</function>,
<function>logxor</function>, <function>lognot</function> and their combinations;
and <function>ash</function> with the positive second argument. "Good" widths
are 32 on HPPA, MIPS, PPC, Sparc and X86 and 64 on Alpha. While it is
possible to support smaller widths as well, currently it is not
implemented.
</para></note>
</sect1>
</chapter>

File diff suppressed because it is too large Load diff

View file

@ -1,8 +0,0 @@
<?xml version='1.0'?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:import href="docbook_fo.xsl"/>
<xsl:param name="fop.extensions" select="1"/>
</xsl:stylesheet>

View file

@ -1,10 +0,0 @@
<?xml version='1.0'?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:import href="docbook_html.xsl"/>
<xsl:param name="use.id.as.filename" select="1"/>
<xsl:output encoding="ISO-8859-1" method="html" />
</xsl:stylesheet>

View file

@ -1,16 +0,0 @@
<?xml version='1.0'?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:import href="docbook_chunk.xsl"/>
<xsl:param name="use.id.as.filename" select="1"/>
<!-- Force TT HTML markup for <type> DocBook markup -->
<xsl:template match="type">
<tt xmlns="http://www.w3.org/1999/xhtml" class="type">
<xsl:value-of select="."/>
</tt>
</xsl:template>
</xsl:stylesheet>

View file

@ -1,216 +0,0 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1//EN"
"http://www.oasis-open.org/docbook/xml/4.1/docbookx.dtd" [
<!ENTITY % myents SYSTEM "entities.inc">
%myents;
]>
<chapter id="intro"><title>Introduction</title>
<para>&SBCL; is a mostly-conforming implementation of the &ANSI;
&CommonLisp; standard. This manual focuses on behavior which is
specific to &SBCL;, not on behavior which is common to all
implementations of &ANSI; &CommonLisp;.</para>
<sect1 id="more-cl-info">
<title>Where To Go For More Information about &CommonLisp; in General</title>
<para>Regardless of your ability level, two very useful resources
for working with any implementation of
&CommonLisp; are the
<ulink url="http://ilisp.cons.org"><application>ILISP</application></ulink>
package for <application>Emacs</application> and
<ulink url="http://www.harlequin.com/books/HyperSpec">the &CommonLisp;
HyperSpec</ulink>.</para>
<para>If you're not a programmer and you're trying to learn,
many introductory Lisp books are available. However, we don't have any
standout favorites. If you can't decide, try checking the Usenet
comp.lang.lisp FAQ for recent recommendations.</para>
<para>If you are an experienced programmer in other languages
but need to learn about Lisp, three books stand out.
<itemizedlist>
<listitem><para><emphasis>ANSI Common Lisp</emphasis>, by Paul Graham,
will teach you about most of the language. (And later it might
also be worth checking out <emphasis>On Lisp</emphasis>, by the same
author.)</para></listitem>
<listitem><para><emphasis>Paradigms Of Artificial Intelligence
Programming</emphasis>, by Peter Norvig, also has some good information
on general &CommonLisp; programming, and many nontrivial examples.
Whether or not your work is AI, it's a very good book to look
at.</para></listitem>
<listitem><para>
Neither of the books above emphasizes CLOS, but
<emphasis>Object-Oriented Programming In Common Lisp</emphasis> by Sonya Keene
does. Even if you're very knowledgeable about object oriented
programming in the abstract, it's worth looking at this book
if you want to do any OO in &CommonLisp;. Some abstractions
in CLOS (especially multiple dispatch) go beyond anything
you'll see in most OO systems, and there are a number of lesser
differences as well. This book tends to help with the culture shock.
</para></listitem>
</itemizedlist>
</para>
</sect1>
<sect1 id="where-more">
<title>Where To Go For More Information About &SBCL;</title>
<para>Before you read this user manual, you should probably read
two other things.
<itemizedlist>
<listitem><para>You should know how to program in &CommonLisp;.
If you don't already know how, you should probably read a
<link linkend="more-cl-info">book on it</link>.</para></listitem>
<listitem><para>The Unix <quote>man page</quote> for &SBCL; will tell you
how to start the &SBCL; environment, so you can get to the
classic <quote>hello, world</quote> level of knowledge. It's the file
called <filename>sbcl.1</filename> in the &SBCL; distribution. If &SBCL; is
installed on your system, you can read a formatted copy by
executing the command <command>man sbcl</command>.</para></listitem>
</itemizedlist>
</para>
<para>Besides this user manual and the Unix man page, some
other &SBCL;-specific information is available:
<itemizedlist>
<listitem><para>The <ulink url="http://sbcl.sourceforge.net/">
&SBCL; home page</ulink> has some general
information, plus links to mailing lists devoted to &SBCL;,
and to archives of these mailing lists.</para></listitem>
<listitem><para>Documentation for non-&ANSI; extensions for
various commands is available online from the &SBCL; executable
itself. The extensions for functions which have their own
command prompts (e.g. the debugger, and <function>inspect</function>)
are documented in text available by typing <userinput>help</userinput>
at their command prompts. The extensions for functions which
don't have their own command prompt (like <function>trace</function>
does) are described in their documentation strings,
unless your &SBCL; was compiled with an option not
to include documentation strings, in which case the doc strings
are only readable in the source code.</para></listitem>
<listitem><para>Some low-level information describing the
programming details of the conversion from &CMUCL; to &SBCL;
is available in the <filename>doc/FOR-CMUCL-DEVELOPERS</filename>
file in the &SBCL; distribution.</para></listitem>
</itemizedlist>
</para>
</sect1>
<sect1 id="implementation">
<title>Overview Of SBCL, How It Works And Where It Came From</title>
<para>You can work productively with SBCL without knowing anything
understanding anything about where it came from, how it is implemented,
or how it extends the &ANSI; &CommonLisp; standard. However,
a little knowledge can be helpful in order to understand error
messages, to troubleshoot problems, to understand why some parts of
the system are better debugged than others, and to anticipate which
known bugs, known performance problems, and missing extensions are
likely to be fixed, tuned, or added. </para>
<para>&SBCL; is descended from &CMUCL;, which is itself descended from
Spice Lisp, including early implementations for the Mach operating
system on the IBM RT, back in the 1980s. Design decisions from that
time are still reflected in the current implementation:
<itemizedlist>
<listitem><para>The system expects to be loaded into a
fixed-at-compile-time location in virtual memory, and also expects
the location of all of its heap storage to be specified
at compile time.</para></listitem>
<listitem><para>The system overcommits memory, allocating large
amounts of address space from the system (often more than
the amount of virtual memory available) and then failing
if ends up using too much of the allocated storage.</para></listitem>
<listitem><para>A word is a 32-bit quantity. The system has been
ported to many processor architectures without altering this
basic principle. Some hacks allow the system to run on the Alpha
chip (a 64-bit architecture) but even there 32-bit words are
used. The assumption that a word is
32 bits wide is implicit in hundreds of places in the
system.</para></listitem>
<listitem><para>The system is implemented as a C program which is
responsible for supplying low-level services and loading a
Lisp <quote>.core</quote> file.
</para></listitem>
</itemizedlist>
</para>
<para>&SBCL; also inherited some newer architectural features from
&CMUCL;. The most important is that it has a generational garbage
collector (<quote>GC</quote>), which has various implications (mostly good)
for performance. These are discussed in <link linkend="efficiency">
another chapter</link>.</para>
<para>&SBCL; has diverged from &CMUCL; in that &SBCL; is now
essentially a <quote>compiler-only implementation</quote> of
&CommonLisp;. A &CommonLisp; implementation is permitted to implement
both a compiler and an interpreter, and there's some special support
in the standard (e.g. the distinction between <function>functionp</function>
and <function>compiled-function-p</function>) to help support that. But &SBCL;
has only a vestigial, rudimentary true interpreter. In &SBCL;, the
<function>eval</function> function only truly <quote>interprets</quote> a few
special classes of forms, such as symbols which are
<function>boundp</function>. More complicated forms are evaluated by calling
<function>compile</function> and then calling <function>funcall</function> on the
returned result.
</para>
<para>The direct ancestor of &SBCL; is the X86 port of &CMUCL;. This
port was in some ways the most cobbled-together of all the &CMUCL;
ports, since a number of strange changes had to be made to support the
register-poor X86 architecture. Some things (like tracing and
debugging) do not work particularly well there. &SBCL; should be able
to improve in these areas (and has already improved in some other
areas), but it takes a while.</para>
<para>On the x86, &SBCL; like the X86 port of &CMUCL;, uses a
<emphasis>conservative</emphasis> GC. This means that it doesn't maintain a
strict separation between tagged and untagged data, instead treating
some untagged data (e.g. raw floating point numbers) as
possibly-tagged data and so not collecting any Lisp objects that they
point to. This has some negative consequences for average time
efficiency (though possibly no worse than the negative consequences of
trying to implement an exact GC on a processor architecture as
register-poor as the X86) and also has potentially unlimited
consequences for worst-case memory efficiency. In practice,
conservative garbage collectors work reasonably well, not getting
anywhere near the worst case. But they can occasionally cause
odd patterns of memory usage.</para>
<para>The fork from &CMUCL; was based on a major rewrite of the system
bootstrap process. &CMUCL; has for many years tolerated a very unusual
<quote>build</quote> procedure which doesn't actually build the complete
system from scratch, but instead progressively overwrites parts of a
running system with new versions. This quasi-build procedure can cause
various bizarre bootstrapping hangups, especially when a major change
is made to the system. It also makes the connection between the
current source code and the current executable more tenuous than in
other software systems -- it's easy to accidentally
<quote>build</quote> a &CMUCL; system containing characteristics not
reflected in the current version of the source code.</para>
<para>Other major changes since the fork from &CMUCL; include
<itemizedlist>
<listitem><para>&SBCL; has dropped support for many &CMUCL; extensions,
(e.g. IP networking, remote procedure call, Unix system interface, and X11
interface). Some of these are now available as contributed or
third-party modules.</para></listitem>
<listitem><para>&SBCL; has deleted or deprecated
some nonstandard features and code complexity which helped
efficiency at the price of maintainability. For example, the
&SBCL; compiler no longer implements memory pooling internally
(and so is simpler and more maintainable, but generates more
garbage and runs more slowly), and various block-compilation
efficiency-increasing extensions to the language have been
deleted or are no longer used in the implementation of &SBCL;
itself.</para></listitem>
</itemizedlist>
</para>
</sect1>
</chapter>

View file

@ -1,19 +1,3 @@
#!/bin/sh
. ../find-gnumake.sh
find_gnumake
# Where is xsltproc?
if [ "" != "$XSLTPROC" ]; then
# The user has told us where to find xsltproc, good.
echo using XSLTPROC=$XSLTPROC
elif which xsltproc > /dev/null; then
# We have found it ourselves.
XSLTPROC=xsltproc
else
echo "can't find xsltproc, sorry"
exit 1
fi
export XSLTPROC
$GNUMAKE html
(cd ./manual ; make html)

View file

@ -1,45 +0,0 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1//EN"
"http://www.oasis-open.org/docbook/xml/4.1/docbookx.dtd" [
<!ENTITY % myents SYSTEM "entities.inc">
%myents;
]>
<book lang="en">
<bookinfo>
<title>&SBCL; User Manual</title>
<legalnotice>
<para>This manual is part of the &SBCL; software system. See the
<filename>README</filename> file for more information.</para>
<para>This manual is largely derived from the manual for the
&CMUCL; system, which was produced at Carnegie Mellon University
and later released into the public domain. This manual is in the
public domain and is provided with absolutely no warranty. See the
<filename>COPYING</filename> and <filename>CREDITS</filename>
files for more information.</para>
</legalnotice>
</bookinfo>
<xi:include href="intro.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="compiler.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="efficiency.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="beyond-ansi.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="ffi.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<colophon id="colophon">
<para>This manual is maintained in SGML/DocBook, and automatically
translated into other forms (e.g. HTML or TeX). If you're
<emphasis>reading</emphasis> this manual in one of these non-DocBook
translated forms, that's fine, but if you want to
<emphasis>modify</emphasis> this manual, you are strongly advised to
seek out a DocBook version and modify that instead of modifying a
translated version. Even better might be to seek out
<emphasis>the</emphasis> DocBook version (maintained at the time of
this writing as part of <ulink url="http://sbcl.sourceforge.net/">the
&SBCL; project</ulink>) and submit a patch.</para>
</colophon>
</book>

View file

@ -2,10 +2,7 @@
# Create a distribution containing the HTML versions of system
# documentation. (make-doc.sh needs to be run first, in order to
# compile the DocBook sources into HTML.)
# (Before sbcl-0.7.0, this functionality was part of
# binary-distribution.sh.)
# compile the doc sources into HTML.)
b=${1:?missing base directory name argument}
tar cf $b-html.tar \

View file

@ -17,4 +17,4 @@
;;; checkins which aren't released. (And occasionally for internal
;;; versions, especially for internal versions off the main CVS
;;; branch, it gets hairier, e.g. "0.pre7.14.flaky4.13".)
"0.8.14.27"
"0.8.14.28"