Subsections

Data Types

Like other Lisps, it is data objects that are typed, not variables. Any variable can have any object as its value. Although it is possible to declare the type of object which is bound to a variable, but usually it is only advisory information to the compiler to generate faster code. Numbers are represented as immediate values in pointers and all the others are represented by objects referenced by pointers.

In the implementation of Sun4, a pointer or a number is represented by a long word as depicted in fig.2. Two bits at LSB of a pointer are used as tag bits to discriminate between a pointer, an integer, and a float. Since a pointer's tags are all zero and it can use all 32 bits for addressing an object, EusLisp can utilize up to 4GB of process address space.

Figure 2: Pointer and Immediate Value
\includegraphics[width=10cm]{fig/pointer.ps}

Numbers

There are two kinds of numbers, integer and float (floating-point number), both are represented with 29 bits value and 1 bit sign. Thus, integers range from -536,870,912 to 536,870,911. Floats can represent plus/minus from 4.8E-38 to 3.8E38 with the approximate accuracy of 6 digits in decimal, i.e., floating-point epsilon is approximately 1/1,000,000.

Numbers are always represented by immediate data, and not by objects. This is the only exception of EusLisp's object orientation. However, since numbers never waste heap memory, number crunching applications run efficiently without causing garbage collection.

EusLisp does not have the character type, and characters are represented by integers. In order to write a program independent of character code sets, #\ reader dispatch macro is used. However, when the character is read, it is converted to numerical representation, and the printer does not know how to reconvert it to #\ notation.

A number has two tag bits in a long word Figure 2, which must be stripped off by shifting or masking when used in arithmetic computation. Note that an integer should ignore two MSB bits by arithmetic shifting, while a float should ignore two LSB bits by masking. Byte swap is also necessary for an architecture like VAX which does not use the rightmost byte as the least-significant mantissa byte.

Objects

Every data other than number is represented by an object which is allocated in heap. Each memory cell of an object has the object header and fixed number of slots for object variables. Since vectors may consist of arbitrary number of elements, they have 'size' slot immediately after the header. Fig. 3 depicts the structures of object and vector, and their header word. Only the words indicated as slot and element are accessible from users.

Figure 3: Structures of object, vector, and object header
\includegraphics{fig/object.ps}

A header is composed of six fields. Two MSB bits, m and b, are used to indicate the side of the neighbor cell in Fibonacci-buddy memory management. There are three mark bits in the mark field, each of which is used by the garbage collector to identify accessible cells, by the printer to recognize circular objects in printing in #n= and #n# notations, and by copy-object to copy shared objects. The elmt field discriminates one of seven possible data types of vector elements, pointer, bit, character, byte, integer, float and foreign-string. Although elmt can be available in the class, it is provided in the header to make the memory manager independent of the structure of a class and to make the element accessing faster. The bid field represents the physical size of a memory cell. 31 different sizes up to 16 MB are represented by the five bits in this field. The lower short word (16 bits) is used for the class id. This is used to retrieve the class of an object via the system's class table. This class id can be regarded as the type tag of traditional Lisps. Currently only the lower 8 bits of the cid are used and the upper 8 bits are ignored. Therefore, the maximum number of classes is limited to 256, though this limit can be raised up to 65536 by reconfiguring the EusLisp to allocate more memory to the system's class table.

Class Hierarchy

The data structure of objects are defined by classes, and their behaviors are defined by methods in the classes. In EusLisp, a few dozens of classes have already been defined in tree structured hierarchy as depicted in fig. 4. You can browse the real inheritance structure by the class-hierarchy function. The class 'object' at the leftmost is the ultimate super-class of all the classes in EusLisp. User-defined classes can inherit any of these built-in classes.

Figure 4: Hierarchy of Predefined Classes
\begin{figure}\small
\begin{verbatim}object
cons
queue
propertied-object
s...
...h-table
surrounding-box
stereo-viewing\end{verbatim}
\normalsize\end{figure}

A class is defined the defclass macro or by the defstruct macro.


 (defclass class-name &key :super   class 

:slots ()
:metaclass metaclass
:element-type t
:size -1
)
(defstruct struct-name slots...)
(defstruct (struct-name [struct-options ...])
(slot-name1 [slot-option...])
(slot-name2 [slot-option...])
...)

Methods are defined by the defmethod special form. Defmethod can appear any times for a particular class.


 (defmethod class-name  

(:method-name1 (parameter...) . body1)
(:method-name2 (parameter...) . body2)
...)

