new-doc: objects: finish objects (dev) module

This commit is contained in:
Daniel Kochmański 2016-03-04 19:54:09 +01:00
parent ee5733b4a0
commit d8f8f6bca9
2 changed files with 592 additions and 3 deletions

View file

@ -1,11 +1,23 @@
@node Manipulating Lisp objects
@section Manipulating Lisp objects
@menu
* Integers (dev)::
* Characters (dev)::
* Arrays (dev)::
* Strings (dev)::
* Bit-vectors (dev)::
* Streams (dev)::
* Structures (dev)::
* Instances (dev)::
* Bytecodes (dev)::
@end menu
If you want to extend, fix or simply customize ECL for your own needs,
you should understand how the implementation works.
@cppindex cl_lispunion
@deftp {C/C++ index} cl_lispunion cons big ratio SF DF longfloat complex symbol pack hash array vector base_string string stream random readtable pathname bytecodes bclosure cfun cfunfixed cclosure d instance process queue lock rwlock condition_variable semaphore barrier mailbox cblock foreign frame weak sse
@deftp {@cind} cl_lispunion cons big ratio SF DF longfloat complex symbol pack hash array vector base_string string stream random readtable pathname bytecodes bclosure cfun cfunfixed cclosure d instance process queue lock rwlock condition_variable semaphore barrier mailbox cblock foreign frame weak sse
Union containing all first-class ECL types.
@end deftp
@ -194,9 +206,12 @@ denoting the type that lisp object. That integer is one of the values of
the enumeration type @code{cl_type}.
@end deftypefun
@c XXX: add all predicate macros to the index
@cppindex ECL_FIXNUMP
@cppindex ECL_CHARACTERP
@cppindex CODE_CHAR_P
@cppindex ECL_BASE_CHAR_P
@cppindex ECL_BASE_CHAR_CODE_P
@cppindex ECL_NUMBER_TYPE_P
@cppindex ECL_REAL_TYPE_P
@cppindex ECL_REAL_TYPE_P
@ -212,6 +227,8 @@ the enumeration type @code{cl_type}.
@deftypefun bool ECL_FIXNUMP (cl_object o)
@deftypefunx bool ECL_CHARACTERP (cl_object o)
@deftypefunx bool ECL_BASE_CHAR_P (cl_object o)
@deftypefunx bool ECL_CODE_CHAR_P (cl_object o)
@deftypefunx bool ECL_BASE_CHAR_CODE_P (cl_object o)
@deftypefunx bool ECL_NUMBER_TYPE_P (cl_object o)
@deftypefunx bool ECL_REAL_TYPE_P (cl_object o)
@deftypefunx bool ECL_CONSP (cl_object o)
@ -228,10 +245,580 @@ type. These checks have been optimized, and are preferred over several
calls to @code{ecl_t_of}.
@end deftypefun
@cppindex ECL_IMMEDIATE
@deftypefun bool ECL_IMMEDIATE (cl_object o)
Tells whether @var{x} is an immediate datatype.
@end deftypefun
@deftp {@cind} cl_objectxx
@end deftp
@subsection Constructing objects
On each of the following sections we will document the standard
interface for building objects of different types. For some objects,
though, it is too difficult to make a C interface that resembles all of
the functionality in the lisp environment. In those cases you need to
@enumerate
@item build the objects from their textual representation, or
@item use the evaluator to build these objects.
@end enumerate
The first way makes use of a C or Lisp string to construct an
object. The two functions you need to know are the following ones.
@cppindex c_string_to_object
@cppindex string_to_object
@deftypefun cl_object c_string_to_object (const char *s)
@deftypefunx cl_object string_to_object (cl_object o)
@code{c_string_to_object} builds a lisp object from a C string which
contains a suitable representation of a lisp
object. @code{string_to_object} performs the same task, but uses a lisp
string, and therefore it is less useful.
@subsubheading Example
@exindex @code{c_string_to_object} constructing Lisp objects in C
Using a C string
@example
cl_object array1 = c_string_to_object("#(1 2 3 4)");
@end example
Using a Lisp string
@example
cl_object string = make_simple_string("#(1 2 3 4)");
cl_object array2 = string_to_object(string);
@end example
@end deftypefun
@node Integers (dev)
@subsection Integers (dev)
Common-Lisp distinguishes two types of integer types: @code{bignum}s and
@code{fixnum}s. A fixnum is a small integer, which ideally occupies only
a word of memory and which is between the values
@code{MOST-NEGATIVE-FIXNUM} and @code{MOST-POSITIVE-FIXNUM}. A
@code{bignum} is any integer which is not a @code{fixnum} and it is only
constrained by the amount of memory available to represent it.
In ECL a @code{fixnum} is an integer that, together with the tag bits,
fits in a word of memory. The size of a word, and thus the size of a
@code{fixnum}, varies from one architecture to another, and you should
refer to the types and constants in the ecl.h header to make sure that
your C extensions are portable. All other integers are stored as
@code{bignum}s, they are not immediate objects, they take up a variable
amount of memory and the GNU Multiprecision Library is required to
create, manipulate and calculate with them.
@cppindex cl_fixnum
@deftp {@cind} cl_fixnum
This is a C signed integer type capable of holding a whole @code{fixnum}
without any loss of precision. The opposite is not true, and you may
create a @code{cl_fixnum} which exceeds the limits of a fixnum and
should be stored as a @code{bignum}.
@end deftp
@cppindex cl_index
@deftp {@cind} cl_index
This is a C unsigned integer type capable of holding a non-negative
@code{fixnum} without loss of precision. Typically, a @code{cl_index} is
used as an index into an array, or into a proper list, etc.
@end deftp
@cppindex MOST_NEGATIVE_FIXNUM
@cppindex MOST_POSITIVE_FIXNUM
@lspindex MOST-NEGATIVE-FIXNUM
@lspindex MOST-POSITIVE-FIXNUM
@defvr {Constant} MOST_NEGATIVE_FIXNUM
@defvrx {Constant} MOST_POSITIVE_FIXNUM
These constants mark the limits of a @code{fixnum}.
@end defvr
@cppindex ecl_fixnum_lower
@cppindex ecl_fixnum_greater
@cppindex ecl_fixnum_leq
@cppindex ecl_fixnum_geq
@cppindex ecl_fixnum_plusp
@cppindex ecl_fixnum_minusp
@deftypefun bool ecl_fixnum_lower (cl_fixnum a, cl_fixnum b)
@deftypefunx bool ecl_fixnum_greater (cl_fixnum a, cl_fixnum b)
@deftypefunx bool ecl_fixnum_leq (cl_fixnum a, cl_fixnum b)
@deftypefunx bool ecl_fixnum_geq (cl_fixnum a, cl_fixnum b)
@deftypefunx bool ecl_fixnum_plusp (cl_fixnum a)
@deftypefunx bool ecl_fixnum_minusp (cl_fixnum a)
Operations on @code{fixnums} (comparison and predicates).
@end deftypefun
@cppindex ecl_make_fixnum
@cppindex ecl_fixnum
@cppindex MAKE_FIXNUM
@cppindex fix
@deftypefun cl_object ecl_make_fixnum (cl_fixnum n)
@deftypefunx cl_fixnum ecl_unfix (cl_object o)
@code{ecl_make_fixnum} converts from an integer to a lisp object, while
the @code{ecl_fixnum} does the opposite (converts lisp object fixnum to
integer). These functions do @strong{not} check their arguments.
@itemize @bullet
@item @strong{DEPRECATED} @code{MAKE_FIXNUM} equivalent to @code{cl_make_fixnum}
@item @strong{DEPRECATED} @code{fix} equivalent to @code{cl_fixnum}
@end itemize
@end deftypefun
@cppindex cl_fixnum
@cppindex cl_index
@deftypefun cl_fixnum fixint (cl_object o)
@deftypefunx cl_index fixnint (cl_object o)
Safe conversion of a lisp @code{fixnum} to a C integer of the
appropriate size. Signals an error if @var{o} is not of fixnum type.
@code{fixnint} additionally ensure that @var{o} is not negative.
@end deftypefun
@node Characters (dev)
@subsection Characters (dev)
@cfindex --enable-unicode (YES|no|32)
ECL has two types of characters one fits in the C type char, while the
other is used when ECL is built with a configure option
@code{--enable-unicode}.
@cppindex ecl_character
@cppindex ecl_base_char
@deftp {@cind} ecl_character
Immediate type @code{t_character}. If ECL built with Unicode support,
then may be either base or extended character, which may be
distinguished with the predicate @code{ECL_BASE_CHAR_P}.
Additionally we have @code{ecl_base_char} for base strings, which is an
equivalent to the ordinary char.
@subsubheading Example
@exindex distinguishing between base and Unicode character
@example
if (ECL_CHARACTERP(o) && ECL_BASE_CHAR_P(o))
printf("Base character: %c\n", ECL_CHAR_CODE(o));
@end example
@end deftp
@cppindex ECL_CHAR_CODE_LIMIT
@cppindex CHAR_CODE_LIMIT
@defvr {Constant} ECL_CHAR_CODE_LIMIT
Each character is assigned an integer code which ranges from 0 to
(ECL_CHAR_CODE_LIMIT-1).
@itemize @bullet
@item @strong{DEPRECATED} @code{CODE_CHAR_LIMIT} equivalent to @code{ECL_CHAR_CODE_LIMIT}
@end itemize
@end defvr
@cppindex ecl_char_code
@cppindex ecl_base_char_code
@cppindex ECL_CHAR_CODE
@cppindex ECL_CODE_CHAR
@cppindex CODE_CHAR
@cppindex CHAR_CODE
@deftypefun cl_fixnum ECL_CHAR_CODE (cl_object o)
@deftypefunx cl_fixnum ECL_CODE_CHAR (cl_object o)
@code{ECL_CHAR_CODE}, @code{ecl_char_code} and @code{ecl_base_char_code}
return the integer code associated to a lisp
character. @code{ecl_char_code} and @code{ecl_base_char_code} perform a
safe conversion, while ECL_CHAR_CODE doesn't check it's
argument. @code{ecl_base_char_code} is an optimized version for base
chars. Checks it's argument.
@code{ECL_CODE_CHAR} returns the lisp character associated to an integer
code. It does not check its arguments.
@itemize @bullet
@item @strong{DEPRECATED} @code{CHAR_CODE} equivalent to @code{ECL_CHAR_CODE}
@item @strong{DEPRECATED} @code{CODE_CHAR} equivalent to @code{ECL_CODE_CHAR}
@end itemize
@end deftypefun
@cppindex ecl_char_eq
@cppindex ecl_char_equal
@deftypefun bool ecl_char_eq (cl_object x, cl_object y)
@deftypefunx bool ecl_char_equal (cl_object x, cl_object y)
Compare two characters for equality. char_eq take case into account and
char_equal ignores it.
@end deftypefun
@cppindex ecl_char_cmp
@cppindex ecl_char_compare
@deftypefun bool ecl_char_cmp (cl_object x, cl_object y)
@deftypefunx bool ecl_char_compare (cl_object x, cl_object y)
Compare the relative order of two characters. @code{char_cmp} takes care
of case and @code{char_compare} converts all characters to uppercase
before comparing them.
@end deftypefun
@node Arrays (dev)
@subsection Arrays (dev)
An array is an aggregate of data of a common type, which can be accessed
with one or more non-negative indices. ECL stores arrays as a C structure
with a pointer to the region of memory which contains the actual
data. The cell of an array datatype varies depending on whether it is a
vector, a bit-vector, a multidimensional array or a string.
@cppindex ECL_ADJUSTABLE_ARRAY_P
@cppindex ECL_ARRAY_HAS_FILL_POINTER_P
@deftypefun bool ECL_ADJUSTABLE_ARRAY_P (cl_object x)
@deftypefunx bool ECL_ARRAY_HAS_FILL_POINTER_P (cl_object x)
All arrays (arrays, strings and bit-vectors) may be tested for being
adjustable and whenever they have a fill pointer with this two
functions.
@end deftypefun
@cppindex ecl_vector
@deftp {@cind} ecl_vector
If @code{x} contains a vector, you can access the following fields:
@table @code
@item x->vector.elttype
The type of the elements of the vector.
@item x->vector.displaced
Boolean indicating if it is displaced.
@item x->vector.dim
The maximum number of elements.
@item x->vector.fillp
Actual numer of elements in the vector or @code{fill pointer}.
@item x->vector.self
Union of pointers of different types. You should choose the right
pointer depending on @var{x->vector.elttype}.
@end table
@end deftp
@cppindex ecl_array
@deftp {@cind} ecl_array
If @code{x} contains a multidimensional array, you can access the
following fields:
@table @code
@item x->array.elttype
The type of the elements of the array.
@item x->array.rank
The number of array dimensions.
@item x->array.displaced
Boolean indicating if it is displaced.
@item x->vector.dim
The maximum number of elements.
@item x->array.dims[]
Array with the dimensions of the array. The elements range from
@code{x->array.dim[0]} to @code{x->array.dim[x->array.rank-1]}.
@item x->array.fillp
Actual numer of elements in the array or @code{fill pointer}.
@item x->array.self
Union of pointers of different types. You should choose the right
pointer depending on @var{x->array.elttype}.
@end table
@end deftp
@cppindex cl_elttype
@deftp {@cind} cl_elttype ecl_aet_object ecl_aet_sf ecl_aet_df ecl_aet_bit ecl_aet_fix ecl_aet_index ecl_aet_b8 ecl_aet_i8 ecl_aet_b16 ecl_aet_i16 ecl_aet_b32 ecl_aet_i32 ecl_aet_b64 ecl_aet_i64 ecl_aet_ch ecl_aet_bc
Each array is of an specialized type which is the type of the elements
of the array. ECL has arrays only a few following specialized types, and
for each of these types there is a C integer which is the corresponding
value of @code{x->array.elttype} or @code{x->vector.elttype}. We list
some of those types together with the C constant that denotes that type:
@table @var
@item T
@code{ecl_aet_object}
@item BASE-CHAR
@code{ecl_aet_object}
@item SIGNLE-FLOAT
@code{ecl_aet_sf}
@item DOUBLE-FLOAT
@code{ecl_aet_df}
@item BIT
@code{ecl_aet_bit}
@item FIXNUM
@code{ecl_aet_fix}
@item INDEX
@code{ecl_aet_index}
@item CHARACTER
@code{ecl_aet_ch}
@item BASE-CHAR
@code{ecl_aet_bc}
@end table
@end deftp
@cppindex ecl_array_elttype
@deftypefun cl_elttype ecl_array_elttype (cl_object array)
Returns the element type of the array @code{o}, which can be a string, a
bit-vector, vector, or a multidimensional array.
@subsubheading Example
@exindex @code{ecl_array_elttype} different types of objects
For example, the code
@example
ecl_array_elttype(c_string_to_object("\"AAA\"")); /* returns ecl_aet_ch */
ecl_array_elttype(c_string_to_object("#(A B C)")); /* returns ecl_aet_object */
@end example
@end deftypefun
@cppindex ecl_aref
@cppindex ecl_aset
@deftypefun cl_object ecl_aref (cl_object x, cl_index index)
@deftypefunx cl_object ecl_aset (cl_object x, cl_index index, cl_object value)
These functions are used to retrieve and set the elements of an
array. The elements are accessed with one index, index, as in the lisp
function ROW-MAJOR-AREF.
@subsubheading Example
@exindex @code{ecl_aref} and @code{ecl_aset} accessing arrays
@example
cl_object array = c_string_to_object("#2A((1 2) (3 4))");
cl_object x = aref(array, 3);
cl_print(1, x); /* Outputs 4 */
aset(array, 3, MAKE_FIXNUM(5));
cl_print(1, array); /* Outputs #2A((1 2) (3 5)) */
@end example
@end deftypefun
@cppindex ecl_aref1
@cppindex ecl_aset1
@deftypefun cl_object ecl_aref (cl_object x, cl_index index)
@deftypefunx cl_object ecl_aset (cl_object x, cl_index index, cl_object value)
These functions are similar to aref and aset, but they operate on vectors.
@subsubheading Example
@exindex @code{ecl_aref1} and @code{ecl_aset1} accessing vectors
@example
cl_object array = c_string_to_object("#(1 2 3 4)");
cl_object x = aref1(array, 3);
cl_print(1, x); /* Outputs 4 */
aset1(array, 3, MAKE_FIXNUM(5));
cl_print(1, array); /* Outputs #(1 2 3 5) */
@end example
@end deftypefun
@node Strings (dev)
@subsection Strings (dev)
A string, both in Common-Lisp and in ECL is nothing but a vector of
characters. Therefore, almost everything mentioned in the section of
arrays remains valid here.
The only important difference is that ECL stores the base-strings
(non-Unicode version of a string) as a lisp object with a pointer to a
zero terminated C string. Thus, if a string has n characters, ECL will
reserve n+1 bytes for the base-string. This allows us to pass the
base-string self pointer to any C routine.
@cppindex ecl_string
@cppindex ecl_base_string
@deftp {@cind} ecl_string
@deftpx {@cind} ecl_base_string
If @code{x} is a lisp object of type string or a base-string, we can
access the following fields:
@table @code
@item x->string.dim x->base_string.dim
Actual number of characters in the string.
@item x->string.fillp x->base_string.fillp
Actual number of characters in the string.
@item x->string.self x->base_string.self
Pointer to the characters (appropriately integers and chars).
@end table
@end deftp
@cppindex ECL_EXTENDED_STRING_P
@cppindex ECL_BASE_STRING_P
@deftypefun bool ECL_EXTENDED_STRING_P (cl_object object)
@deftypefunx bool ECL_BASE_STRING_P (cl_object object)
Verifies if an objects is an extended or base string. If Unicode isn't
supported, then @code{ECL_EXTENDED_STRING_P} always returns 0.
@end deftypefun
@node Bit-vectors (dev)
@subsection Bit-vectors (dev)
Bit-vector operations are implemented in file
@code{src/c/array.d}. Bit-vector shares the structure with a vector,
therefore, almost everything mentioned in the section of arrays remains
valid here.
@node Streams (dev)
@subsection Streams (dev)
Streams implementation is a broad topic. Most of the implementation is
done in the file @code{src/c/file.d}. Stream handling may have different
implementations referred by a member pointer @code{ops}.
Additionally on top of that we have implemented @emph{Gray Streams} (in
portable Common Lisp) in file @code{src/clos/streams.lsp}, which may be
somewhat slower (we need to benchmark it!). This implementation is in a
separate package @var{GRAY}. We may redefine functions in the
@var{COMMON-LISP} package with a function @code{redefine-cl-functions}
at run-time.
@cppindex ecl_file_pos
@deftp {@cind} ecl_file_ops write_* read_* unread_* peek_* listen clear_input clear_output finish_output force_output input_p output_p interactive_p element_type length get_position set_position column close
@end deftp
@cppindex ecl_stream
@deftp {@cind} ecl_stream
@table @code
@item ecl_smmode mode
Stream mode (in example @code{ecl_smm_string_input}).
@item int closed
Whenever stream is closed or not.
@item ecl_file_ops *ops
Pointer to the structure containing operation implementations (dispatch
table).
@item union file
Union of ANSI C streams (FILE *stream) and POSIX files interface
(cl_fixnum descriptor).
@item cl_object object0, object1
Some objects (may be used for a specific implementation purposes).
@item cl_object byte_stack
Buffer for unread bytes.
@item cl_index column
File column.
@item cl_fixnum last_char
Last character read.
@item cl_fixnum last_code[2]
Actual composition of the last character.
@item cl_fixnum int0 int1
Some integers (may be used for a specific implementation purposes).
@item cl_index byte_size
Size of byte in binary streams.
@item cl_fixnum last_op
0: unknown, 1: reading, -1: writing
@item char *buffer
Buffer for FILE
@item cl_object format
external format
@item cl_eformat_encoder encoder
@item cl_eformat_encoder decoder
@item cl_object format_table
@item in flags
Character table, flags, etc
@item ecl_character eof_character
@end table
@end deftp
@cppindex ECL_ANSI_STREAM_P
@deftypefun ECL_ANSI_STREAM_P (cl_object o)
Predicate determining if @code{o} is a first-class stream
object. Doesn't check type of it's argument.
@end deftypefun
@cppindex ECL_ANSI_STREAM_TYPE_P
@deftypefun ECL_ANSI_STREAM_TYPE_P (cl_object o, ecl_smmode m)
Predicate determining if @code{o} is a first-class stream
object of type @code{m}.
@end deftypefun
@node Structures (dev)
@subsection Structures (dev)
Structures and instances share the same datatype @code{t_instance} (
with a few exceptions. Structure implementation details are the file
@code{src/c/structure.d}.
@cppindex ECL_STRUCT_TYPE
@cppindex ECL_STRUCT_SLOTS
@cppindex ECL_STRUCT_LENGTH
@cppindex ECL_STRUCT_SLOT
@cppindex ECL_STRUCT_NAME
@deftypefun cl_object ECL_STRUCT_TYPE (cl_object x)
@deftypefunx cl_object ECL_STRUCT_SLOTS (cl_object x)
@deftypefunx cl_object ECL_STRUCT_LENGTH (cl_object x)
@deftypefunx cl_object ECL_STRUCT_SLOT (cl_object x, cl_index i)
@deftypefunx cl_object ECL_STRUCT_NAME (cl_object x)
Convenience functions for the structures.
@end deftypefun
@node Instances (dev)
@subsection Instances (dev)
@cppindex ECL_CLASS_OF
@cppindex ECL_SPEC_FLAG
@cppindex ECL_SPEC_OBJECT
@cppindex ECL_CLASS_NAME
@cppindex ECL_CLASS_SUPERIORS
@cppindex ECL_CLASS_INFERIORS
@cppindex ECL_CLASS_SLOTS
@cppindex ECL_CLASS_CPL
@cppindex ECL_INSTANCEP
@deftypefun cl_object ECL_CLASS_OF (cl_object x)
@deftypefunx cl_object ECL_SPEC_FLAG (cl_object x)
@deftypefunx cl_object ECL_SPEC_OBJECT (cl_object x)
@deftypefunx cl_object ECL_CLASS_NAME (cl_object x)
@deftypefunx cl_object ECL_CLASS_SUPERIORS (cl_object x)
@deftypefunx cl_object ECL_CLASS_INFERIORS (cl_object x)
@deftypefunx cl_object ECL_CLASS_SLOTS (cl_object x)
@deftypefunx cl_object ECL_CLASS_CPL (cl_object x)
@deftypefunx bool ECL_INSTANCEP (cl_object x)
Convenience functions for the structures.
@end deftypefun
@node Bytecodes (dev)
@subsection Bytecodes (dev)
A bytecodes object is a lisp object with a piece of code that can be
interpreted. The objects of type t_bytecode are implicitly constructed
by a call to eval, but can also be explicitly constructed with the
make_lambda function.
@cppindex si_safe_eval
@cppindex cl_safe_eval
@cppindex cl_eval
@deftypefun cl_object si_safe_eval (cl_object form, cl_object env, ...)
@code{si_safe_eval} evaluates @code{form} in the lexical environment
@code{env}, which can be @var{ECL_NIL}. Before evaluating it, the
expression form must be bytecompiled.
@table @code
@item @strong{DEPRECATED} cl_object cl_eval (cl_object form)
@code{cl_eval} is the equivalent of @code{si_safe_eval} but without
environment and with err_value set to nil. It exists only for
compatibility with previous versions.
@item @strong{DEPRECATED} cl_object cl_safe_eval (cl_object form)
Equivalent of @code{si_safe_eval} (macro define).
@end table
@subheading Exmaple
@exindex @code{cl_safe_eval}
@example
si_object form = c_string_to_object("(print 1)");
si_safe_eval(form, ECL_NIL);
si_safe_eval(form, ECL_NIL, 3); /* on error function will return 3 */
@end example
@end deftypefun
@cppindex si_make_lambda
@deftypefun cl_object si_make_lambda (cl_object name, cl_object def)
Builds an interpreted lisp function with name given by the symbol name
and body given by def.
@subheading Example
@exindex @code{si_make_lambda} building functions
For instance, we would achieve the equivalent of
@lisp
(funcall #'(lambda (x y)
(block foo (+ x y)))
1 2)
@end lisp
with the following code
@example
cl_object def = c_string_to_object("((x y) (+ x y))");
cl_object name = _intern("foo")
cl_object fun = si_make_lambda(name, def);
return funcall(fun, MAKE_FIXNUM(1), MAKE_FIXNUM(2));
@end example
Notice that @code{si_make_lambda} performs a bytecodes compilation of
the definition and thus it may signal some errors. Such errors are not
handled by the routine itself so you might consider using
@code{si_safe_eval} instead.
@end deftypefun

View file

@ -6,6 +6,8 @@
@c * In-house GC:: ECL's own GC
@c * Green threads:: Lightweight processes
@c * Compiler newcmp:: Experimental compiler architecture
@c * In-house bignum implementation::
@c * Possibility to build without bignums::
@c @end menu
@c @node In-house DFFI