文字列からシンボル取りたい。

文字列からシンボルがほしいときがたまにあります。
たとえば

a = 2;
b = 3;
assert(u!("a + b = #{a+b}") == "a + b = 5");

みたいな物を作りたいときとか。
というか今日の更新はそんなのを作ろうとして、あまりにめんどくて挫折した残骸だったり


が、そんな機能はDにないので自前で頑張りましょう。
とりあえず適当に("a",a)のようなタプルのリストを予め作ってみました。
当然、用意してない識別子は使用不可(使えねー)
適当にこんな感じに作った。
http://d.shinh.org/html/toy/kurimura/symtable.html


読めばわかると思いますけど超力任せ。これは、ひどい。
こんなん自力で書いてられんので、
スクリプトで自動生成してるからまだマシ?
http://d.shinh.org/html/toy/kurimura/tablegen.html


とりあえず利用例

import symtable;
void main(){
	void loop(int n){
		// シンボルテーブルの作成
		mixin SymTable;
		// nという名前をテーブルから取り出してシンボルを得る
		if(getId!("n")==0)return; 
		getId!("printf")("%d\n",getId!("n"));
		getId!("loop")(getId!("n")-1);
	}
	loop(10);
}

ついでに文字列で計算をさせてみた。

int flag;
int main(){
	if(flag == 0) flag =1;
	else return 100;
	int a = 2,b = 3,c=10;
	/**
		Calc型を使ったオブジェクト指向プログラミング
	 */
	// Calc型のインスタンス変数dを生成
	mixin Calc d;
	
	//dに計算をさせてみる。戻り値はr
	mixin d.calc!("a+b+c+main") r;
	
	//rのメンバ変数に結果が入ってるので表示
	printf("%d\n",r.result);
	return 0;
}
import symtable;
template find(char[]s,char c){
	static if(s.length == 0)const find = 0;
	else static if(s[0] == c)const find = 0;
	else const find = .find!(s[1..s.length],c)+1;
}
template Calc(){
	mixin SymTable;
	//D言語はカリー化をサポートしています。
	alias .calc!(getId) calc;
}
template calc(alias getId){
	template calc(char[]s){
		static if(s.length == 0)auto result = 0;
		else static if(find!(s,'+')==s.length)alias getId!(s) result;
		else{mixin calc!(s[find!(s,'+')+1..$]) right;
			auto result = getId!(s[0 .. find!(s,'+')]) + right.result;
		}
	}
}

...うーん自分で書いててなんだけど、コレはなんの役にも立たなさそ。
色々とDの制限*1を越えるために汚くなってるし。
というか、やっぱ組み込みでシンボルを取る機能ください。Walterたん

*1:典型的なのは関数の中でtemplateを定義できない