Field definitions for most of built-in classes are found in *eusdir*/c/eus.h header file. (describe) class) gives the description of all the slots in class, namely, super class, slot names, slot types, method list, and so on. Definitions of built-in classes follow. Note that the superclass of class object is NIL since it has no super class.


 (defclass object :super NIL :slots ()) 


 (defclass cons :super object :slots (car cdr)) 


 (defclass propertied-object :super object 

:slots (plist)) ;property list


 (defclass symbol :super propertied-object 

:slots (value ;specially bound value
vtype ;const(0),var(1),special(2)
function ;global func def
pname ;print name string
homepkg)) ;home package


 (defclass foreign-pod :super symbol 

:slots (podcode ;entry code
paramtypes ;type of arguments
resulttype))


 (defclass package :super propertied-object 

:slots (names ;list of package name and nicknames
uses ;spread use-package list
symvector ;hashed obvector
symcount ;number of interned symbols
intsymvector ;hashed obvector of internal symbols
intsymcount ;number of interned internal symbols
shadows ;shadowed symbols
used-by)) ;packages using this package


 (defclass stream :super propertied-object   

:slots (direction ;:input or :output, nil if closed
buffer ;buffer string
count ;current character index
tail)) ;last character index


 (defclass file-stream :super stream 

:slots (fd ;file descriptor (integer)
fname)) ;file name str; qid for msgq


 (defclass broadcast-stream :super stream

:slots (destinations)) ;streams to which output is delivered


 (defclass io-stream :super propertied-object

:slots (instream outstream))


 (defclass socket-stream :super io-stream

:slots (address)) ; socket address


 (defclass read-table  :super propertied-object 

:slots (syntax ; byte vector representing character types
; 0:illegal, 1:white, 2:comment, 3:macro
; 4:constituent, 5:single_escape
; 6:multi_escape, 7:term_macro, 8:nonterm_macro
macro ;character macro expansion function
dispatch-macro))


 (defclass array :super propertied-object 

:slots (entity ;simple vector storing array entity
rank ;number of dimensions: 0-7
fillpointer ;pointer to push next element
offset ;offset for displaced array
dim0,dim1,dim2,dim3,dim4,dim5,dim6)) ;dimensions


 (defclass metaclass :super propertied-object 

:slots (name ;class name symbol
super ;super class
cix ;class id
vars ;var name vector including inherited vars
types ;type vector of object variables
forwards ;components to which messages are forwarded
methods)) ;method list


 (defclass vectorclass :super metaclass  

:slots (element-type ;vector element type 0-7
size)) ;vector size; 0 if unspecified


 (defclass cstructclass :super vectorclass  

:slots (slotlist)) ;cstruct slot descriptors


 (defclass vector :super object :slots (size)) 


 (defclass float-vector :super vector :element-type :float) 


 (defclass string :super vector :element-type :char) 


 (defclass hash-table :super propertied-object 

:slots (lisp::key ;hashed key vector
value ; value vector
size ; the size of the hash table
count ; number of elements entered in the table
lisp::hash-function
lisp::test-function
lisp::rehash-size
lisp::empty lisp::deleted )


 (defclass queue :super cons) 


 (defclass pathname :super propertied-object 

:slots (lisp::host device ; not used
directory ; list of directories
name ; file name before the last "."
type ; type field after the last "."
lisp::version) ; not used


 (defclass label-reference    ;for reading #n=, #n# objects 

:super object
:slots (label value unsolved next))


 (defclass compiled-code :super object 

:slots (codevector
quotevector
type ;0=func, 1=macro, 2=special
entry)) ;entry offset


 (defclass closure :super compiled-code 

:slots (env1 env2));environment


 (defclass foreign-code  :super compiled-code  

:slots (paramtypes ;list of parameter types
resulttype)) ;function result type


 (defclass load-module  :super compiled-code  

:slots (symbol-table ;hashtable of symbols defined
object-file ;name of the object file loaded, needed for unloading
handle ;file handle returned by ''dlopen''

Type Specifier

Though EusLisp does not have the deftype special form, type names are used in declarations and functions requesting to specify the type of results or contents, as in coerce, map, concatenate, make-array, etc. Usually, class names can be used as type specifiers, as in (concatenate cons "ab" "cd") = (97 98 99 100), where Common Lisp uses (quote list) instead of cons.

As EusLisp does not have classes to represent numbers, types for numbers need to be given by keywords. :integer, integer, :int, fixnum, or :fixnum is used to represent the integer type, :float or float, the floating point number type. As the element-type argument of make-array, :character, character, :byte, and byte are recognized to make strings. Low level functions such as defcstruct, sys:peek, and sys:poke, also recognize :character, character, :byte, or byte for the byte access, and :short or short for short word access. In any cases, keywords are preferable to lisp package symbols with the same pname.

Travis CI User 2017-03-07