#ifndef VALUE_HPP__ #define VALUE_HPP__ /** * \file value.hpp * \author Mason Smith * Contains definitions for the various parts of the Value class, * is a variant type for all runtime values */ #include #include #include #include #include #include #include #include "exception.hpp" using boost::variant; using boost::shared_ptr; using boost::shared_array; using boost::static_visitor; using boost::recursive_wrapper; using std::vector; using std::ostream; using std::cout; using std::endl; /** * Should be used at the end of each binary instruction * to default throw type errors when the arguments aren't otherwise suitable. */ #define BINARY_DEFAULT_TO_TYPE_ERROR(name, error) \ Value operator() (const NullValue& nv1, const NullValue& nv2) const \ { \ throw null_value_error(name + string(": uninitialized value used")); \ } \ template \ Value operator() (const NullValue& nv, const VqVwV& v) const \ { \ throw null_value_error(name + string(": uninitialized value used")); \ } \ template \ Value operator() (const UqUwU& v, const NullValue& nv) const \ { \ throw null_value_error(name + string(": uninitialized value used")); \ } \ template \ Value operator() (const UqUwU& u, const VqVwV& v) const \ { throw type_error(error); } \ #define UNARY_DEFAULT_TO_TYPE_ERROR(name, ret, error) \ ret operator() (const NullValue& nv) const \ { \ throw null_value_error(name + string(": uninitialized value used"));\ } \ template \ ret operator() (const UqUwU& u) const { throw type_error(error); } namespace BMD { class List; class Block; class NullValue { }; typedef shared_ptr ListRef; typedef shared_ptr BlockRef; typedef variant, int, double, string, recursive_wrapper< BlockRef >, NullValue > ValueBase; /** * Represents runtime values in the virtual machine. */ class Value : public ValueBase { public: Value() : ValueBase(NullValue()) { } explicit Value(bool b) : ValueBase(b ? 1 : 0) { } explicit Value(int i) : ValueBase(i) { } explicit Value(double d) : ValueBase(d) { } explicit Value(string s) : ValueBase(s) { } Value(ListRef l) : ValueBase(l) { } Value(BlockRef b) : ValueBase(b) { } /**** type-specific access ****/ int get_int() const; double get_float() const; string get_string() const; ListRef get_list() const; ListRef get_nonempty_list() const; BlockRef get_block() const; BlockRef get_array() const; BlockRef get_struct() const; BlockRef get_reference() const; //! Returns a string representing the value's type string get_type() const; // returns true if the value is of a certain type template bool is_type() const; //! copy the value Value clone() const; //! deep-copy the value Value deep_clone() const; //! return a string representation of the value string to_string() const; //! equality bool operator==(const Value& v) const; // parsing static Value parse_value(string s); static Value parse_numeric_value(string s); // print void print(ostream& o, bool print_full = false) const; protected: template T get(string expected) const; }; ostream& operator <<(ostream& o, const Value& v); /** * List runtime value * cons-based immutable list value */ class List { public: List(const Value& _car, ListRef _cdr) : car(_car), cdr(_cdr) { } Value get_car() const { return car; } ListRef get_cdr() const { return cdr; } void set_car(Value _car) { car = _car; } void set_cdr(ListRef _cdr) { cdr = _cdr; } unsigned int length(); // construct a list from a vector of elements static ListRef from_vector(const vector& args); private: List(const List& l); List& operator=(const List& l); protected: Value car; ListRef cdr; }; /** * Block runtime value * runtime safe array value */ class Block { public: enum Tag { Array = 0, Struct, Reference }; Block(vector& v, Tag tag = Array); Block(Value* v, int _size, Tag tag = Array); Block(int _size, Tag tag = Array); Value operator[](int i) const { return get_elem(i); } Value get_elem(int i) const; void set_elem(int i, const Value& v); unsigned int get_size() const { return size; } Tag get_tag() const { return tag; } // default copy construtor and assignment // operator are fine protected: Block(const Block& b); Block& operator=(const Block& b); int assert_in_range(int i) const; shared_array values; unsigned int size; Tag tag; }; } #include "value_visitors.hpp" namespace BMD { /** Returns true iff value is of the specified type */ template bool Value::is_type() const { return boost::apply_visitor(is_type_visitor(), *this); } } #endif