git.iko.soy/rowtype-yoga/purescript-native
on 41d055f help sign in
536 lines 19 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 {
19any::any(const any& val) : type(val.type) {
20 switch (type) {
21 case Type::Integer: i = val.i; break;
22 case Type::Double: d = val.d; break;
23 case Type::Character: c = val.c; break;
24 case Type::Boolean: b = val.b; break;
25 case Type::String: new (&s) shared_string (val.s); break;
26 case Type::Map: new (&m) shared_map (val.m); break;
27 case Type::Vector: new (&v) shared_vector (val.v); break;
28 case Type::Function: new (&f) shared_fn (val.f); break;
29 case Type::EffFunction: new (&e) shared_eff_fn (val.e); break;
30 case Type::Thunk: new (&t) shared_thunk (val.t); break;
31 case Type::Pointer: new (&p) shared_void_ptr (val.p); break;
33 default: assert(false && "Unsupported type in copy ctor");
34 }
37void any::swap(any&& val) {
38 type = val.type;
39 switch (type) {
40 case Type::Integer: i = val.i; break;
41 case Type::Double: d = val.d; break;
42 case Type::Character: c = val.c; break;
43 case Type::Boolean: b = val.b; break;
44 case Type::String: new (&s) shared_string (std::move(val.s)); break;
45 case Type::Map: new (&m) shared_map (std::move(val.m)); break;
46 case Type::Vector: new (&v) shared_vector (std::move(val.v)); break;
47 case Type::Function: new (&f) shared_fn (std::move(val.f)); break;
48 case Type::EffFunction: new (&e) shared_eff_fn (std::move(val.e)); break;
49 case Type::Thunk: new (&t) shared_thunk (std::move(val.t)); break;
50 case Type::Pointer: new (&p) shared_void_ptr (std::move(val.p)); break;
52 default: assert(false && "Unsupported type in move ctor");
53 }
56any::~any() {
57 // std::cout << "destroy" << std::endl;
58 switch (type) {
59 case Type::Integer: ; break;
60 case Type::Double: ; break;
61 case Type::Character: ; break;
62 case Type::Boolean: ; break;
63 case Type::String: s.~shared_string(); break;
64 case Type::Map: m.~shared_map(); break;
65 case Type::Vector: v.~shared_vector(); break;
66 case Type::Function: f.~shared_fn(); break;
67 case Type::EffFunction: e.~shared_eff_fn(); break;
68 case Type::Thunk: t.~shared_thunk(); break;
69 case Type::Pointer: p.~shared_void_ptr(); break;
71 default: assert(false && "Unsupported type in destructor");
72 }
73};
75 #define RETURN_VALUE(TYPE, VAL, FN) \
76 if (type == TYPE) { \
77 return FN(VAL); \
78 } \
79 const any* valuePtr = this; \
80 do { \
81 assert(valuePtr->type == Type::Thunk); \
82 const any& value = (*valuePtr->t)(unthunk); \
83 if (value.type == TYPE) { \
84 return FN(value.VAL); \
85 } \
86 valuePtr = &value; \
87 } while (valuePtr->type != Type::Unknown); \
88 return FN(VAL);
90 template <typename T>
91 auto any::cast() const -> typename std::enable_if<std::is_same<T, long>::value, T>::type {
92 RETURN_VALUE(Type::Integer, i,)
93 }
94 template auto any::cast<long>() const -> long;
96 template <typename T>
97 auto any::cast() const -> typename std::enable_if<std::is_same<T, double>::value, T>::type {
98 RETURN_VALUE(Type::Double, d,)
99 }
100 template auto any::cast<double>() const -> double;
102 template <typename T>
103 auto any::cast() const -> typename std::enable_if<std::is_same<T, char>::value, T>::type {
104 RETURN_VALUE(Type::Character, c,)
105 }
106 template auto any::cast<char>() const -> char;
108 template <typename T>
109 auto any::cast() const -> typename std::enable_if<std::is_same<T, bool>::value, T>::type {
110 RETURN_VALUE(Type::Boolean, b,)
111 }
112 template auto any::cast<bool>() const -> bool;
114 template <typename T>
115 auto any::cast() const -> typename std::enable_if<std::is_same<T, string>::value, const T&>::type {
116 RETURN_VALUE(Type::String, s, *)
117 }
118 template auto any::cast<string>() const -> const string&;
120 template <typename T>
121 auto any::cast() const -> typename std::enable_if<std::is_same<T, const char*>::value, const T>::type {
122 RETURN_VALUE(Type::String, s->c_str(),)
123 }
124 template auto any::cast<const char*>() const -> const char* const;
126 template <typename T>
127 auto any::cast() const -> typename std::enable_if<std::is_same<T, map>::value, const T&>::type {
128 RETURN_VALUE(Type::Map, m, *)
129 }
130 template auto any::cast<any::map>() const -> const map&;
132 template <typename T>
133 auto any::cast() const -> typename std::enable_if<std::is_same<T, vector>::value, const T&>::type {
134 RETURN_VALUE(Type::Vector, v, *)
135 }
136 template auto any::cast<any::vector>() const -> const vector&;
139 auto any::operator()(const any arg) const -> any {
140 if (type == Type::Function) {
141 return (*f)(arg);
142 }
143 const any* valuePtr = this;
144 do {
145 assert(valuePtr->type == Type::Thunk);
146 const any& value = (*valuePtr->t)(unthunk);
147 if (value.type == Type::Function) {
148 return (*value.f)(arg);
149 }
150 valuePtr = &value;
151 } while (valuePtr->type != Type::Unknown);
152 return nullptr;
153 }
155 auto any::operator()(const as_thunk) const -> const any& {
156 assert(type == Type::Thunk);
157 return (*t)(unthunk);
158 }
160 auto any::call(const any& a) -> any {
161 assert(a.type == Type::EffFunction || a.type == Type::Function);
162 if (a.type == Type::EffFunction) {
163 return (*a.e)();
164 } else {
165 return (*a.f)(false);
166 }
167 }
169 auto any::operator()() const -> any {
170 if (type == Type::EffFunction || type == Type::Function) {
171 return call(*this);
172 }
173 assert(type == Type::Thunk);
174 const any* valuePtr = this;
175 do {
176 const any& value = (*valuePtr->t)(unthunk);
177 if (value.type != Type::Thunk) {
178 return call(value);
179 }
180 valuePtr = &value;
181 } while (true);
182 }
184 any::operator long() const {
185 RETURN_VALUE(Type::Integer, i,)
186 }
188 any::operator double() const {
189 RETURN_VALUE(Type::Double, d,)
190 }
192 any::operator bool() const {
193 RETURN_VALUE(Type::Boolean, b,)
194 }
196 any::operator const string&() const {
197 RETURN_VALUE(Type::String, s, *)
198 }
200 any::operator const map&() const {
201 RETURN_VALUE(Type::Map, m, *)
202 }
204 any::operator const vector&() const {
205 RETURN_VALUE(Type::Vector, v, *)
206 }
208 auto any::extractPointer() const -> const void* {
209 RETURN_VALUE(Type::Pointer, p.get(),)
210 }
212 auto any::extract_value(const any& a) -> const any& {
213 if (a.type != Type::Thunk) {
214 return a;
215 }
216 const any* valuePtr = &a;
217 do {
218 const any& value = (*valuePtr->t)(unthunk);
219 if (value.type != Type::Thunk) {
220 return value;
221 }
222 valuePtr = &value;
223 } while (true);
224 }
226 auto any::operator[](const map_key_t rhs) const -> const any& {
227 RETURN_VALUE(Type::Map, m->at(rhs),)
228 }
230 auto any::operator[](const vector::size_type rhs) const -> const any& {
231 RETURN_VALUE(Type::Vector, v->at(rhs),)
232 }
234 auto any::operator[](const any& rhs) const -> const any& {
235 RETURN_VALUE(Type::Vector, v->at(rhs.cast<long>()),)
236 }
238#define DEFINE_OPERATOR_LHS(K, T, OP, V, R, P) \
239auto operator OP(const T lhs, const any& rhs_) -> R { \
240 auto& rhs = any::extract_value(rhs_); \
241 assert(rhs.type == any::Type::K); \
242 return lhs OP P(rhs.V); \
245#define DEFINE_OPERATOR_RHS(K, T, OP, V, R, P) \
246auto any::operator OP(const T rhs) const -> R { \
247 auto& lhs = any::extract_value(*this); \
248 assert(lhs.type == Type::K); \
249 return P(lhs.V) OP rhs; \
252auto any::operator==(const any& rhs_) const -> bool {
253 auto& lhs = extract_value(*this);
254 auto& rhs = extract_value(rhs_);
255 assert(lhs.type == rhs.type);
256 switch (lhs.type) {
257 case Type::Integer: return lhs.i == rhs.i;
258 case Type::Double: return lhs.d == rhs.d;
259 case Type::Character: return lhs.c == rhs.c;
260 case Type::Boolean: return lhs.b == rhs.b;
261 case Type::String: return (*lhs.s) == (*rhs.s);
262 case Type::Pointer: return lhs.p == rhs.p;
263 default: assert(false && "Unsupported type for '==' operator");
264 }
265 return false;
268DEFINE_OPERATOR_RHS(Integer, long, ==, i, bool,)
269DEFINE_OPERATOR_RHS(Double, double, ==, d, bool,)
270DEFINE_OPERATOR_RHS(Character, char, ==, c, bool,)
271DEFINE_OPERATOR_RHS(Boolean, bool, ==, b, bool,)
272DEFINE_OPERATOR_RHS(String, string&, ==, s, bool, *)
273DEFINE_OPERATOR_RHS(String, char* const, ==, s, bool, *)
275auto any::operator!=(const any& rhs_) const -> bool {
276 auto& lhs = extract_value(*this);
277 auto& rhs = extract_value(rhs_);
278 assert(lhs.type == rhs.type);
279 switch (lhs.type) {
280 case Type::Integer: return lhs.i != rhs.i;
281 case Type::Double: return lhs.d != rhs.d;
282 case Type::Character: return lhs.c != rhs.c;
283 case Type::Boolean: return lhs.b != rhs.b;
284 case Type::String: return (*lhs.s) != (*rhs.s);
285 case Type::Pointer: return lhs.p != rhs.p;
286 default: assert(false && "Unsupported type for '!=' operator");
287 }
288 return false;
291DEFINE_OPERATOR_RHS(Integer, long, !=, i, bool,)
292DEFINE_OPERATOR_RHS(Double, double, !=, d, bool,)
293DEFINE_OPERATOR_RHS(Character, char, !=, c, bool,)
294DEFINE_OPERATOR_RHS(Boolean, bool, !=, b, bool,)
295DEFINE_OPERATOR_RHS(String, string&, !=, s, bool, *)
296DEFINE_OPERATOR_RHS(String, char* const, !=, s, bool, *)
298auto any::operator<(const any& rhs_) const -> bool {
299 auto& lhs = extract_value(*this);
300 auto& rhs = extract_value(rhs_);
301 assert(lhs.type == rhs.type);
302 switch (lhs.type) {
303 case Type::Integer: return lhs.i < rhs.i;
304 case Type::Double: return lhs.d < rhs.d;
305 case Type::Character: return lhs.c < rhs.c;
306 case Type::Boolean: return lhs.b < rhs.b;
307 case Type::String: return (*lhs.s) < (*rhs.s);
308 default: assert(false && "Unsupported type for '<' operator");
309 }
310 return false;
313DEFINE_OPERATOR_RHS(Integer, long, <, i, bool,)
314DEFINE_OPERATOR_RHS(Double, double, <, d, bool,)
315DEFINE_OPERATOR_RHS(Character, char, <, c, bool,)
316DEFINE_OPERATOR_RHS(Boolean, bool, <, b, bool,)
317DEFINE_OPERATOR_RHS(String, string&, <, s, bool, *)
318DEFINE_OPERATOR_RHS(String, char* const, <, s, bool, *)
320auto any::operator<=(const any& rhs_) const -> bool {
321 auto& lhs = extract_value(*this);
322 auto& rhs = extract_value(rhs_);
323 assert(lhs.type == rhs.type);
324 switch (lhs.type) {
325 case Type::Integer: return lhs.i <= rhs.i;
326 case Type::Double: return lhs.d <= rhs.d;
327 case Type::Character: return lhs.c <= rhs.c;
328 case Type::Boolean: return lhs.b <= rhs.b;
329 case Type::String: return (*lhs.s) <= (*rhs.s);
330 default: assert(false && "Unsupported type for '<' operator");
331 }
332 return false;
335DEFINE_OPERATOR_RHS(Integer, long, <=, i, bool,)
336DEFINE_OPERATOR_RHS(Double, double, <=, d, bool,)
337DEFINE_OPERATOR_RHS(Character, char, <=, c, bool,)
338DEFINE_OPERATOR_RHS(Boolean, bool, <=, b, bool,)
339DEFINE_OPERATOR_RHS(String, string&, <=, s, bool, *)
340DEFINE_OPERATOR_RHS(String, char* const, <=, s, bool, *)
342auto any::operator>(const any& rhs_) const -> bool {
343 auto& lhs = extract_value(*this);
344 auto& rhs = extract_value(rhs_);
345 assert(lhs.type == rhs.type);
346 switch (lhs.type) {
347 case Type::Integer: return lhs.i > rhs.i;
348 case Type::Double: return lhs.d > rhs.d;
349 case Type::Character: return lhs.c > rhs.c;
350 case Type::Boolean: return lhs.b > rhs.b;
351 case Type::String: return (*lhs.s) > (*rhs.s);
352 default: assert(false && "Unsupported type for '>' operator");
353 }
354 return false;
357DEFINE_OPERATOR_RHS(Integer, long, >, i, bool,)
358DEFINE_OPERATOR_RHS(Double, double, >, d, bool,)
359DEFINE_OPERATOR_RHS(Character, char, >, c, bool,)
360DEFINE_OPERATOR_RHS(Boolean, bool, >, b, bool,)
361DEFINE_OPERATOR_RHS(String, string&, >, s, bool, *)
362DEFINE_OPERATOR_RHS(String, char* const, >, s, bool, *)
364auto any::operator>=(const any& rhs_) const -> bool {
365 auto& lhs = extract_value(*this);
366 auto& rhs = extract_value(rhs_);
367 assert(lhs.type == rhs.type);
368 switch (lhs.type) {
369 case Type::Integer: return lhs.i >= rhs.i;
370 case Type::Double: return lhs.d >= rhs.d;
371 case Type::Character: return lhs.c >= rhs.c;
372 case Type::Boolean: return lhs.b >= rhs.b;
373 case Type::String: return (*lhs.s) >= (*rhs.s);
374 default: assert(false && "Unsupported type for '>' operator");
375 }
376 return false;
379DEFINE_OPERATOR_RHS(Integer, long, >=, i, bool,)
380DEFINE_OPERATOR_RHS(Double, double, >=, d, bool,)
381DEFINE_OPERATOR_RHS(Character, char, >=, c, bool,)
382DEFINE_OPERATOR_RHS(Boolean, bool, >=, b, bool,)
383DEFINE_OPERATOR_RHS(String, string&, >=, s, bool, *)
384DEFINE_OPERATOR_RHS(String, char* const, >=, s, bool, *)
386auto any::operator+(const any& rhs_) const -> any {
387 auto& lhs = extract_value(*this);
388 auto& rhs = extract_value(rhs_);
389 assert(lhs.type == rhs.type);
390 switch (lhs.type) {
391 case Type::Integer: return lhs.i + rhs.i;
392 case Type::Double: return lhs.d + rhs.d;
393 case Type::Character: return any(char(lhs.c + rhs.c));
394 case Type::String: return (*lhs.s) + (*rhs.s);
395 default: assert(false && "Unsupported type for '+' operator");
396 }
397 return nullptr;
400DEFINE_OPERATOR_RHS(Integer, long, +, i, long,)
401DEFINE_OPERATOR_RHS(Double, double, +, d, double,)
402DEFINE_OPERATOR_RHS(Character, char, +, c, char,)
403DEFINE_OPERATOR_RHS(String, string&, +, s, string, *)
404DEFINE_OPERATOR_RHS(String, char* const, +, s, string, *)
406auto any::operator-(const any& rhs_) const -> any {
407 auto& lhs = extract_value(*this);
408 auto& rhs = extract_value(rhs_);
409 assert(lhs.type == rhs.type);
410 switch (lhs.type) {
411 case Type::Integer: return lhs.i - rhs.i;
412 case Type::Double: return lhs.d - rhs.d;
413 case Type::Character: return any(char(lhs.c - rhs.c));
414 default: assert(false && "Unsupported type for '-' binary 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,)
423auto any::operator*(const any& rhs_) const -> any {
424 auto& lhs = extract_value(*this);
425 auto& rhs = extract_value(rhs_);
426 assert(lhs.type == rhs.type);
427 switch (lhs.type) {
428 case Type::Integer: return lhs.i * rhs.i;
429 case Type::Double: return lhs.d * rhs.d;
430 default: assert(false && "Unsupported type for '*' operator");
431 }
432 return nullptr;
435DEFINE_OPERATOR_RHS(Integer, long, *, i, long,)
436DEFINE_OPERATOR_RHS(Double, double, *, d, double,)
438auto any::operator/(const any& rhs_) const -> any {
439 auto& lhs = extract_value(*this);
440 auto& rhs = extract_value(rhs_);
441 assert(lhs.type == rhs.type);
442 switch (lhs.type) {
443 case Type::Integer: return lhs.i / rhs.i;
444 case Type::Double: return lhs.d / rhs.d;
445 default: assert(false && "Unsupported type for '/' operator");
446 }
447 return nullptr;
450DEFINE_OPERATOR_RHS(Integer, long, /, i, long,)
451DEFINE_OPERATOR_RHS(Double, double, /, d, double,)
453auto any::operator%(const any& rhs_) const -> any {
454 auto& lhs = extract_value(*this);
455 auto& rhs = extract_value(rhs_);
456 assert(lhs.type == rhs.type);
457 switch (lhs.type) {
458 case Type::Integer: return lhs.i % rhs.i;
459 default: assert(false && "Unsupported type for '%' operator");
460 }
461 return nullptr;
464DEFINE_OPERATOR_RHS(Integer, long, %, i, long,)
466auto any::operator-() const -> any {
467 auto& lhs = any::extract_value(*this);
468 switch (lhs.type) {
469 case Type::Integer: return (- lhs.i);
470 case Type::Double: return (- lhs.d);
471 default: assert(false && "Unsupported type for unary '-' operator");
472 }
473 return nullptr;
476DEFINE_OPERATOR_LHS(Integer, long, ==, i, bool,)
477DEFINE_OPERATOR_LHS(Integer, long, !=, i, bool,)
478DEFINE_OPERATOR_LHS(Integer, long, <, i, bool,)
479DEFINE_OPERATOR_LHS(Integer, long, <=, i, bool,)
480DEFINE_OPERATOR_LHS(Integer, long, >, i, bool,)
481DEFINE_OPERATOR_LHS(Integer, long, >=, i, bool,)
483DEFINE_OPERATOR_LHS(Double, double, ==, d, bool,)
484DEFINE_OPERATOR_LHS(Double, double, !=, d, bool,)
485DEFINE_OPERATOR_LHS(Double, double, <, d, bool,)
486DEFINE_OPERATOR_LHS(Double, double, <=, d, bool,)
487DEFINE_OPERATOR_LHS(Double, double, >, d, bool,)
488DEFINE_OPERATOR_LHS(Double, double, >=, d, bool,)
490DEFINE_OPERATOR_LHS(Character, char, ==, c, bool,)
491DEFINE_OPERATOR_LHS(Character, char, !=, c, bool,)
492DEFINE_OPERATOR_LHS(Character, char, <, c, bool,)
493DEFINE_OPERATOR_LHS(Character, char, <=, c, bool,)
494DEFINE_OPERATOR_LHS(Character, char, >, c, bool,)
495DEFINE_OPERATOR_LHS(Character, char, >=, c, bool,)
497DEFINE_OPERATOR_LHS(Boolean, bool, ==, b, bool,)
498DEFINE_OPERATOR_LHS(Boolean, bool, !=, b, bool,)
499DEFINE_OPERATOR_LHS(Boolean, bool, <, b, bool,)
500DEFINE_OPERATOR_LHS(Boolean, bool, <=, b, bool,)
501DEFINE_OPERATOR_LHS(Boolean, bool, >, b, bool,)
502DEFINE_OPERATOR_LHS(Boolean, bool, >=, b, bool,)
504DEFINE_OPERATOR_LHS(String, string&, ==, s, bool, *)
505DEFINE_OPERATOR_LHS(String, string&, !=, s, bool, *)
506DEFINE_OPERATOR_LHS(String, string&, <, s, bool, *)
507DEFINE_OPERATOR_LHS(String, string&, <=, s, bool, *)
508DEFINE_OPERATOR_LHS(String, string&, >, s, bool, *)
509DEFINE_OPERATOR_LHS(String, string&, >=, s, bool, *)
511DEFINE_OPERATOR_LHS(String, char* const, ==, s, bool, *)
512DEFINE_OPERATOR_LHS(String, char* const, !=, s, bool, *)
513DEFINE_OPERATOR_LHS(String, char* const, <, s, bool, *)
514DEFINE_OPERATOR_LHS(String, char* const, <=, s, bool, *)
515DEFINE_OPERATOR_LHS(String, char* const, >, s, bool, *)
516DEFINE_OPERATOR_LHS(String, char* const, >=, s, bool, *)
518DEFINE_OPERATOR_LHS(Integer, long, +, i, long,)
519DEFINE_OPERATOR_LHS(Integer, long, -, i, long,)
520DEFINE_OPERATOR_LHS(Integer, long, *, i, long,)
521DEFINE_OPERATOR_LHS(Integer, long, /, i, long,)
522DEFINE_OPERATOR_LHS(Integer, long, %, i, long,)
524DEFINE_OPERATOR_LHS(Double, double, +, d, double,)
525DEFINE_OPERATOR_LHS(Double, double, -, d, double,)
526DEFINE_OPERATOR_LHS(Double, double, *, d, double,)
527DEFINE_OPERATOR_LHS(Double, double, /, d, double,)
529DEFINE_OPERATOR_LHS(Character, char, +, i, char,)
530DEFINE_OPERATOR_LHS(Character, char, -, i, char,)
532DEFINE_OPERATOR_LHS(String, string&, +, s, string, *)
533DEFINE_OPERATOR_LHS(String, char* const, +, s, string, *)
536} // namespace PureScript