#ifndef VALUE_VISITORS_HPP #define VALUE_VISITORS_HPP /** * \file value_visitors.hpp * implements various value visitors that give * useful functionality for values */ namespace BMD { //! prints values class output_visitor : public static_visitor<> { public: // output_visitor() : out(cout), print_full(false) { } output_visitor(ostream& o = cout, bool _print_full = false) : out(o), print_full(_print_full) { } void operator() (int i) const; void operator() (double d) const; void operator() (string s) const; void operator() (ListRef l) const; void operator() (BlockRef a) const; void operator() (const NullValue& nv) const; ostream& out; private: bool print_full; void print_as_tuple(BlockRef b, char start_char, char end_char) const; void print_reference(BlockRef b) const; }; /** * determines if a value is of a particular type */ template class is_type_visitor : public static_visitor { public: bool operator() (T t) const { return true; } template bool operator() (U u) const { return false; } }; /** * casts the value to a specified type * and throws a type error if the value is of an incorrect type */ template class assert_type_visitor : public static_visitor { public: T operator() (T t) const { return t; } T operator() (const NullValue& nv) const { throw null_value_error(""); } template T operator() (const U& u) const { throw type_error("incorrect type"); } }; /** * assigns a name to a given type */ class typename_visitor : public static_visitor { public: string operator() (int i) const { return "int"; } string operator() (double d) const {return "float"; } string operator() (string s) const { return "string"; } string operator() (ListRef l) const { return "list"; } string operator() (BlockRef a) const; string operator() (const NullValue& nv) const { return "null-value"; } }; /** determines equality of given values */ class equals_visitor : public static_visitor { public: bool operator() (int a, int b) const { return a == b; } bool operator() (double a, double b) const { return a == b; } bool operator() (int a, double b) const { return a == b; } bool operator() (double a, int b) const { return a == b; } bool operator() (string a, string b) const { return a == b; } bool operator() (ListRef a, ListRef b) const { return a == b; } bool operator() (BlockRef a, BlockRef b) const { return a == b; } bool operator() (NullValue a, NullValue b) const { return true; } template bool operator() (const U& u, const V& v) const { return false; } }; /** * clones the given type */ class clone_visitor : public boost::static_visitor { public: clone_visitor(bool _deep) : deep(_deep) { } Value operator() (int i) const; Value operator() (double d) const; Value operator() (string s) const; Value operator() (ListRef l) const; Value operator() (BlockRef a) const; Value operator() (NullValue nv) const; private: bool deep; }; /** * retrives the length of a value where having a length makes sense */ class length_visitor : public boost::static_visitor { public: unsigned int operator()(string s) const { return s.size(); } unsigned int operator()(ListRef l) const { if (l.get() == 0) return 0; return l->length(); } unsigned int operator()(BlockRef b) const { return b->get_size(); } UNARY_DEFAULT_TO_TYPE_ERROR("length", unsigned int, "expects a length, string, or block") }; } #endif