はじめての処理系実装 その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と違い、評価結果にバインドされた値を返すようにする。