[Lisp処理系を作る] 11日目 オブジェクト比較と文字列化処理を作る

そろそろ核となる部分以外も固めはじめます。

オブジェクト比較

Lisp 上でオブジェクトの比較を出来るようにする。 Lisp の eq 関数での比較と同じ。

  • 基本的には実装依存になる部分もあるようだ。
    • 一応 xyzzy とあわせておく。
  • nil は nil 同士なら同じ
  • Integer は数値が同じなら同じ
  • Symbol は名前が同じなら同じ
  • それ以外は .NET 上のオブジェクトが同じなら同じ

各クラスで比較する方法が違うので SymbolicExpression クラスで以下のように定義する。 以下の LispEqThisType メソッドをオーバーライドして各クラスでの比較方法を記述する。

public bool LispEq( SymbolicExpression other ) {
  if ( this is Nil ) { return other is Nil; }
  if ( other is Nil ) { return false; }
  return this.LispEqThisType( other );
}
protected virtual bool LispEqThisType( SymbolicExpression other ) {
  return Object.ReferenceEquals( this, other );
}

文字列化

Lisp のオブジェクトを画面に出す際に文字列化する必要があるので文字列化処理を実装する。 メソッドは .NET の標準の文字列化メソッド ToString をオーバーライドして実装する。

Symbol
自身の名前
LString
内部で持っている文字列の両端に二重引用符を付加したもの。
Integer
内部で持っている int の文字列化
Function
"#<" と ">" で囲った中に適当に情報(引数リストなど)を埋め込む

List の文字列化

List は Lisp の中でも中核を担うオブジェクトであり、文字列化処理は多少複雑である。

  • List の Size が 2 の場合
    • その List の一つ目が Symbol の "quote" の場合は "'" を先頭に付け List の 2 つめの文字列化したものを記述する。
    • その List の一つ目が Symbol の "function" の場合は "#'" を先頭に付け List の 2 つめの文字列化したものを記述する。
  • 通常の場合
    • "(" で始まり
    • 先頭から順番に文字列化したのを記述
    • 間には空白を入れる
    • 次が List なら続く
    • 次が Nil なら ")" で閉じる
    • 次が Atom なら "." でつないで")" で閉じる

だいたいこんな感じ。詳しい処理はソースを参照して。

これまでの成果