doc: cosmetic changes
Small improvements to css, correct indentation for examples.
This commit is contained in:
parent
3c3a02ea7d
commit
68b22e522c
11 changed files with 186 additions and 139 deletions
|
|
@ -32,14 +32,15 @@ The demerits are:
|
|||
|
||||
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
|
||||
@lisp
|
||||
(defvar *delta* 2)
|
||||
(defun add1 (x) (+ *delta* x))
|
||||
@end verbatim
|
||||
@end lisp
|
||||
|
||||
|
||||
The compiler generates the following intermediate C code.
|
||||
|
||||
@example
|
||||
@verbatim
|
||||
/* function definition for ADD1 */
|
||||
/* optimize speed 3, debug 0, space 0, safety 2 */
|
||||
|
|
@ -88,12 +89,13 @@ L2:;
|
|||
ecl_cmp_defun(VV[2]); /* ADD1 */
|
||||
}
|
||||
@end verbatim
|
||||
@end example
|
||||
|
||||
The C function @code{L1add1} implements the Lisp function @code{add1}. This relation is established by @code{ecl_cmp_defun} in the initialization function @code{init_fas_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}, while @code{VV[2]} holds the function object for @code{add1}, which is created during initialization of the module. @code{VM} in the definition of @code{L1add1} 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., 3 in this example. Thus the following macro definition is found in the H-file.
|
||||
|
||||
@verbatim
|
||||
@example
|
||||
#define VM 3
|
||||
@end verbatim
|
||||
@end example
|
||||
|
||||
@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.
|
||||
|
|
@ -106,16 +108,16 @@ Later, when the compiled closure is invoked, a pointer is set up to each lexical
|
|||
|
||||
Let us see an example. Suppose the following function has been compiled.
|
||||
|
||||
@verbatim
|
||||
@lisp
|
||||
(defun foo (x)
|
||||
(let ((a #'(lambda () (incf x)))
|
||||
(y x))
|
||||
(values a #'(lambda () (incf x y)))))
|
||||
@end verbatim
|
||||
@end lisp
|
||||
|
||||
@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
|
||||
@example
|
||||
>(multiple-value-setq (f g) (foo 10))
|
||||
#<compiled-closure nil>
|
||||
|
||||
|
|
@ -126,7 +128,7 @@ Let us see an example. Suppose the following function has been compiled.
|
|||
21
|
||||
|
||||
>
|
||||
@end verbatim
|
||||
@end example
|
||||
|
||||
After this, the two compiled closures look like:
|
||||
|
||||
|
|
@ -148,7 +150,7 @@ After this, the two compiled closures look like:
|
|||
@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
|
||||
@lisp
|
||||
(eval-when (:compile-toplevel)
|
||||
(proclaim '(ftype (function (fixnum fixnum) fixnum) tak))
|
||||
(proclaim '(optimize (speed 3) (debug 0) (safety 0))))
|
||||
|
|
@ -159,10 +161,11 @@ Declarations, especially type and function declarations, increase the efficiency
|
|||
y
|
||||
(tak (tak (1- x) y)
|
||||
(tak (1- y) x))))
|
||||
@end verbatim
|
||||
@end lisp
|
||||
|
||||
|
||||
The compiler generates the following C code (Note that the tail-recursive call of @code{TAK} was replaced by iteration):
|
||||
@example
|
||||
@verbatim
|
||||
/* function definition for TAK */
|
||||
/* optimize speed 3, debug 0, space 0, safety 0 */
|
||||
|
|
@ -198,6 +201,7 @@ L1:;
|
|||
goto TTL;
|
||||
}
|
||||
@end verbatim
|
||||
@end example
|
||||
|
||||
@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},
|
||||
|
|
@ -208,6 +212,7 @@ This is primary useful for debugging the compiler, ..\\
|
|||
|
||||
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.
|
||||
|
||||
@example
|
||||
@verbatim
|
||||
> (defun add1 (x) (1+ x))
|
||||
|
||||
|
|
@ -230,3 +235,4 @@ TTL:
|
|||
}
|
||||
}
|
||||
@end verbatim
|
||||
@end example
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ C-program is written to standard output.
|
|||
The function definition:
|
||||
|
||||
@exindex dpp: function definition
|
||||
@example
|
||||
@verbatim
|
||||
@(defun name ({var}*
|
||||
[&optional {var | (var [initform [svar]])}*]
|
||||
|
|
@ -38,6 +39,7 @@ The function definition:
|
|||
|
||||
} @)
|
||||
@end verbatim
|
||||
@end example
|
||||
|
||||
name is the name of the lisp function
|
||||
|
||||
|
|
@ -57,9 +59,11 @@ it should be surrounded by backquotes (`).
|
|||
|
||||
|
||||
Function return:
|
||||
@example
|
||||
@verbatim
|
||||
@(return {form}*);
|
||||
@end verbatim
|
||||
@end example
|
||||
|
||||
Return function expands into a lexical block @verb{|{}|}, so if it's
|
||||
used inside IF/ELSE, then it should be enclosed, even if we
|
||||
|
|
@ -68,16 +72,20 @@ instruction.
|
|||
|
||||
Symbols:
|
||||
|
||||
@example
|
||||
@verbatim
|
||||
@'name'
|
||||
@end verbatim
|
||||
@end example
|
||||
|
||||
Expands into a C statement, whole value is the given symbol
|
||||
from symbols_list.h
|
||||
|
||||
@example
|
||||
@verbatim
|
||||
@[name]
|
||||
@end verbatim
|
||||
@end example
|
||||
|
||||
Expands into a C statement, whole value is a fixnum
|
||||
corresponding to the index in the builtin symbols table of the
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ it returns the first one and the remaining ones are kept in a global
|
|||
To show the argument/value passing mechanism, here we list the actual
|
||||
code for the Common-Lisp function last.
|
||||
|
||||
@example
|
||||
@verbatim
|
||||
cl_object
|
||||
cl_last(cl_narg narg, cl_object l, ...)
|
||||
|
|
@ -58,6 +59,7 @@ cl_last(cl_narg narg, cl_object l, ...)
|
|||
return __value0;
|
||||
}
|
||||
@end verbatim
|
||||
@end example
|
||||
|
||||
ECL adopts the convention that the name of a function that implements
|
||||
a Common-Lisp function begins with a short package name (@code{cl} for
|
||||
|
|
@ -83,12 +85,14 @@ lisp representation of the statements that output values, and of the
|
|||
function definitions. For instance, the actual source code for
|
||||
@code{cl_last} in @code{src/c/list.d}
|
||||
|
||||
@example
|
||||
@verbatim
|
||||
@(defun last (l &optional (k ecl_make_fixnum(1)))
|
||||
@
|
||||
@(return ecl_last(l, ecl_to_size(k)));
|
||||
@)
|
||||
@end verbatim
|
||||
@end example
|
||||
|
||||
@node The lexical environment
|
||||
@subsection The lexical environment
|
||||
|
|
@ -133,73 +137,75 @@ after function invocation.
|
|||
|
||||
Let us see how these invocation records are used for debugging.
|
||||
|
||||
@example
|
||||
@verbatim
|
||||
> (defun fact (x) ;;; Wrong definition of the
|
||||
(if (= x 0) ;;; factorial function.
|
||||
one ;;; one should be 1.
|
||||
(* x (fact (1- x)))))
|
||||
FACT
|
||||
> (defun fact (x) ;;; Wrong definition of the
|
||||
(if (= x 0) ;;; factorial function.
|
||||
one ;;; one should be 1.
|
||||
(* x (fact (1- x)))))
|
||||
FACT
|
||||
|
||||
> (fact 3) ;;; Tries 3!
|
||||
Error: The variable ONE is unbound.
|
||||
Error signalled by IF.
|
||||
Broken at IF.
|
||||
>> :b ;;; Backtrace.
|
||||
Backtrace: eval > fact > if > fact > if > fact > if > fact > IF
|
||||
;;; Currently at the last IF.
|
||||
>> :h ;;; Help.
|
||||
> (fact 3) ;;; Tries 3!
|
||||
Error: The variable ONE is unbound.
|
||||
Error signalled by IF.
|
||||
Broken at IF.
|
||||
>> :b ;;; Backtrace.
|
||||
Backtrace: eval > fact > if > fact > if > fact > if > fact > IF
|
||||
;;; Currently at the last IF.
|
||||
>> :h ;;; Help.
|
||||
|
||||
Break commands:
|
||||
:q(uit) Return to some previous break level.
|
||||
:pop Pop to previous break level.
|
||||
:c(ontinue) Continue execution.
|
||||
:b(acktrace) Print backtrace.
|
||||
:f(unction) Show current function.
|
||||
:p(revious) Go to previous function.
|
||||
:n(ext) Go to next function.
|
||||
:g(o) Go to next function.
|
||||
:fs Search forward for function.
|
||||
:bs Search backward for function.
|
||||
:v(ariables) Show local variables, functions, blocks, and tags.
|
||||
:l(ocal) Return the nth local value on the stack.
|
||||
:hide Hide function.
|
||||
:unhide Unhide function.
|
||||
:hp Hide package.
|
||||
:unhp Unhide package.
|
||||
:unhide-all Unhide all variables and packages.
|
||||
:bds Show binding stack.
|
||||
:m(essage) Show error message.
|
||||
:hs Help stack.
|
||||
Top level commands:
|
||||
:cf Compile file.
|
||||
:exit or ^D Exit Lisp.
|
||||
:ld Load file.
|
||||
:step Single step form.
|
||||
:tr(ace) Trace function.
|
||||
:untr(ace) Untrace function.
|
||||
Break commands:
|
||||
:q(uit) Return to some previous break level.
|
||||
:pop Pop to previous break level.
|
||||
:c(ontinue) Continue execution.
|
||||
:b(acktrace) Print backtrace.
|
||||
:f(unction) Show current function.
|
||||
:p(revious) Go to previous function.
|
||||
:n(ext) Go to next function.
|
||||
:g(o) Go to next function.
|
||||
:fs Search forward for function.
|
||||
:bs Search backward for function.
|
||||
:v(ariables) Show local variables, functions, blocks, and tags.
|
||||
:l(ocal) Return the nth local value on the stack.
|
||||
:hide Hide function.
|
||||
:unhide Unhide function.
|
||||
:hp Hide package.
|
||||
:unhp Unhide package.
|
||||
:unhide-all Unhide all variables and packages.
|
||||
:bds Show binding stack.
|
||||
:m(essage) Show error message.
|
||||
:hs Help stack.
|
||||
Top level commands:
|
||||
:cf Compile file.
|
||||
:exit or ^D Exit Lisp.
|
||||
:ld Load file.
|
||||
:step Single step form.
|
||||
:tr(ace) Trace function.
|
||||
:untr(ace) Untrace function.
|
||||
|
||||
Help commands:
|
||||
:apropos Apropos.
|
||||
:doc(ument) Document.
|
||||
:h(elp) or ? Help. Type ":help help" for more information.
|
||||
Help commands:
|
||||
:apropos Apropos.
|
||||
:doc(ument) Document.
|
||||
:h(elp) or ? Help. Type ":help help" for more information.
|
||||
|
||||
>> :p ;;; Move to the last call of FACT.
|
||||
Broken at IF.
|
||||
>> :p ;;; Move to the last call of FACT.
|
||||
Broken at IF.
|
||||
|
||||
>> :b
|
||||
Backtrace: eval > fact > if > fact > if > fact > if > FACT > if
|
||||
;;; Now at the last FACT.
|
||||
>> :v ;;; The environment at the last call
|
||||
Local variables: ;;; to FACT is recovered.
|
||||
X: 0 ;;; X is the only bound variable.
|
||||
Block names: FACT. ;;; The block FACT is established.
|
||||
>> :b
|
||||
Backtrace: eval > fact > if > fact > if > fact > if > FACT > if
|
||||
;;; Now at the last FACT.
|
||||
>> :v ;;; The environment at the last call
|
||||
Local variables: ;;; to FACT is recovered.
|
||||
X: 0 ;;; X is the only bound variable.
|
||||
Block names: FACT. ;;; The block FACT is established.
|
||||
|
||||
>> x
|
||||
0 ;;; The value of x is 0.
|
||||
>> x
|
||||
0 ;;; The value of x is 0.
|
||||
|
||||
>>(return-from fact 1) ;;; Return from the last call of
|
||||
6 ;;; FACT with the value of 0.
|
||||
;;; The execution is resumed and
|
||||
> ;;; the value 6 is returned.
|
||||
;;; Again at the top-level loop.
|
||||
>>(return-from fact 1) ;;; Return from the last call of
|
||||
6 ;;; FACT with the value of 0.
|
||||
;;; The execution is resumed and
|
||||
> ;;; the value 6 is returned.
|
||||
;;; Again at the top-level loop.
|
||||
@end verbatim
|
||||
@end example
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
html { background: #FFF; }
|
||||
html { background: #FFF; }
|
||||
body {
|
||||
margin: 1em 125px 0 10%;
|
||||
line-height: 1.5em;
|
||||
padding: 0 2em 1em 2em;
|
||||
line-height: 1.5em;
|
||||
padding: 0 2em 1em 2em;
|
||||
background: #FFF;
|
||||
font: 12px Verdana,Arial, sans-serif
|
||||
}
|
||||
|
|
@ -19,10 +19,15 @@ th, td {
|
|||
h1, h2, h3, h4, h5 { background: #EEE; }
|
||||
code, pre {
|
||||
font-size: 1em;
|
||||
font-family: fixed;
|
||||
font-family: monospace;
|
||||
}
|
||||
code {
|
||||
background: #CDC;
|
||||
}
|
||||
pre.verbatim {
|
||||
margin: 0 0 0 0;
|
||||
}
|
||||
pre {
|
||||
line-height: 1em;
|
||||
overflow: auto;
|
||||
}
|
||||
pre.screen {
|
||||
|
|
@ -48,7 +53,7 @@ div.variablelist {
|
|||
padding: 0 2em;
|
||||
}
|
||||
.type, .funcsynopsis, .symbol {
|
||||
font-family: fixed;
|
||||
font-family: monospace;
|
||||
}
|
||||
.type, .symbol, .replaceable {
|
||||
white-space: nowrap;
|
||||
|
|
|
|||
|
|
@ -133,13 +133,13 @@ This macro is compatible with the one in SBCL and as such it also defines three
|
|||
|
||||
@code{mp:with-local-interrupts} executes its body with interrupts enabled provided that there is an @code{mp:allow-with-interrupts} for every @code{mp:without-interrupts} surrounding the current one. @code{mp:with-local-interrupts} is equivalent to:
|
||||
|
||||
@verbatim
|
||||
@lisp
|
||||
(allow-with-interrupts (with-interrupts ...))
|
||||
@end verbatim
|
||||
@end lisp
|
||||
|
||||
Care must be taken not to let either @code{mp:allow-with-interrupts} or @code{mp:with-local-interrupts} appear in a function that escapes from inside the @code{mp:without-interrupts} in:
|
||||
|
||||
@verbatim
|
||||
@lisp
|
||||
(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.
|
||||
|
|
@ -149,6 +149,6 @@ Care must be taken not to let either @code{mp:allow-with-interrupts} or @code{mp
|
|||
;; 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 lisp
|
||||
|
||||
@end defmac
|
||||
|
|
|
|||
|
|
@ -128,40 +128,40 @@ Finally, the function @code{si_make_array} does a similar job to @code{si_make_f
|
|||
|
||||
Create one-dimensional @code{base-string} with room for 11 characters:
|
||||
|
||||
@verbatim
|
||||
@example
|
||||
cl_object s = ecl_alloc_simple_vector(ecl_aet_bc, 11);
|
||||
@end verbatim
|
||||
@end example
|
||||
|
||||
Create a one-dimensional @code{array} with a fill pointer
|
||||
|
||||
@verbatim
|
||||
@example
|
||||
cl_object type = ecl_make_symbol("BYTE8","EXT");
|
||||
cl_object a = si_make_vector(ecl_make_fixnum(16), type, ECL_NIL, /* adjustable */
|
||||
ecl_make_fixnum(0) /* fill-pointer */,
|
||||
ECL_NIL /* displaced_to */,
|
||||
ECL_NIL /* displacement */);
|
||||
@end verbatim
|
||||
@end example
|
||||
|
||||
An alternative formulation
|
||||
|
||||
@verbatim
|
||||
@example
|
||||
cl_object type = ecl_make_symbol("BYTE8","EXT");
|
||||
cl_object a = si_make_array(ecl_make_fixnum(16), type, ECL_NIL, /* adjustable */
|
||||
ecl_make_fixnum(0) /* fill-pointer */,
|
||||
ECL_NIL /* displaced_to */,
|
||||
ECL_NIL /* displacement */);
|
||||
@end verbatim
|
||||
@end example
|
||||
|
||||
Create a 2-by-3 two-dimensional @code{array}, specialized for an integer type:
|
||||
|
||||
@verbatim
|
||||
@example
|
||||
cl_object dims = cl_list(2, ecl_make_fixnum(2), ecl_make_fixnum(3));
|
||||
cl_object type = ecl_make_symbol("BYTE8","EXT");
|
||||
cl_object a = si_make_array(dims, type, ECL_NIL, /* adjustable */
|
||||
ECL_NIL /* fill-pointer */,
|
||||
ECL_NIL /* displaced_to */,
|
||||
ECL_NIL /* displacement */);
|
||||
@end verbatim
|
||||
@end example
|
||||
|
||||
@subsubsection Accessors
|
||||
@cppindex ecl_aref
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
@deffn Macro ECL_HANDLER_CASE
|
||||
C macro for @clhs{m_hand_1.htm,handler-case}
|
||||
@subsubheading Synopsis
|
||||
@example
|
||||
@verbatim
|
||||
ECL_HANDLER_CASE_BEGIN(env,names) {
|
||||
|
||||
|
|
@ -15,6 +16,7 @@ ECL_HANDLER_CASE_BEGIN(env,names) {
|
|||
|
||||
} ECL_HANDLER_CASE_END;
|
||||
@end verbatim
|
||||
@end example
|
||||
|
||||
@subsubheading Description
|
||||
@code{ECL_HANDLER_CASE_BEGIN} runs a block of C code with a set of error handlers bound to the names given by the list @var{names}. The subsequent @code{ECL_HANDLER_CASE} statements specify what to do when the @var{n}-th type of conditions is found, where @var{n} is an integer denoting the position of the name in the list @var{names}.
|
||||
|
|
@ -23,6 +25,7 @@ When a condition is signaled, ECL scans the list of signal handlers, looking for
|
|||
|
||||
The following example shows how to establish a handler for @code{ERROR} conditions. Note how the first value to @code{ECL_HANDLER_CASE} matches the position of the condition name in the list:
|
||||
|
||||
@example
|
||||
@verbatim
|
||||
cl_object error = ecl_make_symbol("ERROR","CL");
|
||||
ECL_HANDLER_CASE_BEGIN(the_env, ecl_list1(error)) {
|
||||
|
|
@ -34,6 +37,7 @@ ECL_HANDLER_CASE_BEGIN(the_env, ecl_list1(error)) {
|
|||
output = condition;
|
||||
} ECL_HANDLER_CASE_END;
|
||||
@end verbatim
|
||||
@end example
|
||||
|
||||
@end deffn
|
||||
|
||||
|
|
@ -41,6 +45,7 @@ ECL_HANDLER_CASE_BEGIN(the_env, ecl_list1(error)) {
|
|||
@deffn Macro ECL_RESTART_CASE
|
||||
C macro for @clhs{m_rst_ca.htm,restart-case}
|
||||
@subsubheading Synopsis
|
||||
@example
|
||||
@verbatim
|
||||
ECL_RESTART_CASE_BEGIN(env,names) {
|
||||
|
||||
|
|
@ -48,6 +53,7 @@ ECL_RESTART_CASE_BEGIN(env,names) {
|
|||
|
||||
} ECL_RESTART_CASE_END;
|
||||
@end verbatim
|
||||
@end example
|
||||
|
||||
@subsubheading Description
|
||||
@code{ECL_RESTART_CASE_BEGIN} runs a block of C code with a set of restarts bound to the names given by the list @var{names}. The subsequent @code{ECL_RESTART_CASE} statements specify what to do when the @var{n}-th restart is invoked, where @var{n} is an integer denoting the position of the name in the list @var{names}.
|
||||
|
|
@ -56,6 +62,7 @@ When the restart is invoked, it can receive any number of arguments, which are g
|
|||
|
||||
The following example shows how to establish an @var{ABORT} and a @var{USE-VALUE} restart. Note how the first value to @var{ECL_RESTART_CASE} matches the position of the restart name in the list:
|
||||
|
||||
@example
|
||||
@verbatim
|
||||
cl_object abort = ecl_make_symbol("ABORT","CL");
|
||||
cl_object use_value = ecl_make_symbol("USE-VALUE","CL");
|
||||
|
|
@ -70,6 +77,7 @@ ECL_RESTART_CASE_BEGIN(the_env, cl_list(2, abort, use_value)) {
|
|||
output = ECL_CAR(args);
|
||||
} ECL_RESTART_CASE_END;
|
||||
@end verbatim
|
||||
@end example
|
||||
@end deffn
|
||||
|
||||
@subsubsection ANSI dictionary
|
||||
|
|
|
|||
|
|
@ -11,21 +11,21 @@
|
|||
|
||||
@node Shadowed bindings
|
||||
@subsection Shadowed bindings
|
||||
@cindex Shadowed bindings in LET, FLET, LABELS and lambda-list
|
||||
ANSI doesn't specify what should happen if any of the @code{LET},
|
||||
@code{FLET} and @code{LABELS} special operators contain many bindings
|
||||
@cindex Shadowed bindings in let, flet, labels and lambda-list
|
||||
ANSI doesn't specify what should happen if any of the @code{let},
|
||||
@code{flet} and @code{labels} special operators contain many bindings
|
||||
sharing the same name. Because the behavior varies between the
|
||||
implementations and the programmer can't rely on the spec ECL signals an
|
||||
error if such situation occur.
|
||||
|
||||
Moreover, while ANSI defines lambda list parameters in the terms of
|
||||
@code{LET*}, when used in function context programmer can't provide an
|
||||
@code{let*}, when used in function context programmer can't provide an
|
||||
initialization forms for required parameters. If required parameters
|
||||
share the same name an error is signaled.
|
||||
|
||||
Described behavior is present in ECL since version 16.0.0. Previously
|
||||
the @code{LET} operator were using first binding. Both @code{FLET} and
|
||||
@code{LABELS} were signaling an error if C compiler was used and used
|
||||
the @code{let} operator were using first binding. Both @code{flet} and
|
||||
@code{labels} were signaling an error if C compiler was used and used
|
||||
the last binding as a visible one when the byte compiler was used.
|
||||
|
||||
@node Minimal compilation
|
||||
|
|
@ -156,27 +156,27 @@ The previous conventions set some burden on the C programmer that calls ECL, for
|
|||
|
||||
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
|
||||
@example
|
||||
#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
|
||||
@end example
|
||||
|
||||
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 - ANSI 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
|
||||
@example
|
||||
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
|
||||
@end example
|
||||
|
||||
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
|
||||
@example
|
||||
/* Symbol + in package CL */
|
||||
cl_object plus = ecl_make_symbol("+","CL");
|
||||
cl_object one = ecl_make_fixnum(1);
|
||||
|
|
@ -184,7 +184,7 @@ 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
|
||||
@end example
|
||||
|
||||
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.
|
||||
|
||||
|
|
@ -265,6 +265,7 @@ 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
|
||||
|
||||
@example
|
||||
@verbatim
|
||||
cl_object my_plus(cl_narg narg, cl_object required1, ...)
|
||||
{
|
||||
|
|
@ -280,6 +281,7 @@ cl_object my_plus(cl_narg narg, cl_object required1, ...)
|
|||
ecl_return1(env, required1);
|
||||
}
|
||||
@end verbatim
|
||||
@end example
|
||||
|
||||
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}.
|
||||
|
||||
|
|
@ -312,20 +314,20 @@ Note that in both cases these macros and functions have to be used right after t
|
|||
@subsubheading Example
|
||||
A C/C++ excerpt:
|
||||
|
||||
@verbatim
|
||||
@example
|
||||
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
|
||||
@end example
|
||||
|
||||
The somewhat equivalent Common Lisp code:
|
||||
|
||||
@verbatim
|
||||
@lisp
|
||||
(multiple-value-bind (modulus equivalent)
|
||||
(floor 13 6))
|
||||
@end verbatim
|
||||
@end lisp
|
||||
|
||||
@end deftypefun
|
||||
|
||||
|
|
@ -351,11 +353,13 @@ Returns @var{N} values from a C/C++ function in a way that a Common Lisp functio
|
|||
|
||||
@cppindex ECL_BLOCK_BEGIN
|
||||
@deffn Macro ECL_BLOCK_BEGIN
|
||||
@example
|
||||
@verbatim
|
||||
ECL_BLOCK_BEGIN(env,code) {
|
||||
|
||||
} ECL_BLOCK_END;
|
||||
@end verbatim
|
||||
@end example
|
||||
|
||||
@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}.
|
||||
|
|
@ -368,11 +372,13 @@ The C/C++ program has to ensure that the code in @code{ECL_BLOCK_END} gets execu
|
|||
|
||||
@cppindex ECL_CATCH_BEGIN
|
||||
@deffn Macro ECL_CATCH_BEGIN
|
||||
@example
|
||||
@verbatim
|
||||
ECL_CATCH_BEGIN(env,tag) {
|
||||
|
||||
} ECL_CATCH_END;
|
||||
@end verbatim
|
||||
@end example
|
||||
|
||||
@subsubheading Description
|
||||
@code{ECL_CATCH_BEGIN} establishes a destination for @code{throw} with the code given by @var{tag}.
|
||||
|
|
@ -388,6 +394,7 @@ The C/C++ program has to ensure that the code in @code{ECL_CATCH_END} gets execu
|
|||
C macro for unwind-protect
|
||||
|
||||
@subsubheading Synopsis
|
||||
@example
|
||||
@verbatim
|
||||
ECL_UNWIND_PROTECT_BEGIN(env) {
|
||||
|
||||
|
|
@ -395,6 +402,7 @@ ECL_UNWIND_PROTECT_BEGIN(env) {
|
|||
|
||||
} ECL_UNWIND_PROTECT_END;
|
||||
@end verbatim
|
||||
@end example
|
||||
|
||||
@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 some nonlocal jump construct (@code{throw}, @code{return}, etc).
|
||||
|
|
|
|||
|
|
@ -168,6 +168,7 @@ In most of those cases there exist straightforward alternatives using
|
|||
the constructs and functions in ECL. For example, @code{unwind-protect}
|
||||
can be implemented using a C macro which is provided by ECL
|
||||
|
||||
@example
|
||||
@verbatim
|
||||
cl_env_ptr env = ecl_process_env();
|
||||
CL_UNWIND_PROTECT_BEGIN(env) {
|
||||
|
|
@ -176,6 +177,7 @@ CL_UNWIND_PROTECT_BEGIN(env) {
|
|||
/* exit code goes here */
|
||||
} CL_UNWIND_PROTECT_END;
|
||||
@end verbatim
|
||||
@end example
|
||||
|
||||
Common Lisp generic functions can be directly accessed using
|
||||
@code{funcall} or @code{apply} and the function name, as shown in the
|
||||
|
|
|
|||
|
|
@ -22,13 +22,13 @@ Many Lisp functions take keyword arguments. When invoking a function with keywor
|
|||
@subsubheading Example
|
||||
The following example converts a section of a string to uppercase characters:
|
||||
|
||||
@verbatim
|
||||
@example
|
||||
cl_object start = ecl_make_keyword("START");
|
||||
cl_object end = ecl_make_keyword("END");
|
||||
...
|
||||
sup = cl_string_upcase(4, s, start, ecl_make_fixnum(2),
|
||||
end, ecl_make_fixnum(6));
|
||||
@end verbatim
|
||||
@end example
|
||||
|
||||
@end deftypefun
|
||||
|
||||
|
|
|
|||
|
|
@ -16,36 +16,38 @@
|
|||
Create a protected region.
|
||||
|
||||
@subsubheading C Macro
|
||||
@example
|
||||
@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
|
||||
cl_env_ptr env = ecl_process_env();
|
||||
CL_CATCH_ALL_BEGIN(env) {
|
||||
/*
|
||||
* In all cases we exit here.
|
||||
* 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
|
||||
@end example
|
||||
|
||||
@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
|
||||
@lisp
|
||||
(block nil
|
||||
(unwind-protect
|
||||
(progn
|
||||
;; Code that is protected
|
||||
)
|
||||
(return nil)))
|
||||
@end verbatim
|
||||
@end lisp
|
||||
|
||||
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 arbitrary transfers of control.
|
||||
|
||||
|
|
@ -60,26 +62,28 @@ As explained in @code{CL_UNWIND_PROTECT},it is normally advisable to set up an u
|
|||
Create a protected region.
|
||||
|
||||
@subsubheading C Macro
|
||||
@example
|
||||
@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
|
||||
cl_env_ptr env = ecl_process_env();
|
||||
CL_UNWIND_PROTECT_BEGIN(env) {
|
||||
/*
|
||||
* We only exit here if NO nonlocal jump was interrupted.
|
||||
* 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
|
||||
@end example
|
||||
|
||||
@subsubheading Description
|
||||
When embedding ECL it is normally advisable to set up an @code{unwind-protect} frame to avoid the embedded lisp code to perform arbitrary transfers of control. Furthermore, the unwind protect form will be used in at least in the following occasions:
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue