git.iko.soy/rowtype-yoga/purescript-native
on 3711c76 help sign in
274 lines 8.4 kB history raw
1///////////////////////////////////////////////////////////////////////////////
2//
3// Module : purescript.hh
4// Copyright : (c) Andy Arvanitis 2015
5// License : MIT
6//
7// Maintainer : Andy Arvanitis <andy.arvanitis@gmail.com>
8// Stability : experimental
9// Portability :
10//
11// Basic types and functions to support purescript-to-C++1x rendering
12//
13///////////////////////////////////////////////////////////////////////////////
14//
15#ifndef PureScript_HH
16#define PureScript_HH
18// Standard includes
20#if defined(DEBUG)
21 #include <cassert>
22#else
23 #define NDEBUG
24 #undef assert
25 #define assert(x)
26#endif
28#include <memory>
29#include <functional>
30#include <string>
31#include <vector>
32#include <unordered_map>
33#include <stdexcept>
34#include "map_key.hh"
36#define DECLARE_OPERATOR(op, ty, rty) \
37 friend auto operator op (const any&, ty) -> rty; \
38 friend auto operator op (ty, const any&) -> rty;
40#define DECLARE_COMPARISON_OPERATOR(op) \
41 friend auto operator op (const any&, const any&) -> bool; \
42 DECLARE_OPERATOR(op, long, bool) \
43 DECLARE_OPERATOR(op, double, bool) \
44 DECLARE_OPERATOR(op, char, bool) \
45 DECLARE_OPERATOR(op, const char *, bool)
48namespace PureScript {
50using string = const char *;
51using runtime_error = std::runtime_error;
52using nullptr_t = std::nullptr_t;
54const bool undefined = false;
56// A variant data class designed to provide some features of dynamic typing.
57//
58class any {
60 public:
61 enum class Type : int8_t {
62 Unknown,
63 Integer,
64 Double,
65 Character,
66 Boolean,
67 StringLiteral,
68 String,
69 Map,
70 Vector,
71 Function,
72 Closure,
73 EffFunction,
74 Thunk,
75 Pointer
76 };
78 mutable Type type = Type::Unknown;
80 struct as_thunk {
81 };
82 static constexpr as_thunk unthunk = as_thunk{};
84 using map = std::unordered_map<const map_key_t, const any, map_key_t::hasher, map_key_t::equal>;
85 using vector = std::vector<any>;
86 using fn = auto (*)(const any&) -> any;
87 using closure = std::function<any(const any&)>;
88 using eff_fn = std::function<any()>;
89 using thunk = auto (*)(const as_thunk) -> const any&;
91 template <typename T>
92 using shared = std::shared_ptr<T>;
94 template <typename T, typename... Args>
95 inline static auto make_shared(Args&&... args) -> decltype(std::make_shared<T>(std::forward<Args>(args)...)) {
96 return std::make_shared<T>(std::forward<Args>(args)...);
97 }
99 private:
100 union {
101 mutable long i;
102 mutable double d;
103 mutable char c;
104 mutable bool b;
105 mutable string r;
106 mutable shared<std::string> s;
107 mutable shared<map> m;
108 mutable shared<vector> v;
109 mutable fn f;
110 mutable shared<closure> l;
111 mutable shared<eff_fn> e;
112 mutable thunk t;
113 mutable shared<void> p;
114 };
116 public:
118 any(const long val) : type(Type::Integer), i(val) {}
119 any(const int val) : type(Type::Integer), i(val) {}
120 any(const unsigned int val) : type(Type::Integer), i(val) {}
121 any(const double val) : type(Type::Double), d(val) {}
122 any(const char val) : type(Type::Character), c(val) {}
124 template <typename T, typename = typename std::enable_if<std::is_same<bool,T>::value>::type>
125 any(const T val) : type(Type::Boolean), b(val) {}
127 template <size_t N>
128 any(const char (&val)[N]) : type(Type::StringLiteral), r(val) {}
129 any(char * val) : type(Type::String), s(make_shared<std::string>(val)) {}
131 any(const std::string& val) : type(Type::String), s(make_shared<std::string>(val)) {}
132 any(std::string&& val) : type(Type::String), s(make_shared<std::string>(std::move(val))) {}
134 any(const shared<std::string>& val) : type(Type::String), s(val) {}
135 any(shared<std::string>&& val) noexcept : type(Type::String), s(std::move(val)) {}
137 any(const map& val) : type(Type::Map), m(make_shared<map>(val)) {}
138 any(map&& val) noexcept : type(Type::Map), m(make_shared<map>(std::move(val))) {}
140 any(const vector& val) : type(Type::Vector), v(make_shared<vector>(val)) {}
141 any(vector&& val) noexcept : type(Type::Vector), v(make_shared<vector>(std::move(val))) {}
143 template <typename T>
144 any(const T& val, typename std::enable_if<std::is_convertible<T,fn>::value>::type* = 0)
145 : type(Type::Function), f(val) {}
147 template <typename T, typename = typename std::enable_if<!std::is_same<any,T>::value &&
148 !std::is_convertible<T,fn>::value>::type>
149 any(const T& val, typename std::enable_if<std::is_assignable<closure,T>::value>::type* = 0)
150 : type(Type::Closure), l(make_shared<closure>(val)) {}
152 template <typename T>
153 any(const T& val, typename std::enable_if<std::is_assignable<eff_fn,T>::value>::type* = 0)
154 : type(Type::EffFunction), e(make_shared<eff_fn>(val)) {}
156 template <typename T>
157 any(const T& val, typename std::enable_if<std::is_convertible<T,thunk>::value>::type* = 0)
158 : type(Type::Thunk), t(val) {}
160 template <typename T>
161 any(const T& val, typename std::enable_if<std::is_assignable<shared<void>,T>::value>::type* = 0)
162 : type(Type::Pointer), p(val) {}
164 template <typename T>
165 any(T&& val, typename std::enable_if<std::is_assignable<shared<void>,T>::value>::type* = 0) noexcept
166 : type(Type::Pointer), p(std::move(val)) {}
168 any(std::nullptr_t) : type(Type::Pointer), p(nullptr) {}
170 any(const any&);
171 any(any&&) noexcept;
173 auto operator=(const any&) -> any&;
174 auto operator=(any&) noexcept -> any&;
175 auto operator=(any&&) noexcept -> any&;
177 any() = delete;
178 ~any();
180 template <typename T>
181 auto cast() const -> typename std::enable_if<std::is_same<T, long>::value, T>::type;
183 template <typename T>
184 auto cast() const -> typename std::enable_if<std::is_same<T, double>::value, T>::type;
186 template <typename T>
187 auto cast() const -> typename std::enable_if<std::is_same<T, char>::value, T>::type;
189 template <typename T>
190 auto cast() const -> typename std::enable_if<std::is_same<T, bool>::value, T>::type;
192 template <typename T>
193 auto cast() const -> typename std::enable_if<std::is_same<T, string>::value, T>::type;
195 template <typename T>
196 auto cast() const -> typename std::enable_if<std::is_same<T, map>::value, const T&>::type;
198 template <typename T>
199 auto cast() const -> typename std::enable_if<std::is_same<T, vector>::value, const T&>::type;
201 template <typename T>
202 auto cast() const -> typename std::enable_if<std::is_assignable<shared<void>,T>::value, typename T::element_type*>::type {
203 return static_cast<typename T::element_type*>(extractPointer());
204 }
206 auto operator()(const any&) const -> any;
208 auto operator()(const as_thunk) const -> const any&;
210 auto operator()() const -> any;
212 operator long() const;
213 operator double() const;
214 operator bool() const;
216 operator string() const;
217 operator std::string() const;
218 operator const map&() const;
219 operator const vector&() const;
221 auto operator[](const map_key_t&) const -> const any&;
222 auto operator[](const vector::size_type) const -> const any&;
223 auto operator[](const any&) const -> const any&;
225 auto extractPointer() const -> void*;
227 static auto extractValue(const any&) -> const any&;
229 DECLARE_COMPARISON_OPERATOR(==)
230 DECLARE_COMPARISON_OPERATOR(!=)
231 DECLARE_COMPARISON_OPERATOR(<)
232 DECLARE_COMPARISON_OPERATOR(<=)
233 DECLARE_COMPARISON_OPERATOR(>)
234 DECLARE_COMPARISON_OPERATOR(>=)
236 friend auto operator+(const any&, const any&) -> any;
238 DECLARE_OPERATOR(+, long, long)
239 DECLARE_OPERATOR(+, double, double)
240 DECLARE_OPERATOR(+, char, char)
241 DECLARE_OPERATOR(+, const char *, std::string)
243 friend auto operator-(const any&, const any&) -> any;
245 DECLARE_OPERATOR(-, long, long)
246 DECLARE_OPERATOR(-, double, double)
247 DECLARE_OPERATOR(-, char, char)
249 friend auto operator*(const any&, const any&) -> any;
251 DECLARE_OPERATOR(*, long, long)
252 DECLARE_OPERATOR(*, double, double)
253 DECLARE_OPERATOR(*, char, char)
255 friend auto operator/(const any&, const any&) -> any;
257 DECLARE_OPERATOR(/, long, long)
258 DECLARE_OPERATOR(/, double, double)
259 DECLARE_OPERATOR(/, char, char)
261 friend auto operator%(const any&, const any&) -> any;
263 DECLARE_OPERATOR(%, long, long)
264 DECLARE_OPERATOR(%, char, char)
266 friend auto operator-(const any&) -> any; // unary negate
267};
269} // namespace PureScript
271#undef DECLARE_OPERATOR
272#undef DECLARE_COMPARISON_OPERATOR
274#endif // PureScript_HH