git.iko.soy/rowtype-yoga/purescript-native
on e13aa06 help sign in
393 lines 13 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>
35namespace PureScript {
37using string = std::string;
38using runtime_error = std::runtime_error;
39using nullptr_t = std::nullptr_t;
41const bool undefined = false;
43// TODO: deprecated -- remove
44#define KEY(k) k
46// A variant data class designed to provide some features of dynamic typing.
47//
48class any {
50 public:
51 enum class Type : std::int8_t {
52 Unknown,
53 Integer,
54 Double,
55 Character,
56 Boolean,
57 String,
58 Map,
59 Vector,
60 Function,
61 EffFunction,
62 Thunk,
63 Pointer
64 };
66 mutable Type type = Type::Unknown;
68 struct as_thunk {
69 };
70 static constexpr as_thunk unthunk = as_thunk{};
72 using map = std::unordered_map<std::string, const any>;
73 using vector = std::vector<any>;
74 using fn = std::function<any(const any&)>;
75 using eff_fn = std::function<any()>;
76 using thunk = std::function<const any& (const as_thunk)>;
78 template <typename T>
79 using shared = std::shared_ptr<T>;
81 template <typename T>
82 static constexpr auto make_shared(const T& arg) -> shared<T> {
83 return std::make_shared<T>(arg);
84 }
86 template <typename T>
87 static constexpr auto make_shared(T&& arg) -> shared<T> {
88 return std::make_shared<T>(std::move(arg));
89 }
91 template <typename T, typename U>
92 static constexpr auto static_cast_shared(U arg) -> T* {
93 return static_cast<T*>(arg.get());
94 }
96 private:
97 union {
98 mutable long i;
99 mutable double d;
100 mutable char c;
101 mutable bool b;
102 mutable shared<string> s;
103 mutable shared<map> m;
104 mutable shared<vector> v;
105 mutable shared<fn> f;
106 mutable shared<eff_fn> e;
107 mutable shared<thunk> t;
108 mutable shared<void> p;
109 };
111 public:
113 any(const long val) : type(Type::Integer), i(val) {}
114 any(const int val) : type(Type::Integer), i(val) {}
115 any(const unsigned int val) : type(Type::Integer), i(val) {}
117 any(const double val) : type(Type::Double), d(val) {}
119 any(const char val) : type(Type::Character), c(val) {}
121 any(const bool val) : type(Type::Boolean), b(val) {}
123 any(const string& val) : type(Type::String), s(make_shared<string>(val)) {}
124 any(string&& val) : type(Type::String), s(make_shared<string>(std::move(val))) {}
126 any(const char val[]) : type(Type::String), s(make_shared<string>(val)) {}
128 any(const shared<string>& val) : type(Type::String), s(val) {}
129 any(shared<string>&& val) : type(Type::String), s(std::move(val)) {}
131 any(const map& val) : type(Type::Map), m(make_shared<map>(val)) {}
132 any(map&& val) : type(Type::Map), m(make_shared<map>(std::move(val))) {}
134 any(const shared<map>& val) : type(Type::Map), m(val) {}
135 any(shared<map>&& val) : type(Type::Map), m(std::move(val)) {}
137 any(const vector& val) : type(Type::Vector), v(make_shared<vector>(val)) {}
138 any(vector&& val) : type(Type::Vector), v(make_shared<vector>(std::move(val))) {}
140 any(const shared<vector>& val) : type(Type::Vector), v(val) {}
141 any(shared<vector>&& val) : type(Type::Vector), v(std::move(val)) {}
143 any(const shared<fn>& val) : type(Type::Function), f(val) {}
144 any(shared<fn>&& val) : type(Type::Function), f(std::move(val)) {}
146 template <typename T>
147 any(const T& val, typename std::enable_if<std::is_assignable<fn,T>::value>::type* = 0)
148 : type(Type::Function), f(make_shared<fn>(val)) {}
150 // template <typename T>
151 // any(T&& val, typename std::enable_if<std::is_assignable<fn,T>::value>::type* = 0)
152 // : type(Type::Function), f(std::move(val)) {}
154 any(const shared<eff_fn>& val) : type(Type::EffFunction), e(val) {}
155 any(shared<eff_fn>&& val) : type(Type::EffFunction), e(std::move(val)) {}
157 template <typename T>
158 any(const T& val, typename std::enable_if<std::is_assignable<eff_fn,T>::value>::type* = 0)
159 : type(Type::EffFunction), e(make_shared<eff_fn>(val)) {}
161 any(const shared<thunk>& val) : type(Type::Thunk), t(val) {}
162 any(shared<thunk>&& val) : type(Type::Thunk), t(std::move(val)) {}
164 template <typename T>
165 any(const T& val, typename std::enable_if<std::is_assignable<thunk,T>::value>::type* = 0)
166 : type(Type::Thunk), t(make_shared<thunk>(val)) {}
168 template <typename T>
169 any(const T& val, typename std::enable_if<std::is_assignable<shared<void>,T>::value>::type* = 0)
170 : type(Type::Pointer), p(val) {}
172 any(std::nullptr_t) : type(Type::Pointer), p(nullptr) {}
174 template <typename T>
175 any(T&& val, typename std::enable_if<std::is_assignable<shared<void>,T>::value>::type* = 0)
176 : type(Type::Pointer), p(std::move(val)) {}
178 any(const any&);
180 void swap(any&&) const;
182 any(any&& val) {
183 swap(std::move(val));
184 }
186 auto operator=(any val) -> any& {
187 swap(std::move(val));
188 return *this;
189 }
191 any() = delete;
192 ~any();
194 template <typename T>
195 auto cast() const -> typename std::enable_if<std::is_same<T, long>::value, T>::type;
197 template <typename T>
198 auto cast() const -> typename std::enable_if<std::is_same<T, double>::value, T>::type;
200 template <typename T>
201 auto cast() const -> typename std::enable_if<std::is_same<T, char>::value, T>::type;
203 template <typename T>
204 auto cast() const -> typename std::enable_if<std::is_same<T, bool>::value, T>::type;
206 template <typename T>
207 auto cast() const -> typename std::enable_if<std::is_same<T, string>::value, const T&>::type;
209 template <typename T>
210 auto cast() const -> typename std::enable_if<std::is_same<T, const char*>::value, const T>::type;
212 template <typename T>
213 auto cast() const -> typename std::enable_if<std::is_same<T, map>::value, const T&>::type;
215 template <typename T>
216 auto cast() const -> typename std::enable_if<std::is_same<T, vector>::value, const T&>::type;
218 template <typename T>
219 auto cast() const -> typename std::enable_if<std::is_assignable<shared<void>,T>::value, typename T::element_type*>::type {
220 if (type == Type::Pointer) {
221 return static_cast_shared<typename T::element_type>(p);
222 }
223 const any* valuePtr = this;
224 do {
225 assert(valuePtr->type == Type::Thunk);
226 const any& value = (*valuePtr->t)(unthunk);
227 if (value.type == Type::Pointer) {
228 return static_cast_shared<typename T::element_type>(value.p);
229 }
230 valuePtr = &value;
231 } while (valuePtr->type != Type::Unknown);
232 return nullptr;
233 }
235 auto operator()(const any) const -> any;
237 auto operator()(const as_thunk) const -> const any&;
239 auto operator()() const -> any;
241 operator long() const;
242 operator double() const;
243 operator bool() const;
245 operator const string&() const;
246 operator const map&() const;
247 operator const vector&() const;
249 auto operator[](const char []) const -> const any&;
250 auto operator[](const vector::size_type) const -> const any&;
251 auto operator[](const any&) const -> const any&;
253 auto extractPointer() const -> const void*;
255 static auto extract_value(const any&) -> const any&;
257 auto operator==(const any&) const -> bool;
258 auto operator==(const long) const -> bool;
259 auto operator==(const double) const -> bool;
260 auto operator==(const char) const -> bool;
261 auto operator==(const bool) const -> bool;
262 auto operator==(const string&) const -> bool;
263 auto operator==(const char * const) const -> bool;
265 auto operator!=(const any&) const -> bool;
266 auto operator!=(const long) const -> bool;
267 auto operator!=(const double) const -> bool;
268 auto operator!=(const char) const -> bool;
269 auto operator!=(const bool) const -> bool;
270 auto operator!=(const string&) const -> bool;
271 auto operator!=(const char * const) const -> bool;
273 auto operator<(const any&) const -> bool;
274 auto operator<(const long) const -> bool;
275 auto operator<(const double) const -> bool;
276 auto operator<(const char) const -> bool;
277 auto operator<(const bool) const -> bool;
278 auto operator<(const string&) const -> bool;
279 auto operator<(const char * const) const -> bool;
281 auto operator<=(const any&) const -> bool;
282 auto operator<=(const long) const -> bool;
283 auto operator<=(const double) const -> bool;
284 auto operator<=(const char) const -> bool;
285 auto operator<=(const bool) const -> bool;
286 auto operator<=(const string&) const -> bool;
287 auto operator<=(const char * const) const -> bool;
289 auto operator>(const any&) const -> bool;
290 auto operator>(const long) const -> bool;
291 auto operator>(const double) const -> bool;
292 auto operator>(const char) const -> bool;
293 auto operator>(const bool) const -> bool;
294 auto operator>(const string&) const -> bool;
295 auto operator>(const char * const) const -> bool;
297 auto operator>=(const any&) const -> bool;
298 auto operator>=(const long) const -> bool;
299 auto operator>=(const double) const -> bool;
300 auto operator>=(const char) const -> bool;
301 auto operator>=(const bool) const -> bool;
302 auto operator>=(const string&) const -> bool;
303 auto operator>=(const char * const) const -> bool;
305 auto operator+(const any&) const -> any;
306 auto operator+(const long) const -> long;
307 auto operator+(const double) const -> double;
308 auto operator+(const char) const -> char;
309 auto operator+(const string&) const -> string;
310 auto operator+(const char * const) const -> string;
312 auto operator-(const any&) const -> any;
313 auto operator-(const long) const -> long;
314 auto operator-(const double) const -> double;
315 auto operator-(const char) const -> char;
317 auto operator*(const any&) const -> any;
318 auto operator*(const long) const -> long;
319 auto operator*(const double) const -> double;
321 auto operator/(const any&) const -> any;
322 auto operator/(const long) const -> long;
323 auto operator/(const double) const -> double;
325 auto operator%(const any&) const -> any;
326 auto operator%(const long) const -> long;
328 auto operator-() const -> any; // unary negate
330 friend auto operator==(const long, const any&) -> bool;
331 friend auto operator!=(const long, const any&) -> bool;
332 friend auto operator< (const long, const any&) -> bool;
333 friend auto operator<=(const long, const any&) -> bool;
334 friend auto operator> (const long, const any&) -> bool;
335 friend auto operator>=(const long, const any&) -> bool;
337 friend auto operator==(const double, const any&) -> bool;
338 friend auto operator!=(const double, const any&) -> bool;
339 friend auto operator< (const double, const any&) -> bool;
340 friend auto operator<=(const double, const any&) -> bool;
341 friend auto operator> (const double, const any&) -> bool;
342 friend auto operator>=(const double, const any&) -> bool;
344 friend auto operator==(const char, const any&) -> bool;
345 friend auto operator!=(const char, const any&) -> bool;
346 friend auto operator< (const char, const any&) -> bool;
347 friend auto operator<=(const char, const any&) -> bool;
348 friend auto operator> (const char, const any&) -> bool;
349 friend auto operator>=(const char, const any&) -> bool;
351 friend auto operator==(const bool, const any&) -> bool;
352 friend auto operator!=(const bool, const any&) -> bool;
353 friend auto operator< (const bool, const any&) -> bool;
354 friend auto operator<=(const bool, const any&) -> bool;
355 friend auto operator> (const bool, const any&) -> bool;
356 friend auto operator>=(const bool, const any&) -> bool;
358 friend auto operator==(const string&, const any&) -> bool;
359 friend auto operator!=(const string&, const any&) -> bool;
360 friend auto operator< (const string&, const any&) -> bool;
361 friend auto operator<=(const string&, const any&) -> bool;
362 friend auto operator> (const string&, const any&) -> bool;
363 friend auto operator>=(const string&, const any&) -> bool;
365 friend auto operator==(const char* const, const any&) -> bool;
366 friend auto operator!=(const char* const, const any&) -> bool;
367 friend auto operator< (const char* const, const any&) -> bool;
368 friend auto operator<=(const char* const, const any&) -> bool;
369 friend auto operator> (const char* const, const any&) -> bool;
370 friend auto operator>=(const char* const, const any&) -> bool;
372 friend auto operator+(const long, const any&) -> long;
373 friend auto operator-(const long, const any&) -> long;
374 friend auto operator*(const long, const any&) -> long;
375 friend auto operator/(const long, const any&) -> long;
376 friend auto operator%(const long, const any&) -> long;
378 friend auto operator+(const double, const any&) -> double;
379 friend auto operator-(const double, const any&) -> double;
380 friend auto operator*(const double, const any&) -> double;
381 friend auto operator/(const double, const any&) -> double;
383 friend auto operator+(const char, const any&) -> char;
384 friend auto operator-(const char, const any&) -> char;
386 friend auto operator+(const string&, const any&) -> string;
387 friend auto operator+(const char* const, const any&) -> string;
389};
391} // namespace PureScript
393#endif // PureScript_HH