ゆにふぁいやー

Identifierはなんて読むんだろうか。いや、それは別にいいや。眠いのでメモだけしとく。酔ってるし。明日は実装頑張るように > 自分。


三日間くらいSWI-Prologのソース読んで単一化の実装は大体わかったので、うにゃうにゃする。
まず、中身をPrologにする必要は無い。unifierにプログラムを溜めていって、最後にrun、というのはなくてもいいはず。

// 中のスタックにふたつ値を積む
unifier.push( ... );
unifier.push( ... );


// スタックの上ふたつでunify
// unifyした結果の値なり変数なり参照なりはスタックの上に置いとく
unifier.unify();

基本は、push、pop、unifyのみっつで処理する。構文木から無理矢理Prologコードを生成するよりは楽にできる。効率もこっちのほうが良いはず。構文木の各ノードにinfer_typeメソッドのようなものを入れといて、なんかぐにょぐにょ。

// 二項演算子
var plus_node = object {
	var lhs = ...;
	var rhs = ...;
	function infer_type( unifier ) {
		lhs.infer_type(unifier);
		rhs.infer_type(unifier);

		unifier.unify();

		if ( unifier.is_top_var() ) { 
			unifier.top.add_hook( this, function(obj,val) { obj.type = val } );
		} else {
			this.type = unifier.top.value;
		}
	}
};

あー、そうか、スタックトップに対する操作が必要だな。あ、obj.type=valはもうほぼ決まりなんだから、いちいち関数書きたくないよな。やっぱ、getslotは用意しちゃおう。

unifier.top.add_slot( getslot this.type );
var type_var = unifier.gen_var( getslot this.type );

いや、getslotは記号にしちゃえ。

unifier.top.add_slot( &this.type );
var type_var = unifier.gen_var( &this.type );

うん。Cに毒されてる感じがして良い。

// 関数呼び出し
var call_node = object {
	var argtype;
	var args;
	var rettype;

	function infer_type( unifier ) {
		args.map( ... なんか );
		var rettype_var = unifier.gen_var( .. );
		unifier.push( rettype_var );
	}
};

昨日のよりは直観的に書ける。と思う。いや、こんな適当な説明で僕以外の人間がわかるのか?いや、いいんだよ。どうせ自分しか使わないし。