Subsections

データ型

他のLispと同様に、型の決まったデータオブジェクトは変数ではない。 どの変数もその値として、どんなオブジェクトも持つことができる。 変数にオブジェクトの型を宣言することが可能であるが、 一般的にコンパイラで高速なコードを生成するための情報としてのみ 使用される。 数値は、ポインタの中で直接値として表現され、 そのほかは、ポインタにより参照されるオブジェクトにより表現される。 Sun4で実行する場合、ポインタおよび数値は図2で描かれているように long wordで表現される。 ポインタのLSBの2ビットは、ポインタ・integer・floatを識別するための tagビットとして使用されている。 ポインタはtagビットが全てゼロであり、オブジェクトのアドレスとして32ビット全て 使用できるので、EusLispは4GB以上のアドレス空間を利用することができる。

Figure 2: ポインタと直接値
\includegraphics{fig/pointer.ps}

数値

数値には、integerとfloat(浮動小数点)の2種類があり、 両方とも29ビットの値と1ビットの符号で表現される。 したがって、integerは\begin{figure}\small
\begin{verbatim}object
cons
queue
propertied-object
s...
...h-table
surrounding-box
stereo-viewing\end{verbatim}
\normalsize\end{figure}536,870,912から536,870,911までの範囲となる。 floatは、正および負で4.8E\begin{figure}\small
\begin{verbatim}object
cons
queue
propertied-object
s...
...h-table
surrounding-box
stereo-viewing\end{verbatim}
\normalsize\end{figure}38から3.8E38までの範囲を表現でき、 その有効数字は、十進数で約6桁すなわち浮動小数点誤差は1/1,000,000程度である。

数値は、いつもオブジェクトでなくポインタで表現される。 これは、EusLispのオブジェクト指向の唯一の例外事項である。 しかしながら、数値は決してヒープメモリを無駄にすることがないため、 数値を扱うアプリケーションでは、ガーベージコレクション の原因とならず有効に動作する。 有理数や複素数など、別の数字の型はEusLispのオブジェクトとして記述される。

EusLispは、文字型を持たないため、文字列はintegerで表現される。 文字コード表と無関係なプログラムを書くためには、 #\ 読みだしマクロが役に立つ。しかし、文字が読まれるとき、 数値表現に変換されるため、プリンタは #\ の表記法に対してどのように再変換すればよいのか解らない。

数値は、図2のlong wordの中に2つのtagビットを持っている。 それで、数値計算に使用するときは、シフトまたはマスクすることにより このビットを消す必要がある。 integerは数値シフトによりMSBの2ビットを無視し、floatはマスクにより LSBの2ビットを無視する。 VAXのようなアーキテクチャのためにByte swapも必要である。なぜなら、 意味を持つ最小の大きさのByteとして右端の1Byteが使用できないためである。

オブジェクト

数値でない全てのデータは、ヒープにおかれるオブジェクトで表現される。 それぞれのオブジェクトのメモリセルは、オブジェクトヘッダーと オブジェクト変数のための固定数のスロットを持っている。 ベクトルは、任意の要素から構成されるため、 sizeスロットをヘッダーのすぐ後に持っている。 図3はオブジェクトとベクトルおよび オブジェクトのヘッダーを描いたものである。 ここに示すslotelementのワードだけがユーザーから アクセスすることができる。

Figure 3: オブジェクト・ベクトル・オブジェクトヘッダーの構造
\includegraphics{fig/object.ps}

ヘッダーは、6つの部分で構成されている。 MSBの2ビットmbは、フィボナッチバディメモリ管理手法の中で、 隣接セルの終端を示すために使用される。

mark部分には、3つのマークビットがあり、それぞれ ガーベージコレクタ用のアクセス可能セルの認識、 プリンタ用の環状オブジェクトの認識( #n=#n#表記法でプリントアウトさせた時)、 copy-object用の分割オブジェクトのコピーとして使用される。 elmt部分は、ベクトル要素として使用可能な7つのデータ型( pointer, bit, character, byte, integer, float, foreign-string) のうち1つを識別するために使用される。 しかしながら、elmtはクラスの中で利用可能なため、 クラスの構造と無関係なメモリ管理ができ、 要素の高速なアクセスができる。 bid部分は、メモリセルの物理的大きさを表現する。 31の違った大きさ(16MB以上)のメモリセルをこの5ビットで表現する。 下位のshort word (16ビット)は、クラスID(cid)として使用される。 これは、システムのクラステーブルを経由してオブジェクトのクラスを 引き出すために使用される。 このクラスIDは、伝統的なLispの型tagとみなすことができる。 cidは下位8ビットのみが使用され、上位8ビットは無視される。 したがって、クラスの最大数は256が限界であるけれども、 システムのクラステーブルにもっとメモリを配置するように EusLispを再構築することによって65536まで限界を引き上げることができる。

クラス継承

オブジェクトのデータ構造はクラスによって定義され、そして、それらの動作は クラス内のメソッドに定義されている。 EusLispにおいて、数ダースのクラスが図4に書かれているように 木構造化された継承のなかにすでに定義されている。 class-hierarchy関数を用いれば、実際の継承構造を見ることができる。 左端のクラスobjectは、EusLisp内の全てのクラスの根幹となるスーパークラスである。 ユーザーが定義したクラスは、これらの内部クラスのどれでも継承することができる。

Figure 4: 定義済みのクラス継承
\begin{figure}\small
\begin{verbatim}object
cons
queue
propertied-object
s...
...h-table
surrounding-box
stereo-viewing\end{verbatim}
\normalsize\end{figure}

クラスは、defclassマクロかdefstructマクロで定義される。


 (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...])
...)

メソッドは、defmethodにより定義される。 defmethodは、特定のクラスについて何度でも存在することができる。


 (defmethod class-name  

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

内部クラスにおけるfield定義は、大部分が *eusdir*/c/eus.hのヘッダーファイルの中にある。

クラスは、(describe)関数によりクラス内の全てのスロット、 名前、スーパークラス、スロット名、スロット型、メソッドリスト、 などを表示することができる。 内部クラスの定義は次の通りである。 クラスobjectはスーパークラスを持たないため、このスーパークラスはNILである。


 (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 elivered


 (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 unloadin
handle)) ;file handle returned by ”dlopen”

型指定

Euslispは、deftype特殊書式を持っていないけれども、 型名は宣言や結果あるいは中身の型の指定を要求する関数の中で 使用される。 例えば、coerce, map, concatenate, make-arrayなど。 一般に、クラス名は(concatenate cons "ab" "cd") = (97 98 99 100)のように 型指定として使用することができる。このとき、Common Lispではconsの代わりに (quote list)を使用する。

Euslispは、数を表現するクラスを持っていないので、数の型はキーワードによって 与える必要がある。 :integer, integer, :int, fixnum, あるいは:fixnumが整数型を表現するために使用され、 :floatあるいはfloatが実数型を表現するために使用される。 make-arrayelement-type引数においては、文字列を作るために :character, character, :bytebyteを 認識する。 defcstruct, sys:peeksys:pokeのような低レベルの関数も、 バイト毎にアクセスするために :character, character, :byteあるいはbyteを認識し、 short word毎にアクセスするために :shortあるいはshortを認識する。 どの場合においても、キーワードはpnameと同じ名前を持つlispパッケージのsymbol を選ぶべきである。

This document was generated using the LaTeX2HTML translator on Sat Feb 5 14:36:44 JST 2022 from EusLisp version 138fb6ee Merge pull request #482 from k-okada/apply_dfsg_patch