X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;f=doc%2Fbeyond-ansi.sgml;h=b1c0a39a32b301bf7aa883f11018530091b0faed;hb=1bbd405c3c21f93db7aa956946738c8a3f30837d;hp=eb789f0c22474038deb63acd7362df7002e68d84;hpb=5dc28680e9cb2d598da02aed512aa49ea81fdade;p=sbcl.git diff --git a/doc/beyond-ansi.sgml b/doc/beyond-ansi.sgml index eb789f0..b1c0a39 100644 --- a/doc/beyond-ansi.sgml +++ b/doc/beyond-ansi.sgml @@ -1,126 +1,107 @@ -Beyond the &ANSI; Standard</> - -<para>Besides &ANSI;, we have other stuff..</para> - -<sect1 id="non-conformance"><title>Non-Conformance with the &ANSI; Standard</> - -<para>&SBCL; is derived from code which was written before the &ANSI; -standard, and some incompatibilities remain.</para> - -<para>The &ANSI; standard defines constructs like -<function>defstruct</>, <function>defun</>, and <function>declaim</> -so that they can be implemented as macros which expand into ordinary -code wrapped in <function>eval-when</> forms. However, the pre-&ANSI; -&CMUCL; implementation handled these (and some related functions like -<function>proclaim</>) as special cases in the compiler, with subtly -(or sometimes not-so-subtly) different semantics. Much of this -weirdness has been removed in the years since the &ANSI; standard was -released, but bits and pieces remain, so that e.g., as of &SBCL; 0.6.3 -compiling the function - -<programlisting>(defun foo () (defstruct bar))</> - -will cause the class <type>BAR</> to be defined, even when the -function is not executed. These remaining nonconforming behaviors are -considered bugs, and clean patches will be gratefully accepted, but as -long as they don't cause as many problems in practice as other known -issues, they tend not to be actively fixed.</para> - -<para>More than any other &Lisp; system I am aware of, &SBCL; (and its -parent &CMUCL;) store and use a lot of compile-time static type -information. By and large they conform to the standard in doing so, -but in one regard they do not — they consider <function>defun</>s to, -in effect, implicitly <function>proclaim</> type information about the -signature of the function being defined. Thus, if you compile and load - -<programlisting>(defun foo-p (x) - (error "stub, foo-p ~s isn't implemented yet!" x)) -(defun foolike-p (x) - (or (foo-p x) (foo-p (car x))))</programlisting> - -everything will appear to work correctly, but if you subsequently -redefine <function>foo-p</> - -<programlisting>(defun foo-p (x) (or (null x) (symbolp (car x))))</> - -and call - -<programlisting>(foolike-p nil)</> - -you will not get the correct result, but an error, - -<screen>debugger invoked on SB-DEBUG::*DEBUG-CONDITION* of type -SB-KERNEL:SIMPLE-CONTROL-ERROR: - A function with declared result type NIL returned: - FOO-P</screen> - -because when &SBCL; compiled <function>foolike-p</>, &SBCL; thought it -knew that <function>foo-p</> would never return. More insidious -problems are quite possible when &SBCL; thinks it can optimize away e.g. -particular branches of a <function>case</> because of what it's proved -to itself about the function's return type. This will probably be -fixed in the foreseeable future, either with a quick fix, or ideally -in conjunction with some related fixes to generalize the principle -that declarations are assertions (see below). But for now it remains a -gross violation of the &ANSI; spec (and reasonable user -expectations).</para> - -<para>The &CMUCL; <function>defstruct</> implementation treated -structure accessors and other <function>defstruct</>-related functions -(e.g. predicates) as having some special properties, not quite like -ordinary functions. This specialness has been reduced in &SBCL;, but -some still remains. In particular, redefining a structure accessor -function may magically cause the entire structure class to be deleted. -This, too, will probably be fixed in the foreseeable future.</para> - -<para>The CLOS implementation used in &SBCL; is based on the -<application>Portable Common Loops</> (PCL) reference implementation -from Xerox. Unfortunately, PCL seems never to have quite conformed to -the final CLOS specification. Moreover, despite the "Portable" in its -name, it wasn't quite portable. Various implementation-specific hacks -were made to make it run on &CMUCL;, and then more hacks were added to -make it less inefficient. The result is a system with mostly tolerable -performance which mostly conforms to the standard, but which has a few -remaining weirdnesses which seem to be hard to fix. The most important -remaining weirdness is that the <type>CL:CLASS</> class is not the -same as the <type>SB-PCL:CLASS</> type used internally in PCL; and -there are several other symbols maintained in parallel (e.g. -<type>SB-PCL:FIND-CLASS</> vs. <type>CL:FIND-CLASS</>). So far, any -problems this has caused have had workarounds involving consistently -using the SB-PCL versions or the CL versions of the class hierarchy. -This is admittedly ugly, but it may not be fixed in the foreseeable -future, since the required cleanup looks nontrivial, and we don't have -anyone sufficiently motivated to do it.</para> +<!-- -*- mode: SGML; sgml-parent-document: ("user-manual.sgml" "BOOK") -*- --> +<chapter id="beyond-ansi"><title>Beyond The &ANSI; Standard</> + +<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</> + +<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</> 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</> +<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> -<note><para>It's not an idiosyncrasy yet, since we haven't done -it, but someday soon &SBCL; may become a compiler-only implementation. -That is, essentially, <function>eval</> will be defined to create -a lambda expression, call <function>compile</> on the lambda -expression to create a compiled function, and then -<function>funcall</> the resulting function. This would allow -a variety of simplifications in the implementation, while introducing -some other complexities. It remains to be seen when it will be -possible to try this, or whether it will work well when it's tried, -but it looks appealing right now.</para></note> +<para>&SBCL; is essentially a compiler-only implementation of +&CommonLisp;. That is, for all but a few special cases, +<function>eval</> creates a +lambda expression, calls <function>compile</> on the lambda +expression to create a compiled function, and then calls +<function>funcall</> on the resulting function object. This +is explicitly allowed by the &ANSI; standard, but leads to some +oddities, e.g. collapsing <function>functionp</> and +<function>compiled-function-p</> into the same predicate.</para> + +<para>&SBCL; is quite strict about ANSI's definition of +<function>defconstant</>. ANSI says that doing <function>defconstant</> +of the same symbol more than once is undefined unless the new value +is <function>eql</> 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=</> or <function>equal</>. It's +especially annoying because <function>defconstant</> 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))</> +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</> either with <function>defparameter</> or +with a customized macro which does the right thing, possibly along the +lines of the <function>defconstant-eqx</> macro used internally in the +implementation of SBCL itself.</para> + +<para>&SBCL; gives style warnings about various kinds of perfectly +legal code, e.g. +<itemizedlist> + <listitem><para><function>defmethod</> without + <function>defgeneric</></para></listitem> + <listitem><para>multiple <function>defun</>s of the same + symbol</para></listitem> + <listitem><para>special variables not named in the conventional + <varname>*foo*</> style, and lexical variables unconventionally named + in the <varname>*foo*</> 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</>) +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</>s is pointlessly annoying when you compile +and then load a function containing <function>defun</> wrapped +in <function>eval-when</>, 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</> -<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> +<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</> +<sect2><title>Things Which Might Be In The Next &ANSI; Standard</> <para>&SBCL; provides extensive support for calling external C code, described @@ -132,14 +113,139 @@ maintained without keeping them from being GCed. And "finalization" hooks are available to cause code to be executed when an object is GCed.</para> <!-- FIXME: Actually documenting these would be good.:-| --> -<para>&SBCL; does not currently provide Gray streams, but may do so in -the near future. (It has unmaintained code inherited from &CMUCL; to -do so.) <!-- FIXME: Add citation to Gray streams.--> -</para> +<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</>).</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: +<itemizedlist> + <listitem><para>the abstract <classname>metaobject</> class is not + present in the class hierarchy;</para></listitem> + <listitem><para>the <classname>standard-object</> and + <classname>funcallable-standard-object</> classes are + disjoint;</para></listitem> + <listitem><para><function>compute-effective-method</> only returns + one value, not two;</para></listitem> + <listitem><para>the system-supplied <property>:around</> method for + <function>compute-slots</> specialized on + <classname>funcallable-standard-class</> does not respect the + requested order from a user-supplied primary method. +</itemizedlist> </sect2> -<sect2><title>Support for Unix</> +<sect2><title>Threading (a.k.a Multiprocessing)</> + +<para>&SBCL; (as of version 0.x.y, 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. + +<sect3><title>Lisp-level view + +A rudimentary interface to creating and managing multiple threads +can be found in the sb-thread package. This is +intended for public consumption, so look at the exported symbols and +their documentation strings. + +Dynamic bindings to symbols are per-thread. Signal handlers +are per-thread. + +sb-ext:quit exits the current thread, not +necessarily the whole environment. The environment will be shut down +when the last thread exits. + +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. + +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. +sb-thread:make-listener-thread can be used to +start a new thread in its own `session'. + +Mutexes and condition variables are available for +managing access to shared data: see + + + +(apropos "mutex" :sb-thread) + +(apropos "condition" :sb-thread) + and the waitqueue structure + + + + +and poke around in their documentation strings. + +Implementation (Linux x86) + +On Linux x86, this is implemented using +clone() and does not involve pthreads. This is +not because there is anything wrong with pthreads per +se, 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. ps output. + +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. + +Threads waiting on queues (e.g. for locks or condition +variables) are put to sleep using sigtimedwait() +and woken with SIGCONT. + +&SBCL; at present will alway have at least two tasks running as +seen from Linux: when the first process has done startup +initialization (mapping files in place, installing signal handlers +etc) it creates a new thread to run the Lisp startup and initial listener. +The original thread is then used to run GC and to reap dead subthreads +when they exit. + +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 using ptrace(), so you +should be very careful if you wish to examine an &SBCL; worker thread +using strace, truss, +gdb or similar. It may be prudent to disable GC +before doing so. + +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. + +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. Arbitration for the input stream +is managed by locking on sb-thread::*session-lock* + +A thread can be created in a new Lisp 'session' (new terminal or +window) using sb-thread:make-listener-thread. +These sessions map directly onto POSIX sessions, so that pressing +Control-C in the wrong window will not interrupt them - this has been +found to be embarrassing. + +Support For Unix</> <para>The UNIX command line can be read from the variable <varname>sb-ext:*posix-argv*</>. The UNIX environment can be queried with the @@ -152,7 +258,18 @@ is also supported.</para> </sect2> -<sect2><title>Tools to Help Developers +Customization Hooks for Users + +The behaviour of require when called with only +one argument is implementation-defined. In &SBCL; it calls functions +on the user-settable list sb-ext:*module-provider-functions* +- see the require documentation string for details. + +The toplevel repl prompt may be customized, and the function +that reads user input may be replaced completely. + +Tools To Help Developers &SBCL; provides a profiler and other extensions to the &ANSI; trace facility. See the online function documentation for @@ -160,13 +277,21 @@ is also supported. The debugger supports a number of options. Its documentation is accessed by typing help at the debugger prompt. + Documentation for inspect is accessed by typing help at the inspect prompt. -Interface to Low-Level &SBCL; Implementation +Interface To Low-Level &SBCL; Implementation &SBCL; has the ability to save its state as a file for later execution. This functionality is important for its bootstrapping @@ -189,7 +314,7 @@ 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 ecode and bring it up on the developers' mailing +at the code and bring it up on the developers' mailing list. @@ -198,16 +323,20 @@ list. The sb-ext:purify 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, but is less important with modern generational -garbage collectors.) +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. The sb-ext:truly-the operator does what the cl:the operator does in a more conventional implementation of &CommonLisp;, declaring the type of its argument -without any runtime checks. (Ordinarily in &SBCL;, any type declaration -is treated as an assertion and checked at runtime.) +without any runtime checks. (Ordinarily in &SBCL;, any type +declaration is treated as an assertion and checked at runtime.) The sb-ext:freeze-type declaration declares that a type will never change, which can make type testing @@ -215,9 +344,10 @@ type will never change, which can make type testing The sb-ext:constant-function declaration specifies that a function will always return the same value for the same -arguments. This is appropriate for functions like sqrt. -It is not appropriate for functions like aref, which can -change their return values when the underlying data are +arguments, which may allow the compiler to optimize calls +to it. This is appropriate for functions like sqrt, but +is not appropriate for functions like aref, +which can change their return values when the underlying data are changed.