Let's start Scheme

2014-01-12

SBCLのPCLを読む

クラス再定義を実装するべPCLを参考にすることにした。ので、真面目に全部を読むわけではなく、defclassから下に続く処理を読むだけ。また、断定系で書いてあるけど、動作確認までしてるわけではないので、全ての断定系には「と思う」を付与して読むこと。上から順番に何をしているか書いてるので、読み終わるころにはPCLのdefclassが何をしているのか分かる(と思う、補足して読むことw)。

defclass
単なるマクロ。一応defstructで定義されたものも裁けるようになってるらしい。展開後はload-defclassを呼ぶ式になる。

load-defclass
defclassは単なるマクロなので、マクロ内で何かをするか、展開結果がクラスを作ることは容易に想像できると思う。じゃあ、その下請けの関数は何か?という話。
2種類あって、単にコンパイラに知らせる用のものと、実際にensure-classを呼ぶreal-load-defclassがある。PCLをブートする再には前者を使って、ブート後は後者を使う。

ensure-class
ロックをかけて渡されたクラスの名前からクラスを検索、ensure-class-using-classを呼ぶ

ensure-class-using-class
メソッド。ensure-classでクラスが見つかった場合と見つからなかった場合の2種類が定義されている。
前者はfrob-ensure-class-argsを呼んで見つかったメタクラスが再定義されるクラスを同じならchange-classを呼ぶ、違えば呼ばない。その後、reinitialize-instanceを呼んでインスタンスを更新する。メタクラスが違った場合はどうなるんだろう?
後者は単に普通の定義。(以下では言及されない)

change-class
メソッド。いくつか定義されてるけど、基本的にはCPLを調べて変更可能かのチェックをしたのち%change-classを呼ぶだけ。

%change-class
古いインスタンスと新しいインスタンス、このケースでは元クラスと新クラス、を受け取ってメモリ割付、スロットとメタクラスの交換をした後、update-instance-for-different-classを呼ぶ。

update-instance-for-different-class
基本的には何もせずshared-initializeに処理を委譲

shared-initialize
メソッド。プライマリのメソッドは一個なんだけど、クラス用に:beforeと:afterが定義されてる。(それ以外にもあるが。) 中身は後で読む。っが、見た感じ、クラスのスロットを詰めてるだけに見える。まぁ、initializeからも呼ばれるメソッドなので、ある意味当たり前か。

reinitialize-instance
メソッド。 プライマリはcheck-initargs-1呼んで何かしらチェックした後、shared-initializeを呼ぶ。
クラス用の:beforeではダイレクトサブクラスを除去したのちスロットの除去をしてる。
:afterではmap-dependentにupdate-dependentを呼ぶ手続きを渡している。何するかは今一不明。多分依存関係の解決。

基本的にはほぼ全ての手続きがメソッドなので、頑張ればいろいろ手を加えられそう。Sagittariusに組み込む場合ここまでは要らないので、下請け手続きは単なるlambdaにする気がする。

No comments:

Post a Comment