#pragma once #include #include #include #include #include #include #include #include class bad_cast : public std::exception { std::string why; public: bad_cast( const std::type_index& f, const std::type_index& t ) : std::exception() { why = std::string{"bad cast of "} + f.name() + " to " + t.name(); } ~bad_cast() override = default; const char* what() const noexcept override { return why.c_str(); } }; template std::type_index class_of() { return { typeid(T) }; } class object { public: std::type_index get_class() const { return { this ? typeid(*this) : typeid(std::nullptr_t) }; } template T& as() { T* p = dynamic_cast(this); if ( !p ) throw bad_cast{ get_class(), class_of() }; return *p; } template const T& as() const { const T* p = dynamic_cast(this); if ( !p ) throw bad_cast{ get_class(), class_of() }; return *p; } virtual std::unique_ptr new_inst() const = 0; virtual std::unique_ptr new_copy() const = 0; virtual object& operator= (const object&) = 0; virtual ~object() = default; }; template std::unique_ptr as_ptr( std::unique_ptr&& p ) { return std::unique_ptr{ &p.release()->template as() }; } class ordered : public virtual object { public: virtual int cmp(const ordered&) const = 0; bool operator< (const ordered& that) const { return cmp(that) < 0; } bool operator<= ( const ordered& that ) const { return cmp(that) <= 0; } bool operator== ( const ordered& that ) const { return cmp(that) == 0; } bool operator!= ( const ordered& that ) const { return cmp(that) != 0; } bool operator> ( const ordered& that ) const { return cmp(that) > 0; } bool operator>= ( const ordered& that ) const { return cmp(that) >= 0; } }; class printable : public virtual object { public: virtual void print(std::ostream&) const = 0; }; class boolean : public ordered, public printable { bool x; public: boolean() = default; boolean(bool x) : x(x) {} std::unique_ptr new_inst() const override { return std::make_unique(); } std::unique_ptr new_copy() const override { return std::make_unique(*this); } boolean& operator= (const boolean& that) { x = that.x; return *this; } object& operator= (const object& that) override { return *this = that.as(); } /***/ ~boolean() override = default; int cmp(const boolean& that) const { return x == that.x ? 0 : x == false ? -1 : 1; } int cmp(const ordered& that) const override { return cmp( that.as() ); } /***/ void print(std::ostream& out) const override { out << (x ? "true" : "false"); } }; class character : public ordered, public printable { char x; public: character() = default; character(char x) : x(x) {} std::unique_ptr new_inst() const override { return std::make_unique(); } std::unique_ptr new_copy() const override { return std::make_unique(*this); } character& operator= (const character& that) { x = that.x; return *this; } object& operator= (const object& that) override { return *this = that.as(); } /***/ ~character() override = default; int cmp(const character& that) const { return x == that.x ? 0 : x < that.x ? -1 : 1; } int cmp(const ordered& that) const override { return cmp( that.as() ); } /***/ void print(std::ostream& out) const override { if ( 0x20 <= x && x <= 0x7E ) { out << "'" << x << "'"; } else { out << "'\\" << std::hex << (unsigned int)x << std::setbase(0) << "'"; } } }; class integer : public ordered, public printable { int x; public: integer() = default; integer(int x) : x(x) {} std::unique_ptr new_inst() const override { return std::make_unique(); } std::unique_ptr new_copy() const override { return std::make_unique(*this); } integer& operator= (const integer& that) { x = that.x; return *this; } object& operator= (const object& that) override { return *this = that.as(); } /***/ ~integer() override = default; int cmp(const integer& that) const { return x == that.x ? 0 : x < that.x ? -1 : 1; } int cmp(const ordered& that) const override { return cmp( that.as() ); } /***/ void print(std::ostream& out) const override { out << x; } }; class c_string : public printable { static constexpr const char* empty = ""; const char* s; public: c_string() : s(empty) {} c_string(const char* s) : s(s) {} std::unique_ptr new_inst() const override { return std::make_unique(); } std::unique_ptr new_copy() const override { return std::make_unique(s); } c_string& operator= (const c_string& that) { s = that.s; return *this; } object& operator= (const object& that) override { return *this = that.as(); } /***/ ~c_string() override = default; void print(std::ostream& out) const override { out << s; } }; class pair : public ordered, public printable { std::unique_ptr x; std::unique_ptr y; public: pair() = default; pair(std::unique_ptr&& x, std::unique_ptr&& y) : x(std::move(x)), y(std::move(y)) {} std::unique_ptr new_inst() const override { return std::make_unique(); } std::unique_ptr new_copy() const override { return std::make_unique(x->new_copy(), y->new_copy()); } pair& operator= (const pair& that) { x = that.x->new_copy(); y = that.y->new_copy(); return *this; } object& operator= (const object& that) override { return *this = that.as(); } /***/ ~pair() override = default; int cmp(const pair& that) const { int c = x->as().cmp( that.x->as() ); /***/ if ( c != 0 ) return c; return y->as().cmp( that.y->as() ); /***/ } int cmp(const ordered& that) const override { return cmp( that.as() ); } void print(std::ostream& out) const override { out << "["; x->as().print(out); /***/ out << ", "; y->as().print(out); /***/ out << "]"; } };