#ifdef __GNUC__ # undef __STRICT_ANSI__ //declare snprintf for GCC -std=c++0x #endif #define BOOST_TEST_NO_LIB #include #include #include "tagged_object.h" BOOST_AUTO_TEST_SUITE(tagged_object) // // Syntax Tree // struct Expr; typedef boost::shared_ptr ExprPtr; struct Location { const int line; const int column; Location(int line, int column): line(line), column(column){} }; struct ASTNodeInfo { const Location loc; explicit ASTNodeInfo(const Location &loc):loc(loc){} virtual ~ASTNodeInfo(){} }; struct Expr : tagged_object::TaggedBase, ASTNodeInfo { struct DerivedTypes; explicit Expr(const Location &loc) : ASTNodeInfo(loc){} }; struct TAGGED_DERIVED(ConstI32, Expr) { const int value; ConstI32(int value, const Location &loc) : TaggedDerived(loc), value(value){} }; struct TAGGED_DERIVED(ConstF64, Expr) { const double value; ConstF64(double value, const Location &loc) : TaggedDerived(loc), value(value){} }; struct TAGGED_DERIVED(BinaryOperator, Expr) { const ExprPtr lhs; const ExprPtr rhs; BinaryOperator(const ExprPtr &lhs, const ExprPtr &rhs, const Location &loc) : TaggedDerived(loc), lhs(lhs), rhs(rhs){} }; struct Expr::DerivedTypes { typedef boost::mpl::list< ConstI32, ConstF64, BinaryOperator > Types; }; // // Expression to String // struct Printer { // reference std::string operator()(ConstI32 &v) { return "nonconst->nonconst I32(" + boost::lexical_cast(v.value) + ")"; } std::string operator()(ConstF64 &v) { return "nonconst->nonconst F64(" + boost::lexical_cast(v.value) + ")"; } std::string operator()(BinaryOperator &v) { return "nonconst->nonconst BinOp(" + tagged_object::dispatch(*this, v.lhs) + "," + tagged_object::dispatch(*this, v.rhs) + ")"; } std::string operator()(ConstI32 &v) const { return "const->nonconst I32(" + boost::lexical_cast(v.value) + ")"; } std::string operator()(ConstF64 &v) const { return "const->nonconst F64(" + boost::lexical_cast(v.value) + ")"; } std::string operator()(BinaryOperator &v) const { return "const->nonconst BinOp(" + tagged_object::dispatch(*this, v.lhs) + "," + tagged_object::dispatch(*this, v.rhs) + ")"; } std::string operator()(const ConstI32 &v) { return "nonconst->const I32(" + boost::lexical_cast(v.value) + ")"; } std::string operator()(const ConstF64 &v) { return "nonconst->const F64(" + boost::lexical_cast(v.value) + ")"; } std::string operator()(const BinaryOperator &v) { return "nonconst->const BinOp(" + tagged_object::dispatch(*this, v.lhs) + "," + tagged_object::dispatch(*this, v.rhs) + ")"; } std::string operator()(const ConstI32 &v) const { return "const->const I32(" + boost::lexical_cast(v.value) + ")"; } std::string operator()(const ConstF64 &v) const { return "const->const F64(" + boost::lexical_cast(v.value) + ")"; } std::string operator()(const BinaryOperator &v) const { return "const->const BinOp(" + tagged_object::dispatch(*this, v.lhs) + "," + tagged_object::dispatch(*this, v.rhs) + ")"; } // shared_ptr std::string operator()(const boost::shared_ptr &v) { return "nonconst->sp nonconst I32(" + boost::lexical_cast(v->value) + ")"; } std::string operator()(const boost::shared_ptr &v) { return "nonconst->sp nonconst F64(" + boost::lexical_cast(v->value) + ")"; } std::string operator()(const boost::shared_ptr &v) { return "nonconst->sp nonconst BinOp(" + tagged_object::dispatch(*this, v->lhs) + "," + tagged_object::dispatch(*this, v->rhs) + ")"; } std::string operator()(const boost::shared_ptr &v) const { return "const->sp nonconst I32(" + boost::lexical_cast(v->value) + ")"; } std::string operator()(const boost::shared_ptr &v) const { return "const->sp nonconst F64(" + boost::lexical_cast(v->value) + ")"; } std::string operator()(const boost::shared_ptr &v) const { return "const->sp nonconst BinOp(" + tagged_object::dispatch(*this, v->lhs) + "," + tagged_object::dispatch(*this, v->rhs) + ")"; } std::string operator()(const boost::shared_ptr &v) { return "nonconst->sp const I32(" + boost::lexical_cast(v->value) + ")"; } std::string operator()(const boost::shared_ptr &v) { return "nonconst->sp const F64(" + boost::lexical_cast(v->value) + ")"; } std::string operator()(const boost::shared_ptr &v) { return "nonconst->sp const BinOp(" + tagged_object::dispatch(*this, v->lhs) + "," + tagged_object::dispatch(*this, v->rhs) + ")"; } std::string operator()(const boost::shared_ptr &v) const { return "const->sp const I32(" + boost::lexical_cast(v->value) + ")"; } std::string operator()(const boost::shared_ptr &v) const { return "const->sp const F64(" + boost::lexical_cast(v->value) + ")"; } std::string operator()(const boost::shared_ptr &v) const { return "const->sp const BinOp(" + tagged_object::dispatch(*this, v->lhs) + "," + tagged_object::dispatch(*this, v->rhs) + ")"; } }; BOOST_AUTO_TEST_CASE(dispatch_test) { using tagged_object::dispatch; const boost::shared_ptr v1( new ConstI32(1, Location(11, 21)) ); const boost::shared_ptr v2( new ConstF64(1.25, Location(12, 22)) ); const boost::shared_ptr v3( new BinaryOperator(v1, v2, Location(13, 23)) ); const boost::shared_ptr v1c = v1; const boost::shared_ptr v2c = v2; const boost::shared_ptr v3c = v3; Printer p; // reference BOOST_CHECK_EQUAL(dispatch(p, *v1), "nonconst->nonconst I32(1)"); BOOST_CHECK_EQUAL(dispatch(p, *v2), "nonconst->nonconst F64(1.25)"); BOOST_CHECK_EQUAL(dispatch(p, *v3), "nonconst->nonconst BinOp(nonconst->sp nonconst I32(1),nonconst->sp nonconst F64(1.25))"); BOOST_CHECK_EQUAL(dispatch(Printer(), *v1), "const->nonconst I32(1)"); BOOST_CHECK_EQUAL(dispatch(Printer(), *v2), "const->nonconst F64(1.25)"); BOOST_CHECK_EQUAL(dispatch(Printer(), *v3), "const->nonconst BinOp(const->sp nonconst I32(1),const->sp nonconst F64(1.25))"); BOOST_CHECK_EQUAL(dispatch(p, *v1c), "nonconst->const I32(1)"); BOOST_CHECK_EQUAL(dispatch(p, *v2c), "nonconst->const F64(1.25)"); BOOST_CHECK_EQUAL(dispatch(p, *v3c), "nonconst->const BinOp(nonconst->sp nonconst I32(1),nonconst->sp nonconst F64(1.25))"); BOOST_CHECK_EQUAL(dispatch(Printer(), *v1c), "const->const I32(1)"); BOOST_CHECK_EQUAL(dispatch(Printer(), *v2c), "const->const F64(1.25)"); BOOST_CHECK_EQUAL(dispatch(Printer(), *v3c), "const->const BinOp(const->sp nonconst I32(1),const->sp nonconst F64(1.25))"); // shared_ptr BOOST_CHECK_EQUAL(dispatch(p, v1), "nonconst->sp nonconst I32(1)"); BOOST_CHECK_EQUAL(dispatch(p, v2), "nonconst->sp nonconst F64(1.25)"); BOOST_CHECK_EQUAL(dispatch(p, v3), "nonconst->sp nonconst BinOp(nonconst->sp nonconst I32(1),nonconst->sp nonconst F64(1.25))"); BOOST_CHECK_EQUAL(dispatch(Printer(), v1), "const->sp nonconst I32(1)"); BOOST_CHECK_EQUAL(dispatch(Printer(), v2), "const->sp nonconst F64(1.25)"); BOOST_CHECK_EQUAL(dispatch(Printer(), v3), "const->sp nonconst BinOp(const->sp nonconst I32(1),const->sp nonconst F64(1.25))"); BOOST_CHECK_EQUAL(dispatch(p, v1c), "nonconst->sp const I32(1)"); BOOST_CHECK_EQUAL(dispatch(p, v2c), "nonconst->sp const F64(1.25)"); BOOST_CHECK_EQUAL(dispatch(p, v3c), "nonconst->sp const BinOp(nonconst->sp nonconst I32(1),nonconst->sp nonconst F64(1.25))"); BOOST_CHECK_EQUAL(dispatch(Printer(), v1c), "const->sp const I32(1)"); BOOST_CHECK_EQUAL(dispatch(Printer(), v2c), "const->sp const F64(1.25)"); BOOST_CHECK_EQUAL(dispatch(Printer(), v3c), "const->sp const BinOp(const->sp nonconst I32(1),const->sp nonconst F64(1.25))"); } BOOST_AUTO_TEST_SUITE_END()