git.iko.soy/rowtype-yoga/purescript-native
on 47b98c2 help sign in
555 lines 20 kB history raw
1///////////////////////////////////////////////////////////////////////////////
2//
3// Module : purescript.cc
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#include "PureScript.hh"
17namespace PureScript {
19#define copy_data(src) \
20 type = src.type; \
21 switch (type) { \
22 case Type::Integer: i = src.i; break; \
23 case Type::Double: d = src.d; break; \
24 case Type::Character: c = src.c; break; \
25 case Type::Boolean: b = src.b; break; \
26 case Type::String: new (&s) shared<string> (src.s); break; \
27 case Type::Map: new (&m) shared<map> (src.m); break; \
28 case Type::Vector: new (&v) shared<vector> (src.v); break; \
29 case Type::Function: new (&f) shared<fn> (src.f); break; \
30 case Type::EffFunction: new (&e) shared<eff_fn> (src.e); break; \
31 case Type::Thunk: new (&t) shared<thunk> (src.t); break; \
32 case Type::Pointer: new (&p) shared<void> (src.p); break; \
33 \
34 default: assert(false && "Unsupported type in copy"); \
35 }
37#define move_data(src) \
38 type = src.type; \
39 switch (type) { \
40 case Type::Integer: i = src.i; break; \
41 case Type::Double: d = src.d; break; \
42 case Type::Character: c = src.c; break; \
43 case Type::Boolean: b = src.b; break; \
44 case Type::String: new (&s) shared<string> (std::move(src.s)); break; \
45 case Type::Map: new (&m) shared<map> (std::move(src.m)); break; \
46 case Type::Vector: new (&v) shared<vector> (std::move(src.v)); break; \
47 case Type::Function: new (&f) shared<fn> (std::move(src.f)); break; \
48 case Type::EffFunction: new (&e) shared<eff_fn> (std::move(src.e)); break; \
49 case Type::Thunk: new (&t) shared<thunk> (std::move(src.t)); break; \
50 case Type::Pointer: new (&p) shared<void> (std::move(src.p)); break; \
51 \
52 default: assert(false && "Unsupported type in move"); \
53 }
55any::any(const any& other) {
56 copy_data(other);
59any::any(any&& other) noexcept {
60 move_data(other);
63auto any::operator=(const any& rhs) -> any& {
64 copy_data(rhs);
65 return *this;
68// Takes ownership -- might need to reconsider this
69auto any::operator=(any& rhs) -> any& {
70 move_data(rhs);
71 return *this;
74auto any::operator=(any&& rhs) noexcept -> any& {
75 move_data(rhs);
76 return *this;
79any::~any() {
80 // std::cout << "destroy" << std::endl;
81 switch (type) {
82 case Type::Integer: ; break;
83 case Type::Double: ; break;
84 case Type::Character: ; break;
85 case Type::Boolean: ; break;
86 case Type::String: s.~shared<string>(); break;
87 case Type::Map: m.~shared<map>(); break;
88 case Type::Vector: v.~shared<vector>(); break;
89 case Type::Function: f.~shared<fn>(); break;
90 case Type::EffFunction: e.~shared<eff_fn>(); break;
91 case Type::Thunk: t.~shared<thunk>(); break;
92 case Type::Pointer: p.~shared<void>(); break;
94 default: assert(false && "Unsupported type in destructor");
95 }
96};
98 #define RETURN_VALUE(TYPE, VAL, FN) \
99 if (type == TYPE) { \
100 return FN(VAL); \
101 } \
102 const any* valuePtr = this; \
103 do { \
104 assert(valuePtr->type == Type::Thunk); \
105 const any& value = (*valuePtr->t)(unthunk); \
106 if (value.type == TYPE) { \
107 return FN(value.VAL); \
108 } \
109 valuePtr = &value; \
110 } while (valuePtr->type != Type::Unknown); \
111 assert(false && "Unknown value type"); \
112 return FN(VAL);
114 template <typename T>
115 auto any::cast() const -> typename std::enable_if<std::is_same<T, long>::value, T>::type {
116 RETURN_VALUE(Type::Integer, i,)
117 }
118 template auto any::cast<long>() const -> long;
120 template <typename T>
121 auto any::cast() const -> typename std::enable_if<std::is_same<T, double>::value, T>::type {
122 RETURN_VALUE(Type::Double, d,)
123 }
124 template auto any::cast<double>() const -> double;
126 template <typename T>
127 auto any::cast() const -> typename std::enable_if<std::is_same<T, char>::value, T>::type {
128 RETURN_VALUE(Type::Character, c,)
129 }
130 template auto any::cast<char>() const -> char;
132 template <typename T>
133 auto any::cast() const -> typename std::enable_if<std::is_same<T, bool>::value, T>::type {
134 RETURN_VALUE(Type::Boolean, b,)
135 }
136 template auto any::cast<bool>() const -> bool;
138 template <typename T>
139 auto any::cast() const -> typename std::enable_if<std::is_same<T, string>::value, const T&>::type {
140 RETURN_VALUE(Type::String, s, *)
141 }
142 template auto any::cast<string>() const -> const string&;
144 template <typename T>
145 auto any::cast() const -> typename std::enable_if<std::is_same<T, const char*>::value, const T>::type {
146 RETURN_VALUE(Type::String, s->c_str(),)
147 }
148 template auto any::cast<const char*>() const -> const char* const;
150 template <typename T>
151 auto any::cast() const -> typename std::enable_if<std::is_same<T, map>::value, const T&>::type {
152 RETURN_VALUE(Type::Map, m, *)
153 }
154 template auto any::cast<any::map>() const -> const map&;
156 template <typename T>
157 auto any::cast() const -> typename std::enable_if<std::is_same<T, vector>::value, const T&>::type {
158 RETURN_VALUE(Type::Vector, v, *)
159 }
160 template auto any::cast<any::vector>() const -> const vector&;
162 auto any::operator()(const any& arg) const -> any {
163 if (type == Type::Function) {
164 return (*f)(arg);
165 }
166 const any* valuePtr = this;
167 do {
168 assert(valuePtr->type == Type::Thunk);
169 const any& value = (*valuePtr->t)(unthunk);
170 if (value.type == Type::Function) {
171 return (*value.f)(arg);
172 }
173 valuePtr = &value;
174 } while (valuePtr->type != Type::Unknown);
175 assert(false && "Unknown value type");
176 return nullptr;
177 }
179 auto any::operator()(const as_thunk) const -> const any& {
180 assert(type == Type::Thunk);
181 return (*t)(unthunk);
182 }
184 auto any::operator()() const -> any {
185 if (type == Type::EffFunction) {
186 return (*e)();
187 }
188 const any* valuePtr = this;
189 do {
190 assert(valuePtr->type == Type::Thunk);
191 const any& value = (*valuePtr->t)(unthunk);
192 if (value.type == Type::EffFunction) {
193 return (*value.e)();
194 }
195 valuePtr = &value;
196 } while (valuePtr->type != Type::Unknown);
197 assert(false && "Unknown value type");
198 return nullptr;
199 }
201 any::operator long() const {
202 RETURN_VALUE(Type::Integer, i,)
203 }
205 any::operator double() const {
206 RETURN_VALUE(Type::Double, d,)
207 }
209 any::operator bool() const {
210 RETURN_VALUE(Type::Boolean, b,)
211 }
213 any::operator const string&() const {
214 RETURN_VALUE(Type::String, s, *)
215 }
217 any::operator const map&() const {
218 RETURN_VALUE(Type::Map, m, *)
219 }
221 any::operator const vector&() const {
222 RETURN_VALUE(Type::Vector, v, *)
223 }
225 auto any::extractPointer() const -> void* {
226 RETURN_VALUE(Type::Pointer, p.get(),)
227 }
229 auto any::extract_value(const any& a) -> const any& {
230 if (a.type != Type::Thunk) {
231 return a;
232 }
233 const any* valuePtr = &a;
234 do {
235 const any& value = (*valuePtr->t)(unthunk);
236 if (value.type != Type::Thunk) {
237 return value;
238 }
239 valuePtr = &value;
240 } while (valuePtr->type != Type::Unknown);
241 assert(false && "Unknown value type");
242 return a;
243 }
245 auto any::operator[](const map_key_t& rhs) const -> const any& {
246 RETURN_VALUE(Type::Map, m->at(rhs),)
247 }
249 auto any::operator[](const vector::size_type rhs) const -> const any& {
250 RETURN_VALUE(Type::Vector, v->at(rhs),)
251 }
253 auto any::operator[](const any& rhs) const -> const any& {
254 RETURN_VALUE(Type::Vector, v->at(rhs.cast<long>()),)
255 }
257#define DEFINE_OPERATOR_LHS(K, T, OP, V, R, P) \
258auto operator OP(const T lhs, const any& rhs_) -> R { \
259 const any& rhs = any::extract_value(rhs_); \
260 assert(rhs.type == any::Type::K); \
261 return lhs OP P(rhs.V); \
264#define DEFINE_OPERATOR_RHS(K, T, OP, V, R, P) \
265auto any::operator OP(const T rhs) const -> R { \
266 const any& lhs = any::extract_value(*this); \
267 assert(lhs.type == Type::K); \
268 return P(lhs.V) OP rhs; \
271auto any::operator==(const any& rhs_) const -> bool {
272 const any& lhs = extract_value(*this);
273 const any& rhs = extract_value(rhs_);
274 assert(lhs.type == rhs.type);
275 switch (lhs.type) {
276 case Type::Integer: return lhs.i == rhs.i;
277 case Type::Double: return lhs.d == rhs.d;
278 case Type::Character: return lhs.c == rhs.c;
279 case Type::Boolean: return lhs.b == rhs.b;
280 case Type::String: return (*lhs.s) == (*rhs.s);
281 case Type::Pointer: return lhs.p == rhs.p;
282 default: assert(false && "Unsupported type for '==' operator");
283 }
284 return false;
287DEFINE_OPERATOR_RHS(Integer, long, ==, i, bool,)
288DEFINE_OPERATOR_RHS(Double, double, ==, d, bool,)
289DEFINE_OPERATOR_RHS(Character, char, ==, c, bool,)
290DEFINE_OPERATOR_RHS(Boolean, bool, ==, b, bool,)
291DEFINE_OPERATOR_RHS(String, string&, ==, s, bool, *)
292DEFINE_OPERATOR_RHS(String, char* const, ==, s, bool, *)
294auto any::operator!=(const any& rhs_) const -> bool {
295 const any& lhs = extract_value(*this);
296 const any& rhs = extract_value(rhs_);
297 assert(lhs.type == rhs.type);
298 switch (lhs.type) {
299 case Type::Integer: return lhs.i != rhs.i;
300 case Type::Double: return lhs.d != rhs.d;
301 case Type::Character: return lhs.c != rhs.c;
302 case Type::Boolean: return lhs.b != rhs.b;
303 case Type::String: return (*lhs.s) != (*rhs.s);
304 case Type::Pointer: return lhs.p != rhs.p;
305 default: assert(false && "Unsupported type for '!=' operator");
306 }
307 return false;
310DEFINE_OPERATOR_RHS(Integer, long, !=, i, bool,)
311DEFINE_OPERATOR_RHS(Double, double, !=, d, bool,)
312DEFINE_OPERATOR_RHS(Character, char, !=, c, bool,)
313DEFINE_OPERATOR_RHS(Boolean, bool, !=, b, bool,)
314DEFINE_OPERATOR_RHS(String, string&, !=, s, bool, *)
315DEFINE_OPERATOR_RHS(String, char* const, !=, s, bool, *)
317auto any::operator<(const any& rhs_) const -> bool {
318 const any& lhs = extract_value(*this);
319 const any& rhs = extract_value(rhs_);
320 assert(lhs.type == rhs.type);
321 switch (lhs.type) {
322 case Type::Integer: return lhs.i < rhs.i;
323 case Type::Double: return lhs.d < rhs.d;
324 case Type::Character: return lhs.c < rhs.c;
325 case Type::Boolean: return lhs.b < rhs.b;
326 case Type::String: return (*lhs.s) < (*rhs.s);
327 default: assert(false && "Unsupported type for '<' operator");
328 }
329 return false;
332DEFINE_OPERATOR_RHS(Integer, long, <, i, bool,)
333DEFINE_OPERATOR_RHS(Double, double, <, d, bool,)
334DEFINE_OPERATOR_RHS(Character, char, <, c, bool,)
335DEFINE_OPERATOR_RHS(Boolean, bool, <, b, bool,)
336DEFINE_OPERATOR_RHS(String, string&, <, s, bool, *)
337DEFINE_OPERATOR_RHS(String, char* const, <, s, bool, *)
339auto any::operator<=(const any& rhs_) const -> bool {
340 const any& lhs = extract_value(*this);
341 const any& rhs = extract_value(rhs_);
342 assert(lhs.type == rhs.type);
343 switch (lhs.type) {
344 case Type::Integer: return lhs.i <= rhs.i;
345 case Type::Double: return lhs.d <= rhs.d;
346 case Type::Character: return lhs.c <= rhs.c;
347 case Type::Boolean: return lhs.b <= rhs.b;
348 case Type::String: return (*lhs.s) <= (*rhs.s);
349 default: assert(false && "Unsupported type for '<' operator");
350 }
351 return false;
354DEFINE_OPERATOR_RHS(Integer, long, <=, i, bool,)
355DEFINE_OPERATOR_RHS(Double, double, <=, d, bool,)
356DEFINE_OPERATOR_RHS(Character, char, <=, c, bool,)
357DEFINE_OPERATOR_RHS(Boolean, bool, <=, b, bool,)
358DEFINE_OPERATOR_RHS(String, string&, <=, s, bool, *)
359DEFINE_OPERATOR_RHS(String, char* const, <=, s, bool, *)
361auto any::operator>(const any& rhs_) const -> bool {
362 const any& lhs = extract_value(*this);
363 const any& rhs = extract_value(rhs_);
364 assert(lhs.type == rhs.type);
365 switch (lhs.type) {
366 case Type::Integer: return lhs.i > rhs.i;
367 case Type::Double: return lhs.d > rhs.d;
368 case Type::Character: return lhs.c > rhs.c;
369 case Type::Boolean: return lhs.b > rhs.b;
370 case Type::String: return (*lhs.s) > (*rhs.s);
371 default: assert(false && "Unsupported type for '>' operator");
372 }
373 return false;
376DEFINE_OPERATOR_RHS(Integer, long, >, i, bool,)
377DEFINE_OPERATOR_RHS(Double, double, >, d, bool,)
378DEFINE_OPERATOR_RHS(Character, char, >, c, bool,)
379DEFINE_OPERATOR_RHS(Boolean, bool, >, b, bool,)
380DEFINE_OPERATOR_RHS(String, string&, >, s, bool, *)
381DEFINE_OPERATOR_RHS(String, char* const, >, s, bool, *)
383auto any::operator>=(const any& rhs_) const -> bool {
384 const any& lhs = extract_value(*this);
385 const any& rhs = extract_value(rhs_);
386 assert(lhs.type == rhs.type);
387 switch (lhs.type) {
388 case Type::Integer: return lhs.i >= rhs.i;
389 case Type::Double: return lhs.d >= rhs.d;
390 case Type::Character: return lhs.c >= rhs.c;
391 case Type::Boolean: return lhs.b >= rhs.b;
392 case Type::String: return (*lhs.s) >= (*rhs.s);
393 default: assert(false && "Unsupported type for '>' operator");
394 }
395 return false;
398DEFINE_OPERATOR_RHS(Integer, long, >=, i, bool,)
399DEFINE_OPERATOR_RHS(Double, double, >=, d, bool,)
400DEFINE_OPERATOR_RHS(Character, char, >=, c, bool,)
401DEFINE_OPERATOR_RHS(Boolean, bool, >=, b, bool,)
402DEFINE_OPERATOR_RHS(String, string&, >=, s, bool, *)
403DEFINE_OPERATOR_RHS(String, char* const, >=, s, bool, *)
405auto any::operator+(const any& rhs_) const -> any {
406 const any& lhs = extract_value(*this);
407 const any& rhs = extract_value(rhs_);
408 assert(lhs.type == rhs.type);
409 switch (lhs.type) {
410 case Type::Integer: return lhs.i + rhs.i;
411 case Type::Double: return lhs.d + rhs.d;
412 case Type::Character: return any(char(lhs.c + rhs.c));
413 case Type::String: return (*lhs.s) + (*rhs.s);
414 default: assert(false && "Unsupported type for '+' operator");
415 }
416 return nullptr;
419DEFINE_OPERATOR_RHS(Integer, long, +, i, long,)
420DEFINE_OPERATOR_RHS(Double, double, +, d, double,)
421DEFINE_OPERATOR_RHS(Character, char, +, c, char,)
422DEFINE_OPERATOR_RHS(String, string&, +, s, string, *)
423DEFINE_OPERATOR_RHS(String, char* const, +, s, string, *)
425auto any::operator-(const any& rhs_) const -> any {
426 const any& lhs = extract_value(*this);
427 const any& rhs = extract_value(rhs_);
428 assert(lhs.type == rhs.type);
429 switch (lhs.type) {
430 case Type::Integer: return lhs.i - rhs.i;
431 case Type::Double: return lhs.d - rhs.d;
432 case Type::Character: return any(char(lhs.c - rhs.c));
433 default: assert(false && "Unsupported type for '-' binary operator");
434 }
435 return nullptr;
438DEFINE_OPERATOR_RHS(Integer, long, -, i, long,)
439DEFINE_OPERATOR_RHS(Double, double, -, d, double,)
440DEFINE_OPERATOR_RHS(Character, char, -, c, char,)
442auto any::operator*(const any& rhs_) const -> any {
443 const any& lhs = extract_value(*this);
444 const any& rhs = extract_value(rhs_);
445 assert(lhs.type == rhs.type);
446 switch (lhs.type) {
447 case Type::Integer: return lhs.i * rhs.i;
448 case Type::Double: return lhs.d * rhs.d;
449 default: assert(false && "Unsupported type for '*' operator");
450 }
451 return nullptr;
454DEFINE_OPERATOR_RHS(Integer, long, *, i, long,)
455DEFINE_OPERATOR_RHS(Double, double, *, d, double,)
457auto any::operator/(const any& rhs_) const -> any {
458 const any& lhs = extract_value(*this);
459 const any& rhs = extract_value(rhs_);
460 assert(lhs.type == rhs.type);
461 switch (lhs.type) {
462 case Type::Integer: return lhs.i / rhs.i;
463 case Type::Double: return lhs.d / rhs.d;
464 default: assert(false && "Unsupported type for '/' operator");
465 }
466 return nullptr;
469DEFINE_OPERATOR_RHS(Integer, long, /, i, long,)
470DEFINE_OPERATOR_RHS(Double, double, /, d, double,)
472auto any::operator%(const any& rhs_) const -> any {
473 const any& lhs = extract_value(*this);
474 const any& rhs = extract_value(rhs_);
475 assert(lhs.type == rhs.type);
476 switch (lhs.type) {
477 case Type::Integer: return lhs.i % rhs.i;
478 default: assert(false && "Unsupported type for '%' operator");
479 }
480 return nullptr;
483DEFINE_OPERATOR_RHS(Integer, long, %, i, long,)
485auto any::operator-() const -> any {
486 const any& lhs = any::extract_value(*this);
487 switch (lhs.type) {
488 case Type::Integer: return (- lhs.i);
489 case Type::Double: return (- lhs.d);
490 default: assert(false && "Unsupported type for unary '-' operator");
491 }
492 return nullptr;
495DEFINE_OPERATOR_LHS(Integer, long, ==, i, bool,)
496DEFINE_OPERATOR_LHS(Integer, long, !=, i, bool,)
497DEFINE_OPERATOR_LHS(Integer, long, <, i, bool,)
498DEFINE_OPERATOR_LHS(Integer, long, <=, i, bool,)
499DEFINE_OPERATOR_LHS(Integer, long, >, i, bool,)
500DEFINE_OPERATOR_LHS(Integer, long, >=, i, bool,)
502DEFINE_OPERATOR_LHS(Double, double, ==, d, bool,)
503DEFINE_OPERATOR_LHS(Double, double, !=, d, bool,)
504DEFINE_OPERATOR_LHS(Double, double, <, d, bool,)
505DEFINE_OPERATOR_LHS(Double, double, <=, d, bool,)
506DEFINE_OPERATOR_LHS(Double, double, >, d, bool,)
507DEFINE_OPERATOR_LHS(Double, double, >=, d, bool,)
509DEFINE_OPERATOR_LHS(Character, char, ==, c, bool,)
510DEFINE_OPERATOR_LHS(Character, char, !=, c, bool,)
511DEFINE_OPERATOR_LHS(Character, char, <, c, bool,)
512DEFINE_OPERATOR_LHS(Character, char, <=, c, bool,)
513DEFINE_OPERATOR_LHS(Character, char, >, c, bool,)
514DEFINE_OPERATOR_LHS(Character, char, >=, c, bool,)
516DEFINE_OPERATOR_LHS(Boolean, bool, ==, b, bool,)
517DEFINE_OPERATOR_LHS(Boolean, bool, !=, b, bool,)
518DEFINE_OPERATOR_LHS(Boolean, bool, <, b, bool,)
519DEFINE_OPERATOR_LHS(Boolean, bool, <=, b, bool,)
520DEFINE_OPERATOR_LHS(Boolean, bool, >, b, bool,)
521DEFINE_OPERATOR_LHS(Boolean, bool, >=, b, bool,)
523DEFINE_OPERATOR_LHS(String, string&, ==, s, bool, *)
524DEFINE_OPERATOR_LHS(String, string&, !=, s, bool, *)
525DEFINE_OPERATOR_LHS(String, string&, <, s, bool, *)
526DEFINE_OPERATOR_LHS(String, string&, <=, s, bool, *)
527DEFINE_OPERATOR_LHS(String, string&, >, s, bool, *)
528DEFINE_OPERATOR_LHS(String, string&, >=, s, bool, *)
530DEFINE_OPERATOR_LHS(String, char* const, ==, s, bool, *)
531DEFINE_OPERATOR_LHS(String, char* const, !=, s, bool, *)
532DEFINE_OPERATOR_LHS(String, char* const, <, s, bool, *)
533DEFINE_OPERATOR_LHS(String, char* const, <=, s, bool, *)
534DEFINE_OPERATOR_LHS(String, char* const, >, s, bool, *)
535DEFINE_OPERATOR_LHS(String, char* const, >=, s, bool, *)
537DEFINE_OPERATOR_LHS(Integer, long, +, i, long,)
538DEFINE_OPERATOR_LHS(Integer, long, -, i, long,)
539DEFINE_OPERATOR_LHS(Integer, long, *, i, long,)
540DEFINE_OPERATOR_LHS(Integer, long, /, i, long,)
541DEFINE_OPERATOR_LHS(Integer, long, %, i, long,)
543DEFINE_OPERATOR_LHS(Double, double, +, d, double,)
544DEFINE_OPERATOR_LHS(Double, double, -, d, double,)
545DEFINE_OPERATOR_LHS(Double, double, *, d, double,)
546DEFINE_OPERATOR_LHS(Double, double, /, d, double,)
548DEFINE_OPERATOR_LHS(Character, char, +, i, char,)
549DEFINE_OPERATOR_LHS(Character, char, -, i, char,)
551DEFINE_OPERATOR_LHS(String, string&, +, s, string, *)
552DEFINE_OPERATOR_LHS(String, char* const, +, s, string, *)
555} // namespace PureScript