2014年12月1日月曜日

Swank RPC プロトコル


Swank RPC プロトコルは、SLIME と Swank との間で用いられる、テキストベースの非同期通信プロトコルです。

SLIME は、Common Lisp でアプリケーションを開発するための Emacs モードで、IDE(統合開発環境)と呼べるほど強力な機能を備えています。

SLIME には、Swank と呼ばれるバックエンドがあります。Swank は、Common Lisp プロセスにロードされ、ソケットを経由して SLIME と通信します。このとき使用されるのが、Swank RPC プロトコルです。

Swank RPC プロトコルの概観


Swank RPC プロトコルは、6文字の16進数文字列とそれに続くS式、終端の改行文字で構成されます。

000016(:return (:ok nil) 1)\n

先頭の16進数文字列は、続くS式の長さ(最後の改行文字を含む)を表します。S式は、SLIME や Swank によって読み込まれます。S式の最初の要素はメッセージの種類を表すキーワードで、残りの要素がその引数です。

メッセージには、以下のような種類があります。

  • :emacs-rex
  • :return
  • :indentation-update
  • :new-features

Swank RPC プロトコルによるS式の評価


たとえば、(+ 3 4)というS式を Swank で評価するには、以下のメッセージを送信します。

00002c(:emacs-rex (+ 3 4) "COMMON-LISP-USER" t 1)\n

最初の6文字は続くS式の長さで、改行文字を含め44文字のため、16進数で2cとなります。

メッセージの種類は :emacs-rex (Remote EXecute SEXP)で、第一引数が評価するS式、第二引数がそのときのカレントパッケージです。第三引数はS式の評価を行う Swank 側のスレッドを表し、第四引数は戻り値を受け取る継続を意味します。

S式が評価されると、Swank からは以下のようなメッセージが返信されます。

000013(:return (:ok 7) 1)

最初の6文字は、送信されたメッセージと同様にS式の長さを表し、19文字のため、16進数で13となります。

戻り値を表すメッセージは、:return です。評価に成功した場合、第一引数の最初の要素が :ok となり、二番目の要素に評価した結果の値が入ります。ここではその値は7です。第二引数は、送信されたメッセージの第四引数に含まれていた継続がそのまま返されます。

まとめ


このように、Swank RPC プロトコルでは、S式で表現されたテキストベースのメッセージが相互にやりとりされます。SLIME と Swank のやり取りの様子は、Emacs の *slime-events* バッファでみることができます。


2014年5月30日金曜日

cl-coroutine: a coroutine library for Common Lisp


CL-COROUTINE is a coroutine library for Common Lisp. It uses CL-CONT continuations library in its implementation.


https://github.com/takagi/cl-coroutine

;; define a coroutine using DEFCOROUTINE macro 
(defcoroutine example (whom) 
  (format t "First greeting to: ~A~%" whom) 
  (yield 1) 
  (format t "Second greeting to: ~A~%" whom) 
  (yield 2) 
  (format t "Third greeting to: ~A~%" whom) 
  (coexit 3) 
  (format t "No greeting to: ~A~%" whom) 
  (yield 4)) 
=> EXAMPLE 

