#include #include #include #include #include #include #include #include #include class Type { public: virtual void print(void) const = 0; }; // The toy IR class IntType : public Type { int sz; public: IntType(int s) : sz(s) {}; int size(void) const { return sz; } void print(void) const { std::cout << "int" << size(); } }; class TypeList : public Type { typedef std::vector > ListType; ListType types; void push_back(std::tr1::shared_ptr t) { types.push_back(t); } public: TypeList(std::tr1::shared_ptr member) { types.push_back(member); } template TypeList(Sequence members) { // Add the member types. typedef typename boost::fusion::result_of::begin::type begType; typedef typename boost::fusion::result_of::end::type endType; unsigned dist = boost::fusion::result_of::distance::type::value; std::cout << dist << " members for list" << std::endl; boost::fusion::for_each(members, boost::bind(&TypeList::push_back, this, _1)); } void print(void) const { std::cout << "Type list members:\n"; for (ListType::const_iterator i = types.begin(); i != types.end(); ++i) { (*i)->print(); std::cout << std::endl; } } }; template std::tr1::shared_ptr translate(const Expr &e); // The grammar namespace keyword { struct list { friend std::ostream& operator<<(std::ostream& sout, list) { return sout << "list"; } }; struct int_ { friend std::ostream& operator<<(std::ostream& sout, int_) { return sout << "int_"; } }; } class Domain; template struct Wrapper { BOOST_PROTO_EXTENDS(Expr, Wrapper, Domain) }; typedef Wrapper >::type> StringTerminal; typedef Wrapper::type> ListTerminal; typedef Wrapper::type> IntTerminal; typedef Wrapper >::type> IntegerTerminal; // Matches int_() struct IntRule : boost::proto::function< IntTerminal, IntegerTerminal > {}; struct TypeListBody; struct StrictTypeList : boost::proto::comma< TypeListBody, IntRule > {}; // Matches {, }* struct TypeListBody : boost::proto::or_< IntRule, StrictTypeList > {}; // Matches list[ {, }* ] struct TypeListRule : boost::proto::subscript< ListTerminal, TypeListBody > {}; struct TypeRule : boost::proto::or_< IntRule, TypeListRule > {}; // Grammar actions template struct UnaryConstructSymbol : boost::proto::callable { typedef std::tr1::shared_ptr result_type; template result_type operator()(Arg a) { std::tr1::shared_ptr sym(new SymbolType(a)); return sym; } }; /// This is a callable transform to translate a proto expression /// to a symbol. template class TranslateToSymbol : boost::proto::callable { public: typedef std::tr1::shared_ptr result_type; template result_type operator()(const Expr &e) const { std::cout << "Translating to symbol:\n"; boost::proto::display_expr(e); return translate(e); } }; /// This is the grammar to build integer types struct IntBuilder : boost::proto::when< IntRule, UnaryConstructSymbol(boost::proto::_value(boost::proto::_right)) > {}; namespace detail { // Some helpers to translate type lists // Translate a list of size > 1 template class TranslateListImpl { public: template ResultType operator()(const List typeList) { TranslateToSymbol translator; return boost::fusion::transform( boost::proto::flatten(typeList), translator); }; }; // Translate a list of size 1 template class TranslateListImpl { public: template ResultType operator()(const List typeList) { return TranslateToSymbol()(typeList); } }; // Choose whether to translate a single type or a list of types template class TranslateList { public: typedef typename boost::mpl::if_< boost::proto::matches, typename boost::fusion::result_of::transform< const typename boost::proto::result_of::flatten::type, TranslateToSymbol >::type, std::tr1::shared_ptr >::type result_type; result_type operator()(const List theList) { return TranslateListImpl::value>()(theList); }; }; template typename TranslateList::result_type translateList(List typeList) { return TranslateList()(typeList); } } /// This is a callable transform to construct a type list. struct ConstructTypeList : boost::proto::callable { typedef std::tr1::shared_ptr result_type; template result_type operator()(List memberList) { std::cout << "Building type list:\n"; boost::proto::display_expr(memberList); return UnaryConstructSymbol()(detail::translateList(memberList)); } }; // This is the grammar to construct type lists struct TypeListBuilder : boost::proto::when< TypeListRule, ConstructTypeList( // Member type list boost::proto::_right) > {}; // This is the grammar to construct types struct TypeBuilder : boost::proto::or_< IntBuilder, TypeListBuilder > {}; struct Domain : boost::proto::domain > {}; const ListTerminal list = {{}}; const IntTerminal int_ = {{}}; // Some helpers template void checkMatch(const Expr &expr) { BOOST_MPL_ASSERT(( boost::proto::matches )); } template void checkNotMatch(const Expr &expr) { BOOST_MPL_ASSERT(( !boost::proto::matches )); } template std::tr1::shared_ptr translate(const Expr &expr) { std::cout << "Translating:\n"; boost::proto::display_expr(expr); checkMatch(expr); TypeBuilder trans; return trans(expr); } int main(void) { std::tr1::shared_ptr type = translate( int_(32) ); type->print(); std::cout << std::endl; std::tr1::shared_ptr singlelist = translate( list [ int_(32) ] ); singlelist->print(); checkMatch(( int_(32), int_(16), int_(64) )); checkNotMatch(( int_(32) )); std::tr1::shared_ptr typelist = translate( list [ int_(32), int_(16), int_(64) ] ); typelist->print(); return 0; }