#include #include #include #include #include #include #include #include #include #include #include #include using std::tr1::bind; using std::tr1::placeholders::_1; using std::tr1::shared_ptr; namespace keyword { struct int_ { friend std::ostream& operator<<(std::ostream& sout, int_) { return sout << "int_"; } }; struct float_ { friend std::ostream& operator<<(std::ostream& sout, float_) { return sout << "float_"; } }; struct function { friend std::ostream& operator<<(std::ostream& sout, function) { return sout << "function"; } }; struct void_ { friend std::ostream& operator<<(std::ostream& sout, void_) { return sout << "void_"; } }; } class Domain; template struct Wrapper { BOOST_PROTO_EXTENDS(Expr, Wrapper, Domain) }; typedef Wrapper::type> IntegerTerminal; typedef Wrapper::type> IntTerminal; typedef Wrapper::type> FloatTerminal; typedef Wrapper::type> FunctionTerminal; typedef Wrapper::type> VoidTerminal; // int_() typedef boost::proto::function< IntTerminal, IntegerTerminal > IntRule; // float_() typedef boost::proto::function< FloatTerminal, IntegerTerminal > FloatRule; typedef boost::proto::or_< IntRule, FloatRule > SimpleTypeRule; struct TypeRule; /// Define a rule for a list of types. struct TypeList; typedef boost::proto::comma< TypeList, TypeRule > TypeListListPart; struct TypeList : boost::proto::or_< TypeRule, TypeListListPart > {}; // () typedef boost::proto::function< boost::proto::or_< VoidTerminal, TypeRule >, boost::proto::vararg > FunctionTypeWithArgsRule; // () typedef boost::proto::function< boost::proto::or_< VoidTerminal, TypeRule > > FunctionTypeWithoutArgsRule; typedef boost::proto::or_< FunctionTypeWithoutArgsRule, FunctionTypeWithArgsRule > FunctionTypeRule; #if 0 typedef FunctionTypeWithArgsRule FunctionTypeRule; #endif struct TypeRule : boost::proto::or_< SimpleTypeRule, FunctionTypeRule > {}; struct TypeAccessRule : TypeRule {}; struct FunctionTypeAccessRule : FunctionTypeRule {}; // The toy IR struct Type { virtual std::string getName(void) const = 0; void print(std::ostream &out) const { out << getName(); } }; struct IntType : Type { size_t Size; IntType(size_t s) : Size(s) {} std::string getName(void) const { return "int" + boost::lexical_cast(Size); } }; struct FloatType : Type { size_t Size; FloatType(size_t s) : Size(s) {} std::string getName(void) const { return "float" + boost::lexical_cast(Size); } }; struct FunctionType : Type { shared_ptr ReturnType; std::vector > ArgTypes; std::string getName(void) const { std::stringstream name; if (ReturnType) { name << ReturnType->getName() + "("; } else { name << "void("; } for (std::vector >::const_iterator a = ArgTypes.begin(), aend = ArgTypes.end(); a != aend; /* NULL */) { name << (*a)->getName(); if (++a != aend) { name << ','; } } name << ')'; return name.str(); } FunctionType(shared_ptr type) : ReturnType(type) {} template FunctionType(shared_ptr type, Sequence range) : ReturnType(type), ArgTypes(boost::fusion::begin(range), boost::fusion::end(range)) {} }; struct NameEqual : public std::binary_function, const std::string &, bool> { bool operator()(shared_ptr t, const std::string &name) { return t->getName() == name; } }; struct SymbolTable { typedef std::list > TypeList; std::list table; shared_ptr lookup(const std::string &name) { TypeList::iterator v = std::find_if(table.back().begin(), table.back().end(), bind(NameEqual(), _1, name)); if (v == table.back().end()) { return shared_ptr(); } return *v; } void addType(shared_ptr t) { table.back().push_back(t); } }; // Return a null pointer to Type. struct ConstructVoidType : boost::proto::callable { typedef shared_ptr result_type; result_type operator()(void) { return result_type(); } }; template std::string getName(Arg a, IntType *) { return "int" + boost::lexical_cast(a); } template std::string getName(Arg a, FloatType *) { return "float" + boost::lexical_cast(a); } template std::string getName(Arg a, FunctionType *) { std::stringstream name; if (a) { name << a->getName() << "()"; } else { name << "void()"; } return name.str(); } template std::string getName(Arg a, Sequence range, FunctionType *) { std::stringstream name; if (a) { name << a->getName() << "("; } else { name << "void("; } typedef typename boost::fusion::result_of::begin::type iterator; for (iterator i = begin(range), ie = end(range); i != ie; /* NULL */) { name << (*i)->getName(); if ((i = next(i)) != ie) { name << ','; } } name << ")"; return name.str(); } template< typename SymbolType, typename Dummy = boost::proto::callable> struct ConstructUnarySymbol : boost::proto::callable { typedef shared_ptr result_type; template result_type operator()(Arg a) { std::string name = getName(a, reinterpret_cast(0)); result_type result(new SymbolType(a)); if (name != result->getName()) { std::cerr << "Computed wrong name\n"; throw; } return result; } }; template< typename SymbolType, typename Dummy = boost::proto::callable> struct ConstructBinarySymbol : boost::proto::callable { typedef shared_ptr result_type; template result_type operator()(Arg1 a1, Arg2 a2) { //boost::fusion::transform_view ... std::string name = getName(a1, a2, reinterpret_cast(0)); result_type result(new SymbolType(a1, a2)); if (name != result->getName()) { std::cerr << "Computed wrong name\n"; throw; } return result; } }; struct LookupAndAddSymbol : boost::proto::callable { typedef shared_ptr result_type; result_type operator()(shared_ptr symtab, result_type symbol) { result_type result = symtab->lookup(symbol->getName()); if (!result) { symtab->addType(symbol); result = symbol; } else { symbol.reset(); } return result; } }; typedef boost::proto::when< VoidTerminal, ConstructVoidType() > VoidBuilder; /// This is the grammar for integral types. typedef boost::proto::when< IntRule, LookupAndAddSymbol( boost::proto::_data, ConstructUnarySymbol( boost::proto::_value(boost::proto::_right))) > IntBuilder; /// This is the grammar for floating point types. typedef boost::proto::when< FloatRule, LookupAndAddSymbol( boost::proto::_data, ConstructUnarySymbol( boost::proto::_value(boost::proto::_right))) > FloatBuilder; struct TypeBuilder; /// This is the grammar for function types. struct FunctionReturnTypeBuilder : boost::proto::or_< VoidBuilder, TypeBuilder > {}; struct FunctionTypeBuilder : boost::proto::or_< boost::proto::when< FunctionTypeWithoutArgsRule, LookupAndAddSymbol( boost::proto::_data, ConstructUnarySymbol( FunctionReturnTypeBuilder(boost::proto::_left))) >, boost::proto::when< FunctionTypeWithArgsRule, LookupAndAddSymbol( boost::proto::_data, ConstructBinarySymbol( FunctionReturnTypeBuilder(boost::proto::_left), // We really want a sequence of transformed expression operands here. // See ConstructBinarySymbol for a guess at how to use transform_view. boost::proto::functional::pop_front(boost::proto::_expr))) > > {}; #if 0 struct FunctionTypeBuilder : boost::proto::when< FunctionTypeWithArgsRule, LookupAndAddSymbol( boost::proto::_data, ConstructBinarySymbol( FunctionReturnTypeBuilder(boost::proto::_left), boost::proto::functional::pop_front(boost::proto::_expr))) > {}; #endif /// This is the grammar to construct types. struct TypeBuilder : boost::proto::or_< IntBuilder, FloatBuilder, FunctionTypeBuilder > {}; struct Domain : boost::proto::domain > {}; const VoidTerminal void_ = {{}}; const IntTerminal int_ = {{}}; template void checkMatch(const Expr &expr) { BOOST_MPL_ASSERT(( boost::proto::matches )); } template shared_ptr translate(const Expr &expr) { shared_ptr symtab(new SymbolTable); symtab->table.push_back(SymbolTable::TypeList()); checkMatch(expr); TypeBuilder trans; return trans(expr, 0, symtab); } int main(void) { boost::proto::display_expr( void_() ); boost::proto::display_expr( int_(32)() ); boost::proto::display_expr( void_(int_(32), int_(64)) ); shared_ptr type = translate( void_() ); type->print(std::cout); std::cout << '\n'; type = translate( int_(32)() ); type->print(std::cout); std::cout << '\n'; type = translate( void_(int_(32), int_(64)) ); type->print(std::cout); std::cout << '\n'; return 0; }