Merge branch 'develop' into 'develop'

texinfo - a bunch of documentation work

See merge request !88
This commit is contained in:
Daniel Kochmański 2017-09-06 12:42:02 +00:00
commit 5ea8972421
22 changed files with 969 additions and 27 deletions

View file

@ -0,0 +1,194 @@
@node The compiler
@section The compiler
@subsection The compiler translates to C
The ECL compiler is essentially a translator from Common-Lisp to C. Given a Lisp source file, the compiler first generates three intermediate files:
@itemize
@item a C-file which consists of the C version of the Lisp program
@item an H-file which consists of declarations referenced in the C-file
@item a Data-file which consists of Lisp data to be used at load time
@end itemize
The ECL compiler then invokes the C compiler to compile the C-file into an object file. Finally, the contents of the Data-file is appended to the object file to make a @dfn{Fasl-file}. The generated Fasl-file can be loaded into the ECL system by the Common-Lisp function @code{load}. By default, the three intermediate files are deleted after the compilation, but, if asked, the compiler leaves them.
The merits of the use of C as the intermediate language are:
@itemize
@item The ECL compiler is highly portable.
@item Cross compilation is possible, because the contents of the intermediate files are common to all versions of ECL. For example, one can compile his or her Lisp program by the ECL compiler on a Sun, bring the intermediate files to DOS, compile the C-file with the gcc compiler under DOS, and then append the Data-file to the object file. This procedure generates the Fasl-file for the ECL system on DOS. This kind of cross compilation makes it easier to port ECL.
@item Hardware-dependent optimizations such as register allocations are done by the C compiler.
@end itemize
The demerits are:
@itemize
@item At those sites where no C compiler is available, the users cannot compile their Lisp programs.
@item The compilation time is long. 70% to 80% of the compilation time is used by the C compiler. The ECL compiler is therefore slower than compiler generating machine code directly.
@end itemize
@subsection The compiler mimics human C programmer
The format of the intermediate C code generated by the ECL compiler is the same as the hand-coded C code of the ECL source programs. For example, supposing that the Lisp source file contains the following function definition:
@verbatim
(defvar *delta* 2)
(defun add1 (x) (+ *delta* x))
@end verbatim
The compiler generates the following intermediate C code.
@verbatim
/* function definition for ADD1 */
static cl_object L1(cl_object V1)
{ VT2 VLEX2 CLSR2
cl_object value0;
value0=number_plus(symbol_value(VV[0]),V1); NVALUES=1;
return value0;
}
/* initialization of this module */
void init_CODE(cl_object flag)
{ VT1 CLSR1
cl_object value0;
if (!FIXNUMP(flag)){
Cblock=flag;
#ifndef ECL_DYNAMIC_VV
flag->cblock.data = VV;
#endif
flag->cblock.self_destruct=0;
flag->cblock.data_size = VM;
flag->cblock.data_text = compiler_data_text;
flag->cblock.data_text_size = compiler_data_text_size;
return;}
#ifdef ECL_DYNAMIC_VV
VV = Cblock->cblock.data;
#endif
T0= MAKE_FIXNUM(2);
si_Xmake_special(VV[0])
if(SYM_VAL(T0)!=OBJNULL) cl_setq(VV[0],T0);
cl_def_c_function(VV[1],(void*)L1,1);
}
@end verbatim
The C function L1 implements the Lisp function add1. This relation is established by @code{cl_def_c_function} in the initialization function @code{init_CODE}, which is invoked at load time. There, the vector @code{VV} consists of Lisp objects; @code{VV[0]} and @code{VV[1]} in this example hold the Lisp symbols @code{*delta*} and @code{add1}. @code{VM} in the definition of @code{L1} is a C macro declared in the corresponding H-file. The actual value of @code{VM} is the number of value stack locations used by this module, i.e., 2 in this example. Thus the following macro definition is found in the H-file.
@verbatim
#define VM 2
@end verbatim
@subsection Implementation of Compiled Closures
The ECL compiler takes two passes before it invokes the C compiler. The major role of the first pass is to detect function closures and to detect, for each function closure, those lexical objects (i.e., lexical variable, local function definitions, tags, and block-names) to be enclosed within the closure. This check must be done before the C code generation in the second pass, because lexical objects to be enclosed in function closures are treated in a different way from those not enclosed.
Ordinarily, lexical variables in a compiled function @var{f} are allocated on the C stack. However, if a lexical variable is to be enclosed in function closures, it is allocated on a list, called the "environment list", which is local to @var{f}. In addition, a local variable is created which points to the lexical variable's location (within the environment list), so that the variable may be accessed through an indirection rather than by list traversal.
The environment list is a pushdown list: It is empty when @var{f} is called. An element is pushed on the environment list when a variable to be enclosed in closures is bound, and is popped when the binding is no more in effect. That is, at any moment during execution of @var{f}, the environment list contains those lexical variables whose binding is still in effect and which should be enclosed in closures. When a compiled closure is created during execution of @var{f}, the compiled code for the closure is coupled with the environment list at that moment to form the compiled closure.
Later, when the compiled closure is invoked, a pointer is set up to each lexical variable in the environment list, so that each object may be referenced through a memory indirection.
Let us see an example. Suppose the following function has been compiled.
@verbatim
(defun foo (x)
(let ((a #'(lambda () (incf x)))
(y x))
(values a #'(lambda () (incf x y)))))
@end verbatim
@code{foo} returns two compiled closures. The first closure increments @var{x} by one, whereas the second closure increments @var{x} by the initial value of @var{x}. Both closures return the incremented value of @var{x}.
@verbatim
>(multiple-value-setq (f g) (foo 10))
#<compiled-closure nil>
>(funcall f)
11
>(funcall g)
21
>
@end verbatim
After this, the two compiled closures look like:
@verbatim
second closure y: x:
|-------|------| |-------|------| |------|------|
| ** | --|----->| 10 | --|------>| 21 | nil |
|-------|------| |-------|------| |------|------|
^
first closure |
|-------|------| |
| * | --|----------|
|-------|------|
* : address of the compiled code for #'(lambda () (incf x))
** : address of the compiled code for #'(lambda () (incf x y))
@end verbatim
@subsection Use of Declarations to Improve Efficiency
Declarations, especially type and function declarations, increase the efficiency of the compiled code. For example, for the following Lisp source file, with two Common-Lisp declarations added,
@verbatim
(eval-when (compile)
(proclaim '(function tak (fixnum fixnum fixnum) fixnum))
(defun tak (x y z)
(declare (fixnum x y z))
(if (not (< y x))
z
(tak (tak (1- x) y z)
(tak (1- y) z x)
(tak (1- z) x y))))
@end verbatim
The compiler generates the following C code:
@verbatim
/* local entry for function TAK */
static int LI1(register int V1,register int V2,register int V3)
{ VT3 VLEX3 CLSR3
TTL:
if (V2 < V1) {
goto L2;}
return(V3);
L2:
{ int V5;
V5 = LI1((V1)-1,V2,V3);
{ int V6;
V6 = LI1((V2)-1,V3,V1);
V3 = LI1((V3)-1,V1,V2);
V2 = V6;
V1 = V5;}}
goto TTL;
;;; Note: Tail-recursive call of TAK was replaced by iteration.
}
@end verbatim
@subsection Inspecting generated C code
Common-Lisp defines a function disassemble, which is supposed to disassemble a compiled function and to display the assembler code. According to @cite{Common-Lisp: The Language},
@quotation
This is primary useful for debugging the compiler, ..\\
@end quotation
This is, however, @emph{useless} in our case, because we are not concerned with assembly language. Rather, we are interested in the C code generated by the ECL compiler. Thus the disassemble function in ECL accepts not-yet-compiled functions only and displays the translated C code.
@verbatim
> (defun add1 (x) (1+ x))
ADD1
> (disassemble *)
;;; Compiling (DEFUN ADD1 ...).
;;; Emitting code for ADD1.
/* function definition for ADD1 */
static L1(int narg, object V1)
{ VT3 VLEX3 CLSR3
TTL:
VALUES(0) = one_plus((V1));
RETURN(1);
}
@end verbatim

View file

@ -10,7 +10,7 @@
* Manipulating Lisp objects::
* Environment implementation::
@c * The interpreter::
@c * The compiler::
* The compiler::
@c * Porting ECL::
* Removed features::
@c * Experimental features::
@ -22,4 +22,5 @@
@c @include developer-guide/dpp.txi
@include developer-guide/objects.txi
@include developer-guide/environment.txi
@include developer-guide/compiler.txi
@include developer-guide/removed.txi

View file

@ -38,14 +38,14 @@
@c @node Green Threads
@c @section Green Threads
@node Signals and Interrupts
@section Signals and Interrupts
@c Signals and Interrupts
@include extensions/signals.txi
@c Memory Management
@include extensions/memory.txi
@node Meta-Object Protocol (MOP)
@section Meta-Object Protocol (MOP)
@c Meta-Object Protocol (MOP)
@include extensions/mop.txi
@c @node Continuations
@c @section Continuations

View file

@ -44,6 +44,10 @@ Beginning with version 9.2.1, ECL operates a tighter control of the resources it
The customizable limits are listed in @ref{tab:mem-limits}, but they need a careful description.
@lspindex ext:heap-size
@lspindex ext:c-stack
@lspindex ext:binding-stack
@lspindex ext:lisp-stack
@itemize
@item
@code{ext:heap-size} limits the total amount of memory which is available for lisp objects. This is the memory used when you create conses, arrays, structures, etc.

View file

@ -0,0 +1,28 @@
@node Meta-Object Protocol (MOP)
@section Meta-Object Protocol (MOP)
@node MOP - Introduction
@subsection Introduction
The Meta-Object Protocol is an extension to Common Lisp which provides rules, functions and a type structure to handle the object system. It is a reflective system, where classes are also objects and can be created and manipulated using very well defined procedures.
The Meta-Object Protocol associated to Common Lisp's object system was introduced in a famous book, The Art of the Metaobject Protocol AMOP (@xref{Bibliography}), which was probably intended for the ANSI (@xref{Bibliography}) specification but was drop out because of its revolutionary and then not too well tested ideas.
The AMOP is present, in one way or another, in most Common Lisp implementations, eithr using proprietary systems or because their implementation of CLOS descended from PCL (Portable CommonLoops). It has thus become a de facto standard and ECL should not be without it.
Unfortunately ECL's own implemention originally contained only a subset of the AMOP. This was a clever decision at the time, since the focus was on performance and on producing a stable and lean implementation of Common Lisp. Nowadays it is however not an option, specially given that most of the AMOP can be implemented with little cost for both the implementor and the user.
So ECL has an almost complete implementation of the AMOP. However, since it was written from scratch and progressed according to user's request and our own innovations, there might still be some missing functionality which we expect to correct in the near future. Please report any feature you miss as a bug through the appropriate channels.
When considering the Metaobject Protocol, the book itself should be the main reference. The following sections contain only further extensions or improvements over the paragraphs which were either conflicting or less specified.
@c @node MOP - Classes
@c @subsection Classes
@c @node MOP - Slots
@c @subsection Slots
@c @node MOP - Generic functions and methods
@c @subsection Generic functions and methods
@c @node MOP - Sealed slots and classes
@c @subsection Sealed slots and classes

View file

@ -25,7 +25,7 @@ this feature.
@subsection Package local nicknames dictionary
@deffn {macro} cl:defpackage name [[options]]*
@defmac cl:defpackage name [[options]]*
Options are extended to include
:local-nicknames (local-nickname actual-package-name)*
@ -47,7 +47,7 @@ Example:
(let ((*package* (find-package :quux)))
(find-symbol "X" :bar)) ; => FOO::X
@end lisp
@end deffn
@end defmac
@lspindex ext:package-local-nicknames
@cppindex si_package_local_nicknames

View file

@ -0,0 +1,136 @@
@node Signals and Interrupts
@section Signals and Interrupts
@node Signals and Interrupts - Problems associated to signals
@subsection Problems associated to signals
POSIX contemplates the notion of "signals", which are events that cause a process or a thread to be interrupted. Windows uses the term "exception", which includes also a more general kind of errors.
In both cases the consequence is that a thread or process may be interrupted at any time, either by causes which are intrinsic to them (synchronous signals), such as floating point exceptions, or extrinsic (asynchronous signals), such as the process being aborted by the user.
Of course, those interruptions are not always welcome. When the interrupt is delivered and a handler is invoked, the thread or even the whole program may be in an inconsistent state. For instance the thread may have acquired a lock, or it may be in the process of filling the fields of a structure. Furthermore, sometimes the signal that a process receives may not even be related to it, as in the case when a user presses @kbd{Cltr-C} and a @code{SIGINT} signal is delivered to an arbitrary thread, or when the process receives the Windows exception @code{CTRL_CLOSE_EVENT} denoting that the terminal window is being closed.
Understanding this, POSIX restricts severely what functions can be called from a signal handler, thereby limiting its usefulness. However, Common Lisp users expect to be able to handle floating point exceptions and to gracefully manage user interrupts, program exits, etc. In an attempt to solve this seemingly impossible problem, ECL has taken a pragmatic approach that works, it is rather safe, but involves some work on the ECL maintainers and also on users that want to embed ECL as a library.
@node Signals and Interrupts - Kinds of signals
@subsection Kinds of signals
@node Signals and Interrupts - Synchronous signals
@subsubsection Synchronous signals
The name derives from POSIX and it denotes interrupts that occur due to the code that a particular thread executes. They are largely equivalent to C++ and Java exceptions, and in Windows they are called "unchecked exceptions."
Common Lisp programs may generate mostly three kinds of synchronous signals:
@itemize
@item Floating point exceptions, that result from overflows in computations, division by zero, and so on.
@item Access violations, such as dereferencing NULL pointers, writing into regions of memory that are protected, etc.
@item Process interrupts.
@end itemize
The first family of signals are generated by the floating point processing hardware in the computer, and they typically happen when code is compiled with low security settings, performing mathematical operations without checks.
The second family of signals may seem rare, but unfortunately they still happen quite often. One scenario is wrong code that handles memory directly via FFI. Another one is undetected stack overflows, which typically result in access to protected memory regions. Finally, a very common cause of these kind of exceptions is invoking a function that has been compiled with very low security settings with arguments that are not of the expected type -- for instance, passing a float when a structure is expected.
The third family is related to the multiprocessing capabilities in Common Lisp systems and more precisely to the mp:interrupt-process function which is used to kill, interrupt and inspect arbitrary threads. In POSIX systems ECL informs a given thread about the need to interrupt its execution by sending a particular signal from the set which is available to the user.
Note that in neither of these cases we should let the signal pass unnoticed. Access violations and floating point exceptions may propagate through the program causing more harm than expected, and without process interrupts we will not be able to stop and cancel different threads. The only question that remains, though, is whether such signals can be handled by the thread in which they were generated and how.
@node Signals and Interrupts - Asynchronous signals
@subsubsection Asynchronous signals
In addition to the set of synchronous signals or "exceptions", we have a set of signals that denote "events", things that happen while the program is being executed, and "requests". Some typical examples are:
@itemize
@item Request for program termination (@code{SIGKILL}, @code{SIGTERM}).
@item Indication that a child process has finished.
@item Request for program interruption (@code{SIGINT}), typically as a consecuence of pressing a key combination, @kbd{Ctrl-C}.
@end itemize
The important difference with synchronous signals is that we have no thread that causes the interrupt and thus there is no preferred way of handling them. Moreover, the operating system will typically dispatch these signals to an arbitrary thread, unless we set up mechanisms to prevent it. This can have nasty consequences if the incoming signal interrupt a system call, or leaves the interrupted thread in an inconsistent state.
@node Signals and Interrupts - Signals and interrupts in ECL
@subsection Signals and interrupts in ECL
The signal handling facilities in ECL are constrained by two needs. First of all, we can not ignore the synchronous signals mentioned in @ref{Signals and Interrupts - Synchronous signals}. Second, all other signals should cause the least harm to the running threads. Third, when a signal is handled synchronously using a signal handler, the handler should do almost nothing unless we are completely sure that we are in an interruptible region, that is outside system calls, in code that ECL knows and controls.
The way in which this is solved is based on the existence of both synchronous and asynchronous signal handling code, as explained in the following two sections.
@node Signals and Interrupts - Handling of asynchronous signals
@subsubsection Handling of asynchronous signals
In systems in which this is possible, ECL creates a signal handling thread to detect and process asynchronous signals (@xref{Signals and Interrupts - Asynchronous signals}). This thread is a trivial one and does not process the signals itself: it communicates with, or launches new signal handling threads to act accordingly to the denoted events.
The use of a separate thread has some nice consequences. The first one is that those signals will not interrupt any sensitive code. The second one is that the signal handling thread will be able to execute arbitrary lisp or C code, since it is not being executed in a sensitive context. Most important, this style of signal handling is the recommended one by the POSIX standards, and it is the one that Windows uses.
The installation of the signal handling thread is dictated by a boot time option, @code{ECL_OPT_SIGNAL_HANDLING_THREAD}, and it will only be possible in systems that support either POSIX or Windows threads.
Systems which embed ECL as an extension language may wish to deactivate the signal handling thread using the previously mentioned option. If this is the case, then they should take appropriate measures to avoid interrupting the code in ECL when such signals are delivered.
Systems which embed ECL and do not mind having a separate signal handling thread can control the set of asynchronous signals which is handled by this thread. This is done again using the appropriate boot options such as @code{ECL_OPT_TRAP_SIGINT}, @code{ECL_OPT_TRAP_SIGTERM}, etc. Note that in order to detect and handle those signals, ECL must block them from delivery to any other thread. This means changing the @code{sigprocmask()} in POSIX systems or setting up a custom @code{SetConsoleCtrlHandler()} in Windows.
@node Signals and Interrupts - Handling of synchronous signals
@subsubsection Handling of synchronous signals
We have already mentioned that certain synchronous signals and exceptions can not be ignored and yet the corresponding signal handlers are not able to execute arbitrary code. To solve this seemingly impossible contradiction, ECL uses a simple solution, which is to mark the sections of code which are interruptible, and in which it is safe for the handler to run arbitrary code. All other regions would be considered "unsafe" and would be protected from signals and exceptions.
In principle this "marking" of safe areas can be done using POSIX functions such as @code{pthread_sigmask()} or @code{sigprocmask()}. However in practice this is slow, as it involves at least a function call, resolving thread-local variables, etc, etc, and it will not work in Windows.
Furthermore, sometimes we want signals to be detected but not to be immediately processed. For instance, when reading from the terminal we want to be able to interrupt the process, but we can not execute the code from the handler, since the C function which is used to read from the terminal, @code{read()}, may have left the input stream in an inconsistent, or even locked state.
The approach in ECL is more lightweight: we install our own signal handler and use a thread-local variable as a flag that determines whether the thread is executing interrupt safe code or not. More precisely, if the variable @code{ecl_process_env()->disable_interrupts} is set, signals and exceptions will be postponed and then the information about the signal is queued. Otherwise the appropriate code is executed: for instance invoking the debugger, jumping to a condition handler, quitting, etc.
Systems that embed ECL may wish to deactivate completely these signal handlers. This is done using the boot options, @code{ECL_OPT_TRAP_SIGFPE}, @code{ECL_OPT_TRAP_SIGSEGV}, @code{ECL_OPT_TRAP_SIGBUS}, @code{ECL_OPT_TRAP_INTERRUPT_SIGNAL}.
Systems that embed ECL and want to allow handling of synchronous signals should take care to also trap the associated lisp conditions that may arise. This is automatically taken care of by functions such as @code{si_safe_eval()}, and in all other cases it can be solved by enclosing the unsafe code in a @code{CL_CATCH_ALL_BEGIN} frame.
@node Signals and Interrupts - Considerations when embedding ECL
@subsection Considerations when embedding ECL
There are several approaches when handling signals and interrupts in a program that uses ECL. One is to install your own signal handlers. This is perfectly fine, but you should respect the same restrictions as ECL. Namely, you may not execute arbitrary code from those signal handlers, and in particular it will not always be safe to execute Common Lisp code from there.
If you want to use your own signal handlers then you should set the appropriate options before invoking @code{cl_boot()}, as explained in @code{ecl_set_option}. Note that in this case ECL will not always be able to detect floating point exceptions, specially if your compiler does not support C99 and the corresponding floating point flags.
The other option is to let ECL handle signals itself. This would be safer when the dominant part of the code is Common Lisp, but you may need to protect the code that embeds ECL from being interrupted using either the macros @code{ecl_disable_interrupts} and @code{ecl_enable_interrupts} or the POSIX functions @code{pthread_sigmaks}and @code{sigprocmask}.
@node Signals and Interrupts - Signals Reference
@subsection Signals Reference
@lspindex ext:with-interrupts
@lspindex ext:without-interrupts
@defmac ext:with-interrupts &body body
Execute code with interrupts optionally enabled.
@subsubheading Description
Executes the given body with all interrupts enabled. Since interrupts are normally enabled, this macro only makes sense if there is an outer @code{ext:without-interrupts} with a corresponding @code{ext:allow-with-interrupts}: interrupts are not enabled if any outer @code{mp:without-interrupts} is not accompanied by @code{mp:allow-with-interrupts}.
@end defmac
@defmac ext:without-interrupts &body body
Execute code without being interrupted.
@subsubheading Description
Executes the given body with all interrupts disabled. This macro is compatible with the one in SBCL and as such it also defines three other local macros @code{ext:allow-with-interrupts}, @code{ext:with-local-interrupts} and @code{ext:with-restored-interrupts}.
Deferrable interrupts include most blockable POSIX signals, and @code{mp:interrupt-process}. Does not interfere with garbage collection, and does not inhibit scheduling of other threads.
This macro binds @code{allow-with-interrupts}, @code{with-local-interrupts} and @code{with-restored-interrupts} as a local macros.
@code{ext:with-restored-interrupts} executes the body with interrupts enabled if and only if the @code{ext:without-interrupts} was in an environment in which interrupts were allowed.
@code{ext:allow-with-interrupts} allows the ext:with-interrupts to take effect during the dynamic scope of its body, unless there is an outer ext:without-interrupts without a corresponding @code{ext:allow-with-interrupts}.
@code{ext:with-local-interrupts} executes its body with interrupts enabled provided that for there is an @code{ext:allow-with-interrupts} for every @code{ext:without-interrupts} surrounding the current one. @code{ext:with-local-interrupts} is equivalent to:
@verbatim
(allow-with-interrupts (with-interrupts ...))
@end verbatim
Care must be taken not to let either ext:allow-with-interrupts or ext:with-local-interrupts appear in a function that escapes from inside the ext:without-interrupts in:
@verbatim
(without-interrupts
;; The body of the lambda would be executed with WITH-INTERRUPTS allowed
;; regardless of the interrupt policy in effect when it is called.
(lambda () (allow-with-interrupts ...)))
(without-interrupts
;; The body of the lambda would be executed with interrupts enabled
;; regardless of the interrupt policy in effect when it is called.
(lambda () (with-local-interrupts ...)))
@end verbatim
@end defmac

View file

@ -1,5 +1,6 @@
@node Arrays
@section Arrays
@cindex Arrays
@node Arrays - Array limits
@subsection Array limits
@ -44,7 +45,10 @@ Let us remark that some of these specialized types might not exist in your platf
C types, limits and enumerations
@subsubheading Constants and types
@cppindex ECL_ARRAY_RANK_LIMIT
@cppindex ECL_ARRAY_DIMENSION_LIMIT
@cppindex ECL_ARRAY_TOTAL_LIMIT
@cppindex cl_elttype
@defvr Constant ECL_ARRAY_RANK_LIMIT
@end defvr
@defvr Constant ECL_ARRAY_DIMENSION_LIMIT
@ -75,7 +79,8 @@ ECL uses also internally a set of constants to describe the different specialize
To and from element types
@subsubheading Functions
@cppindex ecl_aet_to_symbol
@cppindex ecl_symbol_to_aet
@deftypefun cl_object ecl_aet_to_symbol (cl_elttype @var{param})
@end deftypefun
@deftypefun cl_elttype ecl_symbol_to_aet (cl_object @var{type})
@ -90,6 +95,9 @@ The functions may signal an error if any of the arguments is an invalid C or Lis
Creating array and vectors
@subsubheading Functions
@cppindex ecl_alloc_simple_vector
@cppindex si_make_vector
@cppindex si_make_array
@deftypefun cl_object ecl_alloc_simple_vector( cl_elttype element_type, cl_index length);
@end deftypefun
@deftypefun cl_object si_make_vector( cl_object element_type, cl_object length, cl_object adjustablep, cl_object fill_pointerp, cl_object displaced_to, cl_object displacement);
@ -149,6 +157,10 @@ cl_object a = si_make_array(dims, type, Cnil, /* adjustable */
@end verbatim
@subsubsection Accessors
@cppindex ecl_aref
@cppindex ecl_aset
@cppindex ecl_aref1
@cppindex ecl_aset1
Reading and writing array elements
@subsubheading Functions
@ -172,6 +184,9 @@ The first argument to @code{ecl_aref} or @code{ecl_aset} is an array of any numb
All functions above check that the index does not exceed the array bounds, that the values match the array element type and that the argument is an array (or a vector). If these conditions are not met, a type error is signaled.
@subsubsection Array properties
@cppindex ecl_array_elttype
@cppindex ecl_array_rank
@cppindex ecl_array_dimension
Array size, fill pointer, etc.
@subsubheading Synopsis

View file

@ -12,7 +12,8 @@ When using C characters we are actually relying on the char type of the C langua
When no option is specified ECL builds with support for a larger character set, the Unicode 6.0 standard. This uses 24 bit large character codes, also known as @dfn{codepoints}, with a large database of character properties which include their nature (alphanumeric, numeric, etc), their case, their collation properties, whether they are standalone or composing characters, etc.
@subsubsection Character types
If compiled without Unicode support, ECL all characters are implemented using 8-bit codes and the type @code{extended-char} is empty. If compiled with Unicode support, characters are implemented using 24 bits and the @code{extended-char} type covers characters above code 255.
@lspindex extended-char
If ECL is compiled without Unicode support, all characters are implemented using 8-bit codes and the type @code{extended-char} is empty. If compiled with Unicode support, characters are implemented using 24 bits and the @code{extended-char} type covers characters above code 255.
@multitable @columnfractions .33 .33 .33
@headitem Type @tab With Unicode @tab Without Unicode
@item standard-char @tab #\Newline,32-126 @tab #\Newline,32-126
@ -21,6 +22,7 @@ If compiled without Unicode support, ECL all characters are implemented using 8-
@end multitable
@subsubsection Character names
@lspindex standard-char
All characters have a name. For non-printing characters between 0 and 32, and for 127 we use the ordinary ASCII names. Characters above 127 are printed and read using hexadecimal Unicode notation, with a U followed by 24 bit hexadecimal number, as in @code{U0126}.
@float Table, tab:example-char-names
@ -55,6 +57,8 @@ Internally, ECL represents the @code{#\Newline} character by a single code. Howe
@subsection C Reference
@subsubsection C types
@cppindex ecl_base_char
@cppindex ecl_character
C character types
@subsubheading Type names
@multitable {aaaaaaaaaaaaa} {aaaaaaaaa}
@ -62,15 +66,20 @@ C character types
@item ecl_base_char @tab base-char
@end multitable
@subsubheading Description
ECL defines two C types to hold its characters: @code{ecl_base_char} and @code{ecl_character}.
When ECL is built without Unicode, they both coincide and typically match @code{unsigned char}, to cover the 256 codes that are needed.
When ECL is built with Unicode, the two types are no longer equivalent, with @code{ecl_character} being larger.
@itemize
@item When ECL is built without Unicode, they both coincide and typically match @code{unsigned char}, to cover the 256 codes that are needed.
@item When ECL is built with Unicode, the two types are no longer equivalent, with @code{ecl_character} being larger.
@end itemize
For your code to be portable and future proof, use both types to really express what you intend to do.
@subsubsection Constructors
@cppindex ECL_CODE_CHAR
@cppindex ECL_CHAR_CODE
@cppindex ecl_char_code
Creating and extracting characters from Lisp objects
@subsubheading Functions
@deftypefun cl_object ECL_CODE_CHAR (ecl_character @var{code});
@ -85,8 +94,15 @@ Creating and extracting characters from Lisp objects
These functions and macros convert back and forth from C character types to Lisp. The macros @code{ECL_CHAR_CODE} and @code{ECL_CODE_CHAR} perform this coercion without checking the arguments. The functions @code{ecl_char_code} and @code{ecl_base_char_code}, on the other hand, verify that the argument has the right type and signal an error otherwise.
@subsubsection Predicates
@cppindex ecl_base_char_p
@cppindex ecl_alpha_char_p
@cppindex ecl_alphanumeric_p
@cppindex ecl_graphic_char_p
@cppindex ecl_digit_p
@cppindex ecl_standard_char_p
C predicates for Lisp characters
@subsubheading Functions
@deftypefun bool ecl_base_char_p (ecl_character @var{c});
@end deftypefun
@deftypefun bool ecl_alpha_char_p (ecl_character @var{c});
@ -103,6 +119,11 @@ C predicates for Lisp characters
These functions are equivalent to their Lisp equivalents but return C booleans.
@subsubsection Character case
@cppindex ecl_upper_case_p
@cppindex ecl_lower_case_p
@cppindex ecl_both_case_p
@cppindex ecl_char_downcase
@cppindex ecl_char_upcase
C functions related to the character case
@subsubheading Functions
@deftypefun bool ecl_upper_case_p (ecl_character @var{c});
@ -116,7 +137,7 @@ C functions related to the character case
@deftypefun ecl_character ecl_char_upcase (ecl_character @var{c});
@end deftypefun
@subsubheading Description
These functions check or change the case of a character. Note that in an Unicode context, the output of these functions might not be accurate (for instance when the uppercase character has two or more codepoints).
These functions check or change the case of a character. Note that in a Unicode context, the output of these functions might not be accurate (for instance when the uppercase character has two or more codepoints).
@subsubsection ANSI Dictionary
Common Lisp and C equivalence

View file

@ -3,6 +3,8 @@
@node Conditions - C Reference
@subsection C Reference
@cppindex ECL_HANDLER_CASE
@cppindex ECL_RESTART_CASE
@deffn Macro ECL_HANDLER_CASE
C macro for @clhs{m_hand_1.htm,handler-case}

View file

@ -135,3 +135,301 @@ In @ref{tab:fun-const} we list all Common Lisp values related to the limits of f
@end multitable
@end float
@node C Calling conventions
@subsection C Calling conventions
ECL is implemented using either a C or a C++ compiler. This is not a limiting factor, but imposes some constraints on how these languages are used to implement functions, multiple values, closures, etc. In particular, while C functions can be called with a variable number of arguments, there is no facility to check how many values were actually passed. This forces us to have two types of functions in ECL
@itemize
@item Functions that take a fixed number of arguments have a simple C signature, with all arguments being properly declared, as in @code{cl_object cl_not(cl_object arg1)}.
@item Functions with a variable number of arguments, such as those acception @code{&optional}, @code{&rest} or @code{&key} arguments, must take as first argument the number of remaining ones, as in @code{cl_object cl_list(cl_narg narg, ...)}. Here @var{narg} is the number of supplied arguments.
@end itemize
The previous conventions set some burden on the C programmer that calls ECL, for she must know the type of function that is being called and supply the right number of arguments. This burden disappears for Common Lisp programmers, though.
As an example let us assume that the user wants to invoke two functions which are part of the ANSI @bibcite{ANSI} standard and thus are exported with a C name. The first example is cl_cos, which takes just one argument and has a signature @code{cl_object cl_cos(cl_object)}.
@verbatim
#include <math.h>
...
cl_object angle = ecl_make_double_float(M_PI);
cl_object c = cl_cos(angle);
printf("\nThe cosine of PI is %g\n", ecl_double_float(c));
@end verbatim
The second example also involves some Mathematics, but now we are going to use the C function corresponding to @code{+}. As described in @ref{Numbers - Numbers C dictionary}, the C name for the plus operator is @code{cl_P} and has a signature @code{cl_object cl_P(cl_narg narg,...)}. Our example now reads as follows
@verbatim
cl_object one = ecl_make_fixnum(1);
cl_object two = cl_P(2, one, one);
cl_object three = cl_P(3, one, one, one);
printf("\n1 + 1 is %d\n", ecl_fixnum(two));
printf("\n1 + 1 + 1 is %d\n", ecl_fixnum(three));
@end verbatim
Note that most Common Lisp functions will not have a C name. In this case one must use the symbol that names them to actually call the functions, using @code{cl_funcall} or @code{cl_apply}. The previous examples may thus be rewritten as follows
@verbatim
/* Symbol + in package CL */
cl_object plus = ecl_make_symbol("+","CL");
cl_object one = ecl_make_fixnum(1);
cl_object two = cl_funcall(3, plus, one, one);
cl_object three = cl_funcall(4, plus, one, one, one);
printf("\n1 + 1 is %d\n", ecl_fixnum(two));
printf("\n1 + 1 + 1 is %d\n", ecl_fixnum(three));
@end verbatim
Another restriction of C and C++ is that functions can only take a limited number of arguments. In order to cope with this problem, ECL uses an internal stack to pass any argument above a hardcoded limit, @code{ECL_C_CALL_ARGUMENTS_LIMIT}, which is as of this writing 63. The use of this stack is transparently handled by the Common Lisp functions, such as apply, funcall and their C equivalents, and also by a set of macros, @code{cl_va_arg}, which can be used for coding functions that take an arbitrary name of arguments.
@subsection C Reference
@cppindex ecl_bds_bind
@cppindex ecl_bds_push
@defun ecl_bds_bind (cl_env_ptr @var{cl_env}, cl_object @var{var}, cl_object @var{value});
@end defun
@defun ecl_bds_push (cl_env_ptr @var{cl_env}, cl_object @var{var});
Bind a special variable
@subsubheading Description
Establishes a variable binding for the symbol @var{var} in the Common Lisp environment @var{env}, assigning it @var{value}.
This macro or function is the equivalent of @clhs{s_let_l.htm,LET*} and @clhs{s_let_l.htm,LET}.
@code{ecl_bds_push} does a similar thing, but reuses the old value of the same variable. It is thus the equivalent of @code{(LET ((VAR VAR)) ...)}
Every variable binding must undone when no longer needed. It is best practice to match each call to @code{ecl_bds_bind} by another call to @code{ecl_bds_unwind} in the same function.
@end defun
@cppindex ecl_bds_unwind1
@cppindex ecl_bds_unwind_n
@defun ecl_bds_unwind1 (cl_env_ptr @var{cl_env});
@end defun
@defun ecl_bds_unwind_n (cl_env_ptr @var{cl_env}, int @var{n});
Undo one variable binding
@subsubheading Description
@code{ecl_bds_unwind1} undoes the outermost variable binding, restoring the original value of the symbol in the process.
@code{ecl_bds_unwind_n} does the same, but for the @var{n} last variables.
Every variable binding must undone when no longer needed. It is best practice to match each call to @code{ecl_bds_bind} by another call to @code{ecl_bds_unwind} in the same function.
@end defun
@cppindex ecl_setq
@deffn Macro ecl_setq (cl_env_ptr @var{cl_env}, cl_object @var{var}, cl_object @var{value});
C equivalent of setq
@subsubheading Description
Assigns @var{value} to the special variable denoted by the symbol @var{var}, in the Common Lisp environment @var{cl_env}.
This function implements a variable assignment, not a variable binding. It is thus the equivalent of @clhs{s_setq.htm,setq}.
@end deffn
@cppindex ecl_symbol_value
@defun ecl_symbol_value (cl_env_ptr @var{cl_env}, cl_object @var{var});
@subsubheading Description
Retrieves the value of the special variable or constant denoted by the symbol @var{var}, in the Common Lisp environment @var{cl_env}.
This function implements the equivalent of @clhs{f_symb_5.htm,symbol-value} and works both on special variables and constants.
If the symbol is not bound, an error is signaled.
@end defun
@cppindex ecl_va_list
@cppindex ecl_va_start
@cppindex ecl_va_arg
@cppindex ecl_va_end
@deffn Macro {typedef struct @{ ... @} ecl_va_list[1];}
@end deffn
@deffn Macro ecl_va_start (ecl_va_list @var{arglist}, @var{last_argument}, @var{narg}, @var{n_ordinary});
@end deffn
@deftypefn Macro cl_object ecl_va_arg (ecl_va_list @var{arglist});
@end deftypefn
@deftypefn Macro cl_object ecl_va_end (ecl_va_list @var{arglist});
Accepting a variable number of arguments
@subsubheading Description
The macros above are used to code a function that accepts an arbitrary number of arguments. We will describe them in a practical example
@verbatim
cl_object my_plus(cl_narg narg, cl_object required1, ...)
{
cl_env_ptr env = ecl_process_env();
cl_object other_value;
ecl_va_list varargs;
ecl_va_start(varargs, required1, narg, 1);
while (narg > 1) {
cl_object other_value = ecl_va_arg(varargs);
required1 = ecl_plus(required1, other_value);
}
ecl_va_end(varargs);
ecl_return1(env, required1);
}
@end verbatim
The first thing to do is to declare the variable that will hold the arguments. This is @var{varargs} in our example and it has the type @code{ecl_va_list}.
This arguments list is initialized with the @code{ecl_va_start} macro, based on the supplied number of arguments, @var{narg}, the number of required arguments which are passed as ordinary C arguments (1 in this case), the last such ordinary arguments, @var{required}, and the buffer for the argument list, @var{varargs}.
Once @var{varargs} has been initialized, we can retrieve these values one by one using @code{ecl_va_arg}. Note that the returned value always has the type @code{cl_object}, for it is always a Common Lisp object.
The last statement before returning the output of the function is @code{ecl_va_end}. This macro performs any required cleanup and should never be omitted.
@end deftypefn
@cppindex ecl_nvalues
@cppindex ecl_nth_value
@deftypefun cl_object ecl_nvalues (cl_env_ptr @var{env});
@end deftypefun
@deftypefun cl_object ecl_nth_value (cl_env_ptr @var{env}, int @var{n});
Accessing output values
@subsubheading Description
Common Lisp functions may return zero, one or more values. In ECL, the first two cases do not require any special manipulation, as the C function returns either @code{NIL} or the first (zeroth) value directly. However, if one wishes to access additional values from a function, one needs to use these two macros or functions
@itemize
@item @code{ecl_nvalues(env)} returns the number of values that the function actually outputs. The single argument is the lisp environment. This value is larger or equal to 0 and smaller than @code{ECL_MULTIPLE_VALUES_LIMIT}.
@item Once we know the number of return values, they can be directly accessed using the function @code{ecl_nth_value(env,n)}, where @var{n} is a number larger than or equal to 1, and smaller than @code{ECL_MULTIPLE_VALUES_LIMIT}, which must correspond to a valid output value. No checking is done.
@end itemize
Note that in both cases these macros and functions have to be used right after the Lisp function was called. This is so because other Lisp functions might destroy the content of the return stack.
@subsubheading Example
A C/C++ excerpt:
@verbatim
cl_env_ptr env = ecl_process_env();
cl_object a = ecl_make_fixnum(13);
cl_object b = ecl_make_fixnum(6);
cl_object modulus = cl_floor(2, a, b);
cl_object remainder = ecl_nth_value(env, 1);
@end verbatim
The somewhat equivalent Common Lisp code:
@verbatim
(multiple-value-bind (modulus equivalent)
(floor 13 6))
@end verbatim
@end deftypefun
@cppindex ecl_return0
@cppindex ecl_return1
@cppindex ecl_return2
@cppindex ecl_return3
@defun ecl_return0 (cl_env_ptr @var{cl_env});
@end defun
@defun ecl_return1 (cl_env_ptr @var{cl_env}, cl_object @var{value1});
@end defun
@defun ecl_return2 (cl_env_ptr @var{cl_env}, cl_object @var{value1}, cl_object @var{value2});
@end defun
@defun ecl_return3 (cl_env_ptr @var{cl_env}, cl_object @var{value1}, cl_object @var{value2}, cl_object @var{value3});
Returning multiple values
@subsubheading Description
Returns @var{N} values from a C/C++ function in a way that a Common Lisp function can recognize and use them. The 0-th value is returned directly, while values 1 to N are stored in the Common Lisp environment @var{cl_env}. This macro has to be used from a function which returns an object of type @code{cl_object}.
@end defun
@cppindex ECL_BLOCK_BEGIN
@deffn Macro ECL_BLOCK_BEGIN
@verbatim
ECL_BLOCK_BEGIN(env,code) {
} ECL_BLOCK_END;
@end verbatim
@subsubheading Description
@code{ECL_BLOCK_BEGIN} establishes a block named @var{code} that becomes visible for the Common Lisp code. This block can be used then as a target for @code{cl_return}.
@var{env} must be the value of the current Common Lisp environment, obtained with @code{ecl_process_env}.
The C/C++ program has to ensure that the code in @code{ECL_BLOCK_END} gets executed, avoiding a direct exit of the block via @code{goto} or a C/C++ return.
@end deffn
@cppindex ECL_CATCH_BEGIN
@deffn Macro ECL_CATCH_BEGIN
@verbatim
ECL_CATCH_BEGIN(env,tag) {
} ECL_CATCH_END;
@end verbatim
@subsubheading Description
@code{ECL_CATCH_BEGIN} establishes a destination for @code{throw} with the code given by @var{tag}.
@var{env} must be the value of the current Common Lisp environment, obtained with @code{ecl_process_env}.
The C/C++ program has to ensure that the code in @code{ECL_CATCH_END} gets executed, avoiding a direct exit of the catch block via goto or a C/C++ return.
@end deffn
@cppindex ECL_UNWIND_PROTECT_BEGIN
@deffn Macro ECL_UNWIND_PROTECT_BEGIN
C macro for unwind-protect
@subsubheading Synopsis
@verbatim
ECL_UNWIND_PROTECT_BEGIN(env) {
} ECL_UNWIND_PROTECT_EXIT {
} ECL_UNWIND_PROTECT_END;
@end verbatim
@subsubheading Description
@code{ECL_UNWIND_PROTECT_BEGIN} establishes two blocks of C code that work like the equivalent ones in Common Lisp: a protected block, contained between the "BEGIN" and the "EXIT" statement, and the exit block, appearing immediately afterwards. The form guarantees that the exit block is always executed, even if the protected block attempts to exit via som nonlocal jump construct (@code{throw}, @code{return}, etc).
@var{env} must be the value of the current Common Lisp environment, obtained with @code{ecl_process_env}.
The utility of this construct is limited, for it only protects against nonlocal exits caused by Common Lisp constructs: it does not interfere with C @code{goto}, @code{return} or with C++ exceptions.
@end deffn
@subsubsection ANSI Dictionary
Common Lisp and C equivalence
@subsubheading Synopsis
@multitable @columnfractions .3 .7
@headitem Lisp symbol @tab C function or constant
@item @clhs{f_apply.htm,apply} @tab cl_object cl_apply(cl_narg narg, cl_object function, ...)
@item @clhs{v_call_a.htm,call-arguments-limit} @tab ECL_CALL_ARGUMENTS_LIMIT
@item @clhs{f_cmpd_f.htm,compiled-function-p} @tab cl_object cl_compiled_function_p(cl_object object)
@item @clhs{f_comple.htm,complement} @tab cl_object cl_complement(cl_object function)
@item @clhs{f_cons_1.htm,constantly} @tab cl_object cl_constantly(cl_object value)
@item @clhs{f_everyc.htm,every} @tab cl_object cl_every(cl_narg narg, cl_object predicate, ...)
@item @clhs{f_eq.htm,eq} @tab cl_object cl_eq(cl_object x, cl_object y)
@item @clhs{f_eql.htm,eql} @tab cl_object cl_eql(cl_object x, cl_object y)
@item @clhs{f_equal.htm,equal} @tab cl_object cl_equal(cl_object x, cl_object y)
@item @clhs{f_equalp.htm,equalp} @tab cl_object cl_equalp(cl_object x, cl_object y)
@item @clhs{f_fbound.htm,fboundp} @tab cl_object cl_fboundp(cl_object function_name)
@item @clhs{f_fdefin.htm,fdefinition} @tab cl_object cl_fdefinition(cl_object function_name)
@item @clhs{f_fmakun.htm,fmakunbound} @tab cl_object cl_fmakunbound(cl_object function_name)
@item @clhs{f_funcal.htm,funcall} @tab cl_object cl_funcall(cl_narg narg, cl_object function, ...)
@item @clhs{f_fn_lam.htm,function-lambda-expression} @tab cl_object cl_function_lambda_expression(cl_object function)
@item @clhs{f_fnp.htm,functionp} @tab cl_object cl_functionp(cl_object object)
@item @clhs{f_get_se.htm,get-setf-expansion} @tab cl_object cl_get_setf_expansion(cl_narg narg, cl_object place, ...)
@item @clhs{f_identi.htm,identity} @tab cl_object cl_identity(cl_object x)
@item @clhs{s_let_l.htm,LET}, @clhs{s_let_l.htm,LET*} @tab cl_object ecl_bds_bind(cl_env_ptr env, cl_object symbol, cl_object value)
@item @clhs{v_lamb_1.htm,lambda-parameters-limit} @tab ECL_LAMBDA_PARAMETERS_LIMIT
@item @clhs{v_multip.htm,multiple-values-limit} @tab ECL_MULTIPLE_VALUES_LIMIT
@item @clhs{f_not.htm,not} @tab cl_object cl_not(cl_object object)
@item @clhs{f_everyc.htm,notevery} @tab cl_object cl_notevery(cl_narg narg, cl_object predicate, ...)
@item @clhs{f_everyc.htm,notany} @tab cl_object cl_notany(cl_narg narg, cl_object predicate, ...)
@item @clhs{f_set.htm,set} @tab cl_object cl_set(cl_object symbol, cl_object value)
@item @clhs{s_setq.htm,setq} @tab cl_object ecl_setq(cl_env_ptr env, cl_object symbol, cl_object value)
@item @clhs{f_symb_5.htm,symbol-value} @tab cl_object ecl_symbol_value(cl_env_ptr env, cl_object symbol)
@item @clhs{f_everyc.htm,some} @tab cl_object cl_some(cl_narg narg, cl_object predicate, ...)
@item @clhs{f_vals_l.htm,values-list} @tab cl_object cl_values_list(cl_object list)
@end multitable

View file

@ -3,6 +3,8 @@
@node Environment - Dictionary
@subsection Dictionary
@lspindex disassemble
@lspindex trace
@defun disassemble function-designator*
Display the assembly code of a function
@ -12,7 +14,7 @@ Display the assembly code of a function
A symbol which is bound to a function in the global environment, or a lambda form
@end table
@subsubheading Description
As specified in ANSI (@xref{Bibliography}) this function outputs the internal represention of a compiled function, or of a lambda form, as it would look after being compiled.
As specified in ANSI @bibcite{ANSI} this function outputs the internal represention of a compiled function, or of a lambda form, as it would look after being compiled.
ECL only has a particular difference: it has two different compilers, one based on bytecodes and one based on the C language. The output will thus depend on the arguments and on which compiler is active at the moment in which this function is run.
@ -23,7 +25,7 @@ ECL only has a particular difference: it has two different compilers, one based
@end itemize
@end defun
@deffn Macro trace function-name*
@defmac trace function-name*
Follow the execution of functions
@subsubheading Synopsis
(trace @var{function-name*})
@ -60,7 +62,7 @@ If specified, and @var{form} evaluates to true, then the debugger is invoked at
@item :print, :print-after
In addition to the usual printout, the result of evaluating @var{form} is printed at the start of the function or at the end of the function, depending on the option. Multiple print options cause multiple values to be output, in the order in which they were introduced.
@end table
@end deffn
@end defmac
@node Environment - C Reference
@subsection C Reference

View file

@ -3,7 +3,7 @@
@node Filenames - Syntax
@subsection Syntax
A pathname in the file system of Common-Lisp consists of six elements: host, device, directory, name, type and version. Pathnames are read and printed using the @code{#P} reader macro followed by the namestring. A namestring is a string which represents a pathname. The syntax of namestrings for logical pathnames is well explained in the ANSI (@xref{Bibliography}) and it can be roughly summarized as follows:
A pathname in the file system of Common-Lisp consists of six elements: host, device, directory, name, type and version. Pathnames are read and printed using the @code{#P} reader macro followed by the namestring. A namestring is a string which represents a pathname. The syntax of namestrings for logical pathnames is well explained in the ANSI @bibcite{ANSI} and it can be roughly summarized as follows:
@verbatim
[hostname:][;][directory-item;]0 or more[name][.type[.version]]

View file

@ -5,7 +5,7 @@
@subsection Dictionary
@subsubsection @code{DIRECTORY}
This function does not have any additional arguments other than the ones described in ANSI (@xref{Bibliography}). To list files and directories, it follows the rules for matching pathnames described in @ref{Filenames - Wild pathnames and matching}. In short, you have the following practical examples:
This function does not have any additional arguments other than the ones described in ANSI @bibcite{ANSI}. To list files and directories, it follows the rules for matching pathnames described in @ref{Filenames - Wild pathnames and matching}. In short, you have the following practical examples:
@float Table, tab:examples-using-directory
@caption{Examples of using @code{DIRECTORY}}

View file

@ -33,7 +33,7 @@ The @code{#$} macro can be used to initialize the generator with a random seed (
@node Numbers - C Reference
@subsection C Reference
@node Numbers - Number C types
@subsubsection Number C types
Numeric C types understood by ECL
@ -76,6 +76,7 @@ Check for the definition of C macros with a similar name, shown in the fifth col
In Lisp code, check for the presence of the associated features, shown in the fourth column above.
@end itemize
@node Numbers - Number constructors
@subsubsection Number constructors
Creating Lisp types from C numbers
@ -138,6 +139,7 @@ Note also that some of the constructors do not use C numbers. This is the case o
These functions or macros signal no errors.
@node Numbers - Number accessors
@subsubsection Number accessors
Unchecked conversion from Lisp types to C numbers
@ -154,6 +156,7 @@ Unchecked conversion from Lisp types to C numbers
@subsubheading Description
These functions and macros extract a C number from a Lisp object. They do not check the type of the Lisp object as they typically just access directly the value from a C structure.
@node Numbers - Number coercion
@subsubsection Number coercion
Checked conversion from Lisp types to C numbers
@ -206,6 +209,7 @@ Checked conversion from Lisp types to C numbers
@subsubheading Description
These functions and macros convert a Lisp object to the corresponding C number type. The conversion is done through a coercion process which may signal an error if the argument does not fit the expected type.
@node Numbers - Numbers C dictionary
@subsubsection Numbers C dictionary
Common Lisp and C equivalence

View file

@ -1,7 +1,7 @@
@node Printer
@section Printer
In all situations where the rules are well specified, ECL prints objects according to ANSI (@xref{Bibliography}). The specification leaves however a number of cases as implementation dependent behavior. The output of ECL in those cases is summarized in @ref{tab:impl-spec-print-rep}. Except for the types @code{character} and @code{random-state}, most of those examples regard non-standard written forms @code{#<...>} cannot be read back using @code{read}. These printed representations are just informative and should not be used to reconstruct or compare objects.
In all situations where the rules are well specified, ECL prints objects according to ANSI @bibcite{ANSI}. The specification leaves however a number of cases as implementation dependent behavior. The output of ECL in those cases is summarized in @ref{tab:impl-spec-print-rep}. Except for the types @code{character} and @code{random-state}, most of those examples regard non-standard written forms @code{#<...>} cannot be read back using @code{read}. These printed representations are just informative and should not be used to reconstruct or compare objects.
@float Table, tab:impl-spec-print-rep
@caption{Implementation-specific printed representation}

View file

@ -6,10 +6,13 @@
@node Streams - Supported types
@subsubsection Supported types
ECL implements all stream types described in ANSI (@xref{Bibliography}). Additionally, when configured with option @code{--enable-clos-streams}, ECL includes a version of Gray streams where any object that implements the appropiate methods (@code{stream-input-p}, @code{stream-read-char}, etc) is a valid argument for the functions that expect streams, such as @code{read}, @code{print}, etc.
ECL implements all stream types described in ANSI @bibcite{ANSI}. Additionally, when configured with option @code{--enable-clos-streams}, ECL includes a version of Gray streams where any object that implements the appropiate methods (@code{stream-input-p}, @code{stream-read-char}, etc) is a valid argument for the functions that expect streams, such as @code{read}, @code{print}, etc.
@node Streams - Element types
@subsubsection Element types
@lspindex write-char
@lspindex write-sequence
@lspindex read-char
ECL distinguishes between two kinds of streams: character streams and byte streams. @dfn{Character streams} only accept and produce characters, written or read one by one, with @code{write-char} or @code{read-char}, or in chunks, with @code{write-sequence} or any of the Lisp printer functions. Character operations are conditioned by the external format, as described in @ref{Streams - External formats}.
ANSI Common Lisp also supports binary streams. Here input and output is performed in chunks of bits. Binary streams are created with the function open passing as argument a subtype of integer and the implementation is free to round up that integer type to the closest size it supports. In particular ECL rounds up the size to a multiple of a byte. For example, the form @code{(open "foo.bin" :direction :output :element-type '(unsigned-byte 13))}, will open the file @code{foo.bin} for writing, using 16-bit words as the element type.

View file

@ -21,17 +21,22 @@ It is important to remember that strings with unicode characters can only be pri
@node Strings - C reference
@subsection C reference
@subsubsection Base string constructors
@cppindex ecl_alloc_adjustable_base_string
@cppindex ecl_alloc_adjustable_simple_string
@cppindex ecl_make_simple_base_string
@cppindex ecl_make_constant_base_string
Building strings of C data
@subsubheading Functions
@deftypefun cl_object ecl_alloc_adjustable_base_string (cl_index @var{length});
@end deftypefun
@deftypefun cl_object ecl_alloc_adjustable_simple_string( cl_index @var{length});
@deftypefun cl_object ecl_alloc_adjustable_simple_string (cl_index @var{length});
@end deftypefun
@deftypefun cl_object ecl_make_simple_base_string( ecl_base_char* @var{data}, cl_index @var{length});
@deftypefun cl_object ecl_make_simple_base_string (ecl_base_char* @var{data}, cl_index @var{length});
@end deftypefun
@deftypefun cl_object ecl_make_constant_base_string( ecl_base_char* @var{data}, cl_index @var{length});
@deftypefun cl_object ecl_make_constant_base_string (ecl_base_char* @var{data}, cl_index @var{length});
@end deftypefun
@subsubheading Description
@ -44,6 +49,8 @@ These are different ways to create a base string, which is a string that holds a
The other constructors create strings but use some preexisting data. @code{ecl_make_simple_base_string} creates a string copying the data that the user supplies, and using freshly allocated memory. @code{ecl_make_constant_base_string} on the other hand, does not allocate memory, but simply uses the supplied pointer as buffer for the string. This last function should be used with care, ensuring that the supplied buffer is not deallocated.
@subsubsection String accessors
@cppindex ecl_char
@cppindex ecl_char_set
Reading and writing characters into a string
@subsubheading Functions

View file

@ -4,6 +4,8 @@
There are no implementation-specific limits on the size or content of symbol names. It is however not allowed to write on the strings which have been passed to @code{#'make-symbol} or returned from @code{#'symbol-name}.
@subsection C Reference
@cppindex ecl_make_keyword
@cppindex ecl_make_symbol
@deftypefun cl_object ecl_make_keyword (char * @var{name});
Find a lisp keyword

View file

@ -1,5 +1,7 @@
@node Types and classes
@section Types and classes
@lspindex single-float
@lspindex double-float
ECL defines the following additional built-in classes in the @code{CL} package:
@ -7,3 +9,19 @@ ECL defines the following additional built-in classes in the @code{CL} package:
@item @code{single-float}
@item @code{double-float}
@end itemize
@subsection C Reference
@subsubsection ANSI Dictionary
Common Lisp and C equivalence
@subsubheading Synopsis
@multitable @columnfractions .3 .7
@headitem Lisp symbol @tab C function
@item @clhs{f_coerce.htm,coerce} @tab cl_object cl_coerce(cl_object object, cl_object result_type)
@item @clhs{f_subtpp.htm,subtypep} @tab cl_object cl_subtypep(cl_narg narg, cl_object type1, cl_object type2, ...)
@item @clhs{f_tp_of.htm,type-of} @tab cl_object cl_type_of(cl_object object)
@item @clhs{f_typep.htm,typep} @tab cl_object cl_typep(cl_narg narg, cl_object object, cl_object type_specifier, ...)
@item @clhs{f_tp_err.htm,type-error-datum} @tab [Only in Common Lisp]
@item @clhs{f_tp_err.htm,type-error-expected-type} @tab [Only in Common Lisp]
@end multitable

View file

@ -1,2 +1,209 @@
@node Embedding ECL
@section Embedding ECL
@c @node Embedding ECL - Introduction
@c @subsection Introduction
@node Embedding ECL - Embedding Reference
@subsection Embedding Reference
@cppindex CL_CATCH_ALL
@defmac CL_CATCH_ALL
Create a protected region.
@subsubheading C Macro
@verbatim
cl_env_ptr env = ecl_process_env();
CL_CATCH_ALL_BEGIN(env) {
/*
* Code that is protected. Uncaught lisp conditions, THROW,
* signals such as SIGSEGV and SIGBUS may cause jump to
* this region.
*/
} CL_CATCH_ALL_IF_CAUGHT {
/*
* If the exception, lisp condition or other control transfer
* is caught, this code is executed.
*/
} CL_CATCH_ALL_END
/*
* In all cases we exit here.
*/
@end verbatim
@subsubheading Description
This is a set of three macros that create an @code{UNWIND-PROTECT} region that prevents any nonlocal transfer of control to outer loops. In the Lisp speak, the previous code is equivalent to
@verbatim
(block nil
(unwind-protect
(progn
;; Code that is protected
)
(return nil)))
@end verbatim
As explained in @code{CL_UNWIND_PROTECT},it is normally advisable to set up an unwind-protect frame to avoid the embedded lisp code to perform arbitary transfers of control.
@subsubheading See also
@code{CL_UNWIND_PROTECT}
@end defmac
@cppindex CL_UNWIND_PROTECT
@defmac CL_UNWIND_PROTECT
Create a protected region.
@subsubheading C Macro
@verbatim
cl_env_ptr env = ecl_process_env();
CL_UNWIND_PROTECT_BEGIN(env) {
/*
* Code that is protected. Uncaught lisp conditions, THROW,
* signals such as SIGSEGV and SIGBUS may cause jump to
* this region.
*/
} CL_UNWIND_PROTECT_EXIT {
/*
* If the exception, lisp condition or other control transfer
* is caught, this code is executed. After this code, the
* process will jump to the original destination of the
* THROW, GOTO or other control statement that was interrupted.
*/
} CL_UNWIND_PROTECT_END
/*
* We only exit here if NO nonlocal jump was interrupted.
*/
@end verbatim
@subsubheading Description
When embedding ECL it is normally advisable to set up an unwind-protect frame to avoid the embedded lisp code to perform arbitary transfers of control. Furthermore, the unwind protect form will be used in at least in the following ocasions:
@itemize
@item In a normal program exit, caused by @code{ext:quit}, ECL unwinds up to the outermost frame, which may be an @code{CL_CATCH_ALL} or @code{CL_UNWIND_PROTECT} macro.
@end itemize
Besides this, normal mechanisms for exit, such as ext:quit, and uncaught exceptions, such as serious signals (@xref{Signals and Interrupts - Synchronous signals}), are best handled using unwind-protect blocks.
@subsubheading See also
@code{CL_CATCH_ALL}
@end defmac
@cppindex cl_boot
@deftypefun int cl_boot (int @var{argc}, char **@var{argv});
Setup the lisp environment.
@table @var
@item argc,
An integer with the number of arguments to this program.
@item argv
A vector of strings with the arguments to this program.
@end table
@subsubheading Description
This function must be called before any other function from the ECL library, including the creation of any lisp object or evaluating any lisp code. The only exception are @code{ecl_set_option} and @code{ecl_get_option}.
@end deftypefun
@cppindex cl_shutdown
@deftypefun int cl_shutdown (void);
Close the lisp environment.
@subsubheading Description
This function must be called before exiting a program that uses the ECL environment. It performs some cleaning, including the execution of any finalizers, unloading shared libraries and deleting temporary files that were created by the compiler.
@end deftypefun
@deftypefun void ecl_set_option (int option, cl_fixnum value);
Set a boot option.
@table @var
@item option
An integer from @ref{tab:boot-options}.
@item value
A @code{cl_index} value for this option
@end table
@subsubheading Description
This functions sets the value of different options that have to be customized @emph{before} ECL boots. The table of options and default values [@ref{tab:boot-options}] shows that some of them are boolean, and some of them are unsigned integers.
We distinguish three sets of values. The first set determines whether ECL handles certain exceptions, such as access to forbidden regions of memory, interrupts via , floating point exceptions, etc.
The second set is related to the sizes of different stacks. Currently ECL uses four stacks: a bind stack for keeping assignments to special variables; a frame stack for implementing blocks, tagbodys and catch points; an interpreter stack for evaluating bytecodes, and finally the machine or C stack, of the computer we run in. We can set the expected size of these stacks, together with the size of a safety area which, if penetrated, will lead to the generation of a correctable error.
@float Table,tab:boot-options
@caption{Boot options for embedded ECL}
@multitable @columnfractions .3 .15 .16 .39
@headitem Name @code{(ECL_OPT_*)} @tab Type @tab Default @tab Description
@item @code{INCREMENTAL_GC} @tab boolean @tab @code{TRUE} @tab Activate generational garbage collector.
@item @code{TRAP_SIGSEGV} @tab boolean @tab @code{TRUE} @tab Capture @code{SIGSEGV} signals.
@item @code{TRAP_SIGFPE} @tab boolean @tab @code{TRUE} @tab Capture floating point exceptions.
@item @code{TRAP_SIGINT} @tab boolean @tab @code{TRUE} @tab Capture user interrupts.
@item @code{TRAP_SIGILL} @tab boolean @tab @code{TRUE} @tab Capture @code{SIGILL} exception.
@item @code{TRAP_INTERRUPT_SIGNAL} @tab boolean @tab @code{TRUE} @tab Capture the signal that implements @code{mp:interrupt-process}.
@item @code{SIGNAL_HANDLING_THREAD} @tab boolean @tab @code{TRUE} @tab Create a signal to capture and process asynchronous threads (@xref{Signals and Interrupts - Asynchronous signals}).
@item @code{BOOTED} @tab boolean @tab @code{TRUE}/@code{FALSE} @tab Has ECL booted (read only).
@item @code{BIND_STACK_SIZE} @tab cl_index @tab 8192 @tab Size of stack for binding special variables.
@item @code{BIND_STACK_SAFETY_AREA} @tab cl_index @tab 128 @tab
@item @code{FRAME_STACK_SIZE} @tab cl_index @tab 2048 @tab Size of stack for nonlocal jumps.
@item @code{FRAME_STACK_SAFETY_AREA} @tab cl_index @tab 128 @tab
@item @code{LISP_STACK_SIZE} @tab cl_index @tab 32768 @tab Size of interpreter stack.
@item @code{LISP_STACK_SAFETY_AREA} @tab cl_index @tab 128 @tab
@item @code{C_STACK_SIZE} @tab cl_index @tab 131072 @tab Size of C stack (not exact).
@item @code{C_STACK_SAFETY_AREA} @tab cl_index @tab 4192 @tab
@item @code{SIGALTSTACK_SIZE} @tab cl_index @tab 1 @tab If nonzero, run C signal handler in an alternative signal. A small value is automatically incremented.
@item @code{THREAD_INTERRUPT_SIGNAL} @tab unsigned int @tab 0 @tab If nonzero, specify the unix signal which is used to communicate different Lisp threads.
@end multitable
@end float
@end deftypefun
@cppindex ecl_get_option
@deftypefun cl_fixnum ecl_get_option (int @var{option});
Read the value of a boot option.
@table @var
@item option
An integer from @ref{tab:boot-options}.
@end table
@subsubheading Description
This functions reads the value of different options that have to be customized @emph{before} ECL boots. The table of options and default values is @ref{tab:boot-options}.
@end deftypefun
@cppindex ecl_clear_interrupts
@defmac ecl_clear_interrupts();
Clear all pending signals and exceptions.
@subsubheading Description
This macro clears all pending interrupts.
@subsubheading See also
@code{ecl_disable_interrupts} and @code{ecl_enable_interrupts}.
@end defmac
@cppindex ecl_disable_interrupts
@defmac ecl_disable_interrupts();
Postpone handling of signals and exceptions.
@subsubheading Description
This macro sets a thread-local flag indicating that all received signals should be queued for later processing.
@subsubheading See also
@code{ecl_enable_interrupts} and @code{ecl_clear_interrupts}.
@end defmac
@cppindex ecl_enable_interrupts
@defmac ecl_enable_interrupts();
Activate handling of signals and exceptions.
@subsubheading Description
This macro sets a thread-local flag indicating that all received signals can be handled. If there are any pending signals, they will be immediately processed.
@subsubheading See also
@code{ecl_disable_interrupts} and @code{ecl_clear_interrupts}.
@end defmac

View file

@ -48,10 +48,10 @@ Many nodes, moderate amount of content (deviations from the standard)
# - [ ] DFFI :: Dynamic FFI
- [X] UFFI
- [ ] Multithreading
- [ ] Signals and Interrupts
- [X] Signals and Interrupts
- [ ] Networking
- [X] Memory managament
- [ ] MOP
- [X] MOP
- [ ] Green threads
- [ ] Continuations
- [ ] Extensible Sequences