ゆにふぁいやー
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 ); } };
昨日のよりは直観的に書ける。と思う。いや、こんな適当な説明で僕以外の人間がわかるのか?いや、いいんだよ。どうせ自分しか使わないし。