diff --git a/src/doc/new-doc/developer-guide/compiler.txi b/src/doc/new-doc/developer-guide/compiler.txi new file mode 100644 index 000000000..6c4af6962 --- /dev/null +++ b/src/doc/new-doc/developer-guide/compiler.txi @@ -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)) +# + +>(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 diff --git a/src/doc/new-doc/developer-guide/index.txi b/src/doc/new-doc/developer-guide/index.txi index f8064d1ac..be7829c80 100644 --- a/src/doc/new-doc/developer-guide/index.txi +++ b/src/doc/new-doc/developer-guide/index.txi @@ -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 diff --git a/src/doc/new-doc/extensions/index.txi b/src/doc/new-doc/extensions/index.txi index a31ff429f..2e25c6c4a 100644 --- a/src/doc/new-doc/extensions/index.txi +++ b/src/doc/new-doc/extensions/index.txi @@ -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 diff --git a/src/doc/new-doc/extensions/memory.txi b/src/doc/new-doc/extensions/memory.txi index 661f046c0..0dba2d044 100644 --- a/src/doc/new-doc/extensions/memory.txi +++ b/src/doc/new-doc/extensions/memory.txi @@ -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. diff --git a/src/doc/new-doc/extensions/mop.txi b/src/doc/new-doc/extensions/mop.txi new file mode 100644 index 000000000..f65fad60d --- /dev/null +++ b/src/doc/new-doc/extensions/mop.txi @@ -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 diff --git a/src/doc/new-doc/extensions/packages.txi b/src/doc/new-doc/extensions/packages.txi index 978dff9bb..c6f8b1368 100644 --- a/src/doc/new-doc/extensions/packages.txi +++ b/src/doc/new-doc/extensions/packages.txi @@ -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 diff --git a/src/doc/new-doc/extensions/signals.txi b/src/doc/new-doc/extensions/signals.txi new file mode 100644 index 000000000..980df082b --- /dev/null +++ b/src/doc/new-doc/extensions/signals.txi @@ -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 diff --git a/src/doc/new-doc/standards/arrays.txi b/src/doc/new-doc/standards/arrays.txi index 501ac24b9..0fac0e315 100644 --- a/src/doc/new-doc/standards/arrays.txi +++ b/src/doc/new-doc/standards/arrays.txi @@ -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 diff --git a/src/doc/new-doc/standards/characters.txi b/src/doc/new-doc/standards/characters.txi index 16aaa3d7e..d2b6e5e58 100644 --- a/src/doc/new-doc/standards/characters.txi +++ b/src/doc/new-doc/standards/characters.txi @@ -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 diff --git a/src/doc/new-doc/standards/conditions.txi b/src/doc/new-doc/standards/conditions.txi index 9041cc62d..98f5fd157 100644 --- a/src/doc/new-doc/standards/conditions.txi +++ b/src/doc/new-doc/standards/conditions.txi @@ -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} diff --git a/src/doc/new-doc/standards/data_and_control_flow.txi b/src/doc/new-doc/standards/data_and_control_flow.txi index 53d926377..dad07b8e2 100644 --- a/src/doc/new-doc/standards/data_and_control_flow.txi +++ b/src/doc/new-doc/standards/data_and_control_flow.txi @@ -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 +... +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 diff --git a/src/doc/new-doc/standards/environment.txi b/src/doc/new-doc/standards/environment.txi index 0aa23215f..07b103d30 100644 --- a/src/doc/new-doc/standards/environment.txi +++ b/src/doc/new-doc/standards/environment.txi @@ -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 diff --git a/src/doc/new-doc/standards/filenames.txi b/src/doc/new-doc/standards/filenames.txi index 7370b5a12..ed37a9619 100644 --- a/src/doc/new-doc/standards/filenames.txi +++ b/src/doc/new-doc/standards/filenames.txi @@ -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]] diff --git a/src/doc/new-doc/standards/files.txi b/src/doc/new-doc/standards/files.txi index 15ee1d282..42b07aa9f 100644 --- a/src/doc/new-doc/standards/files.txi +++ b/src/doc/new-doc/standards/files.txi @@ -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}} diff --git a/src/doc/new-doc/standards/numbers.txi b/src/doc/new-doc/standards/numbers.txi index d740b0a8f..c8d7d0566 100644 --- a/src/doc/new-doc/standards/numbers.txi +++ b/src/doc/new-doc/standards/numbers.txi @@ -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 diff --git a/src/doc/new-doc/standards/printer.txi b/src/doc/new-doc/standards/printer.txi index cd29859d7..463e9b3d1 100644 --- a/src/doc/new-doc/standards/printer.txi +++ b/src/doc/new-doc/standards/printer.txi @@ -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} diff --git a/src/doc/new-doc/standards/streams.txi b/src/doc/new-doc/standards/streams.txi index 340a89d60..ef18e221c 100644 --- a/src/doc/new-doc/standards/streams.txi +++ b/src/doc/new-doc/standards/streams.txi @@ -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. diff --git a/src/doc/new-doc/standards/strings.txi b/src/doc/new-doc/standards/strings.txi index 79c94713a..ffea53894 100644 --- a/src/doc/new-doc/standards/strings.txi +++ b/src/doc/new-doc/standards/strings.txi @@ -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 diff --git a/src/doc/new-doc/standards/symbols.txi b/src/doc/new-doc/standards/symbols.txi index ef036e0ac..26893aaa2 100644 --- a/src/doc/new-doc/standards/symbols.txi +++ b/src/doc/new-doc/standards/symbols.txi @@ -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 diff --git a/src/doc/new-doc/standards/types_and_classes.txi b/src/doc/new-doc/standards/types_and_classes.txi index d0970e37d..c9daec640 100644 --- a/src/doc/new-doc/standards/types_and_classes.txi +++ b/src/doc/new-doc/standards/types_and_classes.txi @@ -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 diff --git a/src/doc/new-doc/user-guide/embedding.txi b/src/doc/new-doc/user-guide/embedding.txi index 57ff63b51..20e1dcc55 100644 --- a/src/doc/new-doc/user-guide/embedding.txi +++ b/src/doc/new-doc/user-guide/embedding.txi @@ -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 diff --git a/src/doc/status.org b/src/doc/status.org index 186362706..ce9bde135 100644 --- a/src/doc/status.org +++ b/src/doc/status.org @@ -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