/////////////////////////////////////////////////////////////////////////////// // // 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 #include "map_key.hh" namespace PureScript { using string = std::string; using runtime_error = std::runtime_error; using nullptr_t = std::nullptr_t; const bool undefined = false; // A variant data class designed to provide some features of dynamic typing. // class any { public: enum class Type { Unknown, Integer, Double, Character, Boolean, String, Map, Vector, Function, EffFunction, Thunk, Pointer }; mutable 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 = auto (*)(const as_thunk) -> const any&; template using shared = std::shared_ptr; template inline static auto make_shared(Args&&... args) -> decltype(std::make_shared(std::forward(args)...)) { return std::make_shared(std::forward(args)...); } private: union { mutable long i; mutable double d; mutable char c; mutable bool b; mutable shared s; mutable shared m; mutable shared v; mutable shared f; mutable shared e; mutable thunk t; mutable shared 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) {} template ::value>::type> any(const T val) : type(Type::Boolean), b(val) {} any(const string& val) : type(Type::String), s(make_shared(val)) {} any(string&& val) noexcept : type(Type::String), s(make_shared(std::move(val))) {} any(const char val[]) : type(Type::String), s(make_shared(val)) {} any(const map& val) : type(Type::Map), m(make_shared(val)) {} any(map&& val) noexcept : type(Type::Map), m(make_shared(std::move(val))) {} any(const vector& val) : type(Type::Vector), v(make_shared(val)) {} any(vector&& val) noexcept : type(Type::Vector), v(make_shared(std::move(val))) {} template ::value>::type> any(const T& val, typename std::enable_if::value>::type* = 0) : type(Type::Function), f(make_shared(val)) {} template any(const T& val, typename std::enable_if::value>::type* = 0) : type(Type::EffFunction), e(make_shared(val)) {} template any(const T& val, typename std::enable_if::value>::type* = 0) : type(Type::Thunk), t(val) {} template any(const T& val, typename std::enable_if,T>::value>::type* = 0) : type(Type::Pointer), p(val) {} template any(T&& val, typename std::enable_if,T>::value>::type* = 0) noexcept : type(Type::Pointer), p(std::move(val)) {} any(std::nullptr_t) : type(Type::Pointer), p(nullptr) {} any(const any&); any(any&&) noexcept; auto operator=(const any&) -> any&; auto operator=(any&) noexcept -> any&; auto operator=(any&&) noexcept -> any&; 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,T>::value, typename T::element_type*>::type { return static_cast(extractPointer()); } 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 map_key_t&) const -> const any&; auto operator[](const vector::size_type) const -> const any&; auto operator[](const any&) const -> const any&; auto extractPointer() 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