/////////////////////////////////////////////////////////////////////////////// // // Module : purescript.hh // Copyright : (c) Andy Arvanitis 2015 // License : MIT // // Maintainer : Andy Arvanitis // Stability : experimental // Portability : // // Basic types and functions to support purescript-to-C++1x rendering // /////////////////////////////////////////////////////////////////////////////// // #ifndef PureScript_HH #define PureScript_HH // Standard includes #if defined(DEBUG) #include #else #define NDEBUG #undef assert #define assert(x) #endif #include #include #include #include #include #include namespace PureScript { using string = std::string; using runtime_error = std::runtime_error; using nullptr_t = std::nullptr_t; const bool undefined = false; // TODO: deprecated -- remove #define KEY(k) k // A variant data class designed to provide some features of dynamic typing. // class any { public: enum class Type : std::int8_t { Unknown, Integer, Double, Character, Boolean, String, Map, Vector, Function, EffFunction, Thunk, Pointer }; Type type = Type::Unknown; struct as_thunk { }; static constexpr as_thunk unthunk = as_thunk{}; using map = std::unordered_map; using vector = std::vector; using fn = std::function; using eff_fn = std::function; using thunk = std::function; using shared_string = std::shared_ptr; using shared_map = std::shared_ptr; using shared_vector = std::shared_ptr; using shared_fn = std::shared_ptr; using shared_eff_fn = std::shared_ptr; using shared_thunk = std::shared_ptr; template using shared = std::shared_ptr; using shared_void_ptr = std::shared_ptr; template static constexpr auto make_shared(const T& arg) -> shared { return std::make_shared(arg); } template static constexpr auto make_shared(T&& arg) -> shared { return std::make_shared(std::move(arg)); } template static constexpr auto static_cast_shared(U arg) -> T* { return static_cast(arg.get()); } private: union { long i; double d; char c; bool b; shared_string s; shared_map m; shared_vector v; shared_fn f; shared_eff_fn e; shared_thunk t; shared_void_ptr p; }; public: any(const long val) : type(Type::Integer), i(val) {} any(const int val) : type(Type::Integer), i(val) {} any(const unsigned int val) : type(Type::Integer), i(val) {} any(const double val) : type(Type::Double), d(val) {} any(const char val) : type(Type::Character), c(val) {} any(const bool val) : type(Type::Boolean), b(val) {} any(const string& val) : type(Type::String), s(make_shared(val)) {} any(string&& val) : type(Type::String), s(make_shared(std::move(val))) {} any(const char val[]) : type(Type::String), s(make_shared(val)) {} any(const shared_string& val) : type(Type::String), s(val) {} any(shared_string&& val) : type(Type::String), s(std::move(val)) {} any(const map& val) : type(Type::Map), m(make_shared(val)) {} any(map&& val) : type(Type::Map), m(make_shared(std::move(val))) {} any(const shared_map& val) : type(Type::Map), m(val) {} any(shared_map&& val) : type(Type::Map), m(std::move(val)) {} any(const vector& val) : type(Type::Vector), v(make_shared(val)) {} any(vector&& val) : type(Type::Vector), v(make_shared(std::move(val))) {} any(const shared_vector& val) : type(Type::Vector), v(val) {} any(shared_vector&& val) : type(Type::Vector), v(std::move(val)) {} any(const shared_fn& val) : type(Type::Function), f(val) {} any(shared_fn&& val) : type(Type::Function), f(std::move(val)) {} template any(const T& val, typename std::enable_if::value>::type* = 0) : type(Type::Function), f(make_shared(val)) {} // template // any(T&& val, typename std::enable_if::value>::type* = 0) // : type(Type::Function), f(std::move(val)) {} any(const shared_eff_fn& val) : type(Type::EffFunction), e(val) {} any(shared_eff_fn&& val) : type(Type::EffFunction), e(std::move(val)) {} template any(const T& val, typename std::enable_if::value>::type* = 0) : type(Type::EffFunction), e(make_shared(val)) {} any(const shared_thunk& val) : type(Type::Thunk), t(val) {} any(shared_thunk&& val) : type(Type::Thunk), t(std::move(val)) {} template any(const T& val, typename std::enable_if::value>::type* = 0) : type(Type::Thunk), t(make_shared(val)) {} template any(const T& val, typename std::enable_if::value>::type* = 0) : type(Type::Pointer), p(val) {} any(std::nullptr_t) : type(Type::Pointer), p(nullptr) {} template any(T&& val, typename std::enable_if::value>::type* = 0) : type(Type::Pointer), p(std::move(val)) {} any(const any&); void swap(any&&); any(any&& val) { swap(std::move(val)); } auto operator=(any val) -> any& { swap(std::move(val)); return *this; } any() = delete; ~any(); template auto cast() const -> typename std::enable_if::value, T>::type; template auto cast() const -> typename std::enable_if::value, T>::type; template auto cast() const -> typename std::enable_if::value, T>::type; template auto cast() const -> typename std::enable_if::value, T>::type; template auto cast() const -> typename std::enable_if::value, const T&>::type; template auto cast() const -> typename std::enable_if::value, const T>::type; template auto cast() const -> typename std::enable_if::value, const T&>::type; template auto cast() const -> typename std::enable_if::value, const T&>::type; template auto cast() const -> typename std::enable_if::value, typename T::element_type*>::type { if (type == Type::Pointer) { return static_cast_shared(p); } const any* valuePtr = this; do { assert(valuePtr->type == Type::Thunk); const any& value = (*valuePtr->t)(unthunk); if (value.type == Type::Pointer) { return static_cast_shared(value.p); } valuePtr = &value; } while (valuePtr->type != Type::Unknown); return nullptr; } auto operator()(const any) const -> any; auto operator()(const as_thunk) const -> const any&; auto operator()() const -> any; operator long() const; operator double() const; operator bool() const; operator const string&() const; operator const map&() const; operator const vector&() const; auto operator[](const char []) const -> const any&; auto operator[](const vector::size_type) const -> const any&; auto operator[](const any&) const -> const any&; auto extractPointer() const -> const void*; static auto extract_value(const any&) -> const any&; auto operator==(const any&) const -> bool; auto operator==(const long) const -> bool; auto operator==(const double) const -> bool; auto operator==(const char) const -> bool; auto operator==(const bool) const -> bool; auto operator==(const string&) const -> bool; auto operator==(const char * const) const -> bool; auto operator!=(const any&) const -> bool; auto operator!=(const long) const -> bool; auto operator!=(const double) const -> bool; auto operator!=(const char) const -> bool; auto operator!=(const bool) const -> bool; auto operator!=(const string&) const -> bool; auto operator!=(const char * const) const -> bool; auto operator<(const any&) const -> bool; auto operator<(const long) const -> bool; auto operator<(const double) const -> bool; auto operator<(const char) const -> bool; auto operator<(const bool) const -> bool; auto operator<(const string&) const -> bool; auto operator<(const char * const) const -> bool; auto operator<=(const any&) const -> bool; auto operator<=(const long) const -> bool; auto operator<=(const double) const -> bool; auto operator<=(const char) const -> bool; auto operator<=(const bool) const -> bool; auto operator<=(const string&) const -> bool; auto operator<=(const char * const) const -> bool; auto operator>(const any&) const -> bool; auto operator>(const long) const -> bool; auto operator>(const double) const -> bool; auto operator>(const char) const -> bool; auto operator>(const bool) const -> bool; auto operator>(const string&) const -> bool; auto operator>(const char * const) const -> bool; auto operator>=(const any&) const -> bool; auto operator>=(const long) const -> bool; auto operator>=(const double) const -> bool; auto operator>=(const char) const -> bool; auto operator>=(const bool) const -> bool; auto operator>=(const string&) const -> bool; auto operator>=(const char * const) const -> bool; auto operator+(const any&) const -> any; auto operator+(const long) const -> long; auto operator+(const double) const -> double; auto operator+(const char) const -> char; auto operator+(const string&) const -> string; auto operator+(const char * const) const -> string; auto operator-(const any&) const -> any; auto operator-(const long) const -> long; auto operator-(const double) const -> double; auto operator-(const char) const -> char; auto operator*(const any&) const -> any; auto operator*(const long) const -> long; auto operator*(const double) const -> double; auto operator/(const any&) const -> any; auto operator/(const long) const -> long; auto operator/(const double) const -> double; auto operator%(const any&) const -> any; auto operator%(const long) const -> long; auto operator-() const -> any; // unary negate friend auto operator==(const long, const any&) -> bool; friend auto operator!=(const long, const any&) -> bool; friend auto operator< (const long, const any&) -> bool; friend auto operator<=(const long, const any&) -> bool; friend auto operator> (const long, const any&) -> bool; friend auto operator>=(const long, const any&) -> bool; friend auto operator==(const double, const any&) -> bool; friend auto operator!=(const double, const any&) -> bool; friend auto operator< (const double, const any&) -> bool; friend auto operator<=(const double, const any&) -> bool; friend auto operator> (const double, const any&) -> bool; friend auto operator>=(const double, const any&) -> bool; friend auto operator==(const char, const any&) -> bool; friend auto operator!=(const char, const any&) -> bool; friend auto operator< (const char, const any&) -> bool; friend auto operator<=(const char, const any&) -> bool; friend auto operator> (const char, const any&) -> bool; friend auto operator>=(const char, const any&) -> bool; friend auto operator==(const bool, const any&) -> bool; friend auto operator!=(const bool, const any&) -> bool; friend auto operator< (const bool, const any&) -> bool; friend auto operator<=(const bool, const any&) -> bool; friend auto operator> (const bool, const any&) -> bool; friend auto operator>=(const bool, const any&) -> bool; friend auto operator==(const string&, const any&) -> bool; friend auto operator!=(const string&, const any&) -> bool; friend auto operator< (const string&, const any&) -> bool; friend auto operator<=(const string&, const any&) -> bool; friend auto operator> (const string&, const any&) -> bool; friend auto operator>=(const string&, const any&) -> bool; friend auto operator==(const char* const, const any&) -> bool; friend auto operator!=(const char* const, const any&) -> bool; friend auto operator< (const char* const, const any&) -> bool; friend auto operator<=(const char* const, const any&) -> bool; friend auto operator> (const char* const, const any&) -> bool; friend auto operator>=(const char* const, const any&) -> bool; friend auto operator+(const long, const any&) -> long; friend auto operator-(const long, const any&) -> long; friend auto operator*(const long, const any&) -> long; friend auto operator/(const long, const any&) -> long; friend auto operator%(const long, const any&) -> long; friend auto operator+(const double, const any&) -> double; friend auto operator-(const double, const any&) -> double; friend auto operator*(const double, const any&) -> double; friend auto operator/(const double, const any&) -> double; friend auto operator+(const char, const any&) -> char; friend auto operator-(const char, const any&) -> char; friend auto operator+(const string&, const any&) -> string; friend auto operator+(const char* const, const any&) -> string; }; } // namespace PureScript #endif // PureScript_HH