;; make a coroutine object 
(setf coroutine (make-coroutine 'example)) 
=> a coroutine object 

;; funcall it 
(funcall coroutine "Smith") 
>> First greeting to: Smith 
=> 1 

I want your feedback. Thanks.

 

SBCL (Steel Bank Common Lisp) のビルドプロセス

SBCL のビルドプロセスの外観


Common Lisp の実装の1つである SBCL (Steel Bank Common Lisp) のビルドプロセスは、Allegro Common Lisp や LispWorks といった、イメージベースでそれ自身の上でのみビルド可能な Common Lisp 実装とは異なり、SBCL 以外の Common Lisp 実装の上でもビルドできます。それを実現するために、SBCL のビルドプロセスでは、様々なテクニックが使われています。

このエントリでは、SBCL のビルドプロセスを順を追って説明します。

host-1 ビルドステージ


まず、ホスト上にクロスコンパイラを読み込みます。SBCL のソースコードをホストコンパイラでコンパイルしロードすることで、ホスト上にクロスコンパイラを展開します。

続いて、後のステージのための前処理として、sb!fasl:genesis の読み込みと、C ヘッダファイルの出力を行います。sb!fasl:genesis は、genesis-2 ビルドステージで、'cold core' を生成するために使われます。C ヘッダファイルは、続く target-1 ビルドステージで、SBCL の実行形式を構築するのに使われます。

target-1 ビルドステージ


target-1 ビルドステージでは、大きく2つの処理が行われます。1つは、SBCL 実行形式の構築です。host-1 ビルドステージで生成された C ヘッダファイルと、その他の C ソースファイルおよびアセンブリファイルから、SBCL の実行形式を構築します。ただし、この実行形式は、この時点ではまだ動作しません。OS サービスへのインターフェイスやガベージコレクタを提供するものの、次ステージ以降で生成されるターゲットメモリイメージを含まないためです。

もう1つの処理は、ターゲットの一部として使用される Lisp ソースコードの生成です。この Lisp ソースコードは、小さな C プログラムをコンパイルおよび実行することで生成され、システム依存の定数と型に関する情報を提供します。

host-2 ビルドステージ


このステージでは、SBCL 用のオブジェクトファイル (FASL ファイル) が生成されます。オブジェクトファイルは、クロスコンパイラ版の compile-file を用いて、SBCL ソースコードを再度コンパイルすることで得られます。このとき、SBCL ソースコードの他に、host-1 ビルドステージで生成した Lisp ソースコードを併せて用いることで、クロスコンパイラ上の定数定義を、システム環境に応じたものに更新します。

genesis-2 ビルドステージ


続いて、genesis-2 ビルドステージに入ります。ここでは、host-1 で読み込んだ sb!vm:genesis を用いて、FASL ファイルのロードとメモリイメージの保存をシミュレートします。sb!vm:genesis が必要となる理由は、ホストコンパイラの load 関数では、SBCL の FASL 形式をロードできず、また、SBCL のターゲットイメージがまだ存在しないことからその load 関数を使うこともできないためです。

ここで行う処理は、次のように進みます。まず、特定の順序で擬似的に FASL ファイルをロードし、メモリイメージを展開します。次に、ターゲットのメモリ領域をバイト配列とみなし、FASL ファイルをロードしたときに起こるであろう処理をシミュレートします。この方法で実行できない処理は、ターゲットイメージの初期化関数が実行されるまで遅延されます。すべての FASL ファイルがこの方法で処理された後、メモリ領域を SBCL 実行形式が期待する形式でファイルに保存します。これで 'cold core' が生成されました。

最後に、'cold core' をメモリイメージとして、SBCL 実行形式を起動します ('cold init')。遅延されていたトップレベル・フォームの処理などは、このタイミングで実行されます。'cold init'は、助けになる Lisp デバッガが存在しないことから最もデバッグしづらいため、現在の SBCL のビルドプロセスにおいて、もっとも脆弱な箇所といえます。

target-2 ビルドステージ


SBCL のビルドプロセスの最終ステージが、target-2 ビルドステージです。まず、パッケージを最終的な名前に変更し、sb! プレフィックスを、sb- プレフィックスとします。次に、SBCL に特殊化されたバージョンの Portable Common Loops (PCL) をコンパイルし、ロードします。最後に、そうしてできた新しいメモリイメージを、output/sbcl.core として保存します。

これで、ビルドプロセスが完了しました。

まとめ


このエントリでは、SBCL のビルドプロセスを順を追って説明しました。SBCL のアプローチにもメリット・デメリットはありますが、このような仕組みでセルフ・ブートストラッピングを実現しているというのは、興味深いところです。

参考


SBCL - a Sanely-Bootstrappable Common Lisp
http://www.doc.gold.ac.uk/~mas01cr/papers/s32008/sbcl.pdf
 

2014年5月20日火曜日

Cl-reexport: symbol reexporting library for common lisp


Cl-reexport is a library to reexport symbols which are external symbols in other packages. It is valuable when virtually construct package hierarchy on Common Lisp standard's flat package system. 

https://github.com/takagi/cl-reexport 

ASDF 3 has similar one-package-per-file facility. The structural difference between them is: 


* Virtual hierarchy packages in this context have one system definition and several packages constituting a hierarchical structure. 

* ASDF 3's one-package-per-file style has hierarchical system definitions and hierarchical packages, which are corresponding each other. 

Since ASDF 3's one-package-per-file style has not been de facto standard yet, there may be some cases where cl-reexport is useful. 

Currently requesting to Quicklisp to register. 

I want your feedback.