はじめての処理系実装 その2

データ型クラスをいくつか実装しました。

数値型、文字列型、真偽値型

親クラスとして後で判定に役に立ちそうなのでAtomクラスを定義。
クラス名はそれぞれ、
Num(数値), Str(文字列), Bool(真偽値)。
標準パッケージjava.langに Number, String, Booleanがあるので、
同名にするとEclipseのコード補完やらが不便になる為、省略形で。

public class Num extends Atom {
	private int value;
	public Num(int value) {
		this.value = value;
	}

	public SymbolExp eval(Context ctx) {
		return this;
	}
}


Str, Boolも同じような感じ。
但しBoolは#Tと#Fしかないので、シングルトンモデルのように
コンストラクタをprivateにして静的に定義。

public static final Bool T = new Bool(true, "#T");
public static final Bool F = new Bool(false, "#F");

シンボルは工夫が必要

シンボルは同名で複数作られないようcreateメソッド経由で作成するようにする。

public class Symbol extends Atom {
	private final static Map<String, Symbol> cache = new HashMap<String, Symbol>();
	private String value;
	
	public static Symbol createSymbol(String value) {
		return cache.containsKey(value) ?
				cache.get(value) : new Symbol(value);
	}
	
	private Symbol(String value) {
		this.value = value;
		cache.put(value, this);
	}

	public SymbolExp eval(Context ctx) {
		return ctx.lookup(this);
	}
}

シンボルにバインドされた値はコンテキストに保存。
シンボルの評価のタイミングでルックアップする事で、
他のAtomと違い、評価結果にバインドされた値を返すようにする。

NIL

まぁ基本データ型は簡単。
・・・といいたいところだが一つポイントが。NILの扱いをどうするか。
すこし迷ったが環境に入れるのでシンボル扱いにして、
シンボルクラスに静的定義。

public static final Symbol NIL = new Symbol("nil");


とりあえず続く。