#include #include #include #include #include #include using namespace std; namespace mpl=boost::mpl; namespace proto=boost::proto; using proto::_; template struct arg {}; proto::terminal > >::type const _1 = {{}}; proto::terminal > >::type const _2 = {{}}; proto::terminal > >::type const _3 = {{}}; template struct func {}; struct _map {}; proto::terminal<_map>::type const map = {{}}; struct _symbol_table_tag {}; //// Eval would be used to actually evaluate a function //// invocation of module.func(x,y,z), as opposed to //// simply creating the symbol table. This is incomplete. //struct Eval // : proto::or_< // proto::when< // proto::terminal< arg<_> > // , // TODO look up argument in state tuple // > // , proto::when< // proto::function< // proto::member< // proto::terminal<_symbol_table_tag> // the module // , proto::terminal< func<_> > // the function // > // , proto::vararg // > // , // TODO downcast the module to access the symbol // // table. Look up the function in the symbol table. // // Then evaluate the function. // > // , proto::otherwise< // proto::_default // > // > //{}; #define MK_FUNC_MEMBER(R, DATA, I, ELEM) ((func >, ELEM)) // Define the symbols. Probably should be parameterized on a // domain instead of (or in addition to) the symbol table. #define DECLARE_SYMBOL_TABLE(NAME, SYMBOLS) \ template \ struct NAME \ { \ typedef Module module_type; \ module_type derived() { return *static_cast(this); } \ module_type const derived() const { return *static_cast(this); } \ BOOST_PROTO_BASIC_EXTENDS( \ proto::terminal<_symbol_table_tag>::type \ , NAME \ , proto::default_domain \ ) \ BOOST_PROTO_EXTENDS_MEMBERS(BOOST_PP_SEQ_FOR_EACH_I(MK_FUNC_MEMBER, ~, SYMBOLS)) \ static NAME const self; \ }; \ template \ NAME const NAME::self = {} // Given a set of symbols and some declarations involving the // symbols, build a symbol table. #define DECLARE_MODULE(NAME, SYMBOLS, DECLS) \ struct NAME : SYMBOLS \ { \ typedef BOOST_TYPEOF(proto::deep_copy(DECLS)) table_type; \ table_type const table; \ NAME() \ : table(proto::deep_copy(DECLS)) \ {} \ } // This declares a bunch of symbols that we can later use // in a module to define function declarations DECLARE_SYMBOL_TABLE( symbol_table , (vadd) (negmul) (det_inverse) (vmul) (fib) (precondition) ); // This declares a module containing function declarations. DECLARE_MODULE( module , symbol_table , ( self.vadd = _1 + _2 , self.negmul = -self.vmul(_1, _2) , self.det_inverse = 1 / (_1 * _3 - _2 * _2) , self.vmul = _1 * _2 , self.fib = self.fib(_1 - 1) + self.fib(_1 - 2) , self.precondition = self.vmul(map(self.det_inverse, _1, _2, _3), _1) ) ); int main() { module mod; std::vector a, b, c; // Right now, this just creates an expression template // representing the expression. We'd need to hook this // to get it to actually evaluate the expression. mod.precondition(a, b, c); // This displays a very small tree because the decls // have been type-erased. All that type information is // available statically, so that's not a problem. proto::display_expr(mod.precondition(a, b, c)); }