C++でcompile time Schemeをつくってみる計画
こんなことばかりしてるとSchemeが病的に好きな人みたいに思われそうですが、特にそういうこともありません(それどころかSchemeでまともなプログラムを組んだこともない始末)。
それはともかく、Generic ProgrammingとかModern C++ Designとか読んでたら非常にむらむらしてたのでなんかつくってみた。変数ルックアップのとこだけ。
//boost/preprocessorでなんとかならんのかな #define LIST0() nil #define LIST1(l1) Cons<l1,LIST0()> #define LIST2(l1,l2) Cons<l1,LIST1(l2)> #define LIST3(l1,l2,l3) Cons<l1,LIST2(l2,l3)> #define LIST4(l1,l2,l3,l4) Cons<l1,LIST3(l2,l3,l4)> #define LIST5(l1,l2,l3,l4,l5) Cons<l1,LIST4(l2,l3,l4,l5)> //data types template<int n> struct int_value { enum {value=n;}; }; template<char c> struct symbol {}; struct nil {}; template<typename CA,typename CD> struct Cons { typedef CA car; typedef CD cdr; }; template<typename Args,typename Body> struct lambda { typedef typename Body body; typedef typename Args args; }; //environment #define DECLARE_ENV(name) \ template<typename P> \ struct name { \ typedef P parent; \ template<typename Sym> struct lookup { \ typedef typename parent::lookup<Sym>::result result; \ }; #define BIND_SYMBOL(sym,val) \ template<> struct lookup< symbol<sym> > { \ typedef typename val result; \ }; #define END_ENV() \ }; //eval constant template<typename S,class Env> struct Evaluator { typedef S result; }; //eval symbol template<char c,class Env> struct Evaluator<symbol<c>,Env> { typedef typename Env::lookup<symbol<c> >::result result; }; //eval list template<typename F,typename Arglist,typename Env> struct Evaluator<Cons<F,Arglist>,Env> { }; //to dynamic world template<typename T> struct to_dynamic { }; template<int n> struct to_dynamic<int_value<n> > { static int value() { return n; } }; DECLARE_ENV(e1) BIND_SYMBOL('x',int_value<100>); BIND_SYMBOL('y',int_value<200>); BIND_SYMBOL('z',LIST3(int_value<200>,int_value<100>,int_value<300>)); END_ENV() DECLARE_ENV(e2) BIND_SYMBOL('x',int_value<111>); BIND_SYMBOL('a',int_value<999>); END_ENV() #include <iostream> using namespace std; int _tmain(int argc, _TCHAR* argv[]) { typedef e1<nil> env; typedef e2<env> env2; cout << to_dynamic<Evaluator<symbol<'x'>,env >::result>::value() << endl; //100 cout << to_dynamic<Evaluator<symbol<'x'>,env2 >::result>::value() << endl; //111 cout << to_dynamic<Evaluator<int_value<999>,nil>::result>::value() << endl; //999 }