D式: Lisp パワー, Dylan スタイル

DylanのD式の論文

http://people.csail.mit.edu/jrb/Projects/dexprs.pdf

を読もうといつもIntroductionだけ読んで挫折していたので、目次だけ作ってみました。

1 Abstract
1 要約
2 Introduction
2 序論
2.1 Successes and Failures
2.1 成功と失敗
2.2 Lisp Power, Dylan Style
2.2 Lispパワー,Dylanスタイル
2.3 Requirements and Goals
2.3 要件と目標
3 An Overview of Syntax Representations
3 構文表現の概要
3.1 Text-Based Representations
3.1 テキストベース表現
3.2 Token-Based Representations
3.2 字句ベース表現
3.3 Abstract Syntax Tree Representations
3.3 抽象構文木表現
3.4 Skeleton Syntax Tree Representations
3.4 スケルト構文木表現
4 Dylan's Rewrite-Rule Only Macro System
4 ディランの書換規則だけマクロシステム
4.1 Dylan's Rewrite Rules
4.1 ディランの書換規則
4.2 Dylan's Skeleton Syntax Tree
4.2 ディランのスケルト構文木
4.3 Source-level Pattern Matching
4.3 ソースレベルパターン・マッチング
4.4 Source-level Code Generation
4.4 ソースレベルコード生成
4.5 Example Macros
4.5 マクロの例
4.6 Hygiene
4.6 衛生
4.7 Local Rewrite Rules
4.7 ローカル書換規則
5 The D-Expressions Library
5 D式ライブラリ
5.1 Skeleton Syntax Tree Classes
5.1 スケルト構文木のクラス
5.2 Source-level Tools for Parsing
5.2 構文解析用ソースレベルツール
5.3 Source-level Tools for Code Generation
5.3 コード生成用ソースレベルツール
5.4 D-Expression IO
5.4 D式IO
6 Models of Compile-time Evaluation
6 コンパイル時評価モデル
6.1 Compile-time is Run-time
6.1 コンパイル時はランタイム
6.2 Static Compiler Plugins
6.2 静的なコンパイラプラグイン
6.3 Compile Time Loading and Eval-When
6.3 コンパイル時ローディングとEvalはいつ?
7 Status
7 状態
8 Related Work
8 関連研究
8.1 Lisp Macros
8.1 Lispマクロ
8.2 Scheme
8.2 Scheme
8.3 Weise and Crew
8.3 Weise と Crew
9 Summary
9 概要
Acknowledgements
確認
References
参照
A Auxiliary Macros
A 補助マクロ
B Dylan Rewrite-Rule Only Macro Extensions
ディラン書き換えオンリーマクロ展開
B.1 Template Calls
B.1 テンプレート呼び出し
C Limits of Rewrite-Rule Only Macro System
C 書き換え規則だけのマクロシステムの制限

定数畳み込みというか項書き換えシステムっぽい何か。

eクラスが式オブジェクトで、phpだと関数名とクラス名は同じもの使えるのでnewを書かなくてすむようにするためだけにe関数があります。
で、evalCompでコンパイル用の定数畳み込みっぽいことをする計算をしてグローバル変数の$chgという書き換えがあったかどうかフラグを
書き換えがあったら立てます。evalcでフラグを見てevalCompを繰り返し最大数分だけ呼び出します。
でif文を沢山書きたくないので型と演算子を文字列でくっつけて正規表現でマッチさせるというなんとも遅そうだけど短く書けるかもしれない手段を取ってみました。
対応している演算子は+と*だけで、しかも*はいまいちな対応です。
っていうことで、gccのソース*1
とかを見てみるけど、でかいので読む前に挫折。
うう、1万6千行とかある。。。うう。
mincamlの定数畳み込み*2は1+a+b+3は展開できないっぽい?
ということで、お、w_oさんの定数畳み込みがあった*3
ってことで、このソースは非常に恥ずかしいあまり意味のないものの気がしますが、まぁ、いいや。。。

<?
class e {
	function __construct($l, $op, $r = null) {
		$this->l = $l;
		$this->op = $op;
		$this->r = $r;
	}
}
function e($l, $op = null, $r = null) {
	return new e($l, $op, $r);
}

$chg = false;
function evalComp($e) {
	global $chg;
	switch ($e) {
	case $e instanceof e:
		$l = evalComp($e->l);
		$r = evalComp($e->r);
		$ls = is_integer($l)?"i":(is_string($l)?"s":"e");
		$rs = is_integer($r)?"i":(is_string($r)?"s":"e");
		$op2 = $ls.$e->op.$rs;
		echo $op2."\n";
		$op3="";
		switch (1) {
		case preg_match("/i[+]i/",$op2)>0: $chg = true; return $l+$r;
		case preg_match("/i[*]i/",$op2)>0: $chg = true; return $l*$r;
		case preg_match("/i[\\/]i/",$op2)>0: $chg = true; return $l/$r;
		case preg_match("/i[-]i/",$op2)>0: $chg = true; return $l-$r;
		case preg_match("/[is].e/",$op2)>0:
			$op3 = $ls . $e->op . (is_integer($r->l)?"i":(is_string($r->l)?"s":"e"))
			           . $r->op . (is_integer($r->r)?"i":(is_string($r->r)?"s":"e"));
			echo $op3."\n";
			switch(1){
			case preg_match("/.[*].[+]./", $op3)>0: $chg=true; return e(e($l, "*", $r->l), "*", e($l, "*", $r->r));
			}
			break;
		case preg_match("/e.[is]/",$op2)>0:
			$op3 = (is_integer($l->l)?"i":(is_string($l->l)?"s":"e")).$l->op.
			(is_integer($l->r)?"i":(is_string($l->r)?"s":"e")).$e->op.$rs;
			echo $op3."\n";
			break;
		}
		switch(1){
		case preg_match("/i[+].[+]i/", $op3)>0: $chg=true; return e($l + $r->r, "+", $r->l);
		case preg_match("/i[+]i[+]./", $op3)>0: $chg=true; return e($l + $r->l, "+", $r->r);
		case preg_match("/i[*].[*]i/", $op3)>0: $chg=true; return e($l * $r->r, "*", $r->l);
		case preg_match("/i[*]i[*]./", $op3)>0: $chg=true; return e($l * $r->l, "*", $r->r);
		case preg_match("/.[+]i[+]./", $op3)>0: $chg=true; return e($r->l, "+", e($l, "+", $r->r));
		case preg_match("/.[*]i[*]./", $op3)>0: $chg=true; return e($r->l, "*", e($l, "*", $r->r));
		case preg_match("/.[+].[+]i/", $op3)>0: $chg=true; return e($r->r, "+", e($l, "+", $r->l));
		case preg_match("/.[*].[*]i/", $op3)>0: $chg=true; return e($r->r, "*", e($l, "*", $r->l));
		}
		return e($l, $e->op, $r);
	default:
		return $e;
	}
}
function evalc($e) {
	global $chg;
	for($i=0;$i<100;$i++) {
		$chg = false;
		$e = evalComp($e);
//		if(!$chg) break;
		break;
	}
	return $e;
}
var_dump(evalc(e("a","+",e(2,"+",1))));
var_dump(evalc(e(1,"+",e(2,"+","a"))));
var_dump(evalc(e(3,"+",e("b","+",e(2,"+","a")))));
var_dump(evalc(e("b","+",e(1,"+",e(5,"+","a")))));
var_dump(evalc(e(1,"+",e("a","+",e("b","+",e(5,"+","c"))))));