git.iko.soy/rowtype-yoga/purescript-native
on 8b3c035 help sign in
528 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::operator()() const -> any {
161 if (type == Type::EffFunction) {
162 return (*e)();
163 }
164 const any* valuePtr = this;
165 do {
166 assert(valuePtr->type == Type::Thunk);
167 const any& value = (*valuePtr->t)(unthunk);
168 if (value.type == Type::EffFunction) {
169 return (*value.e)();
170 }
171 valuePtr = &value;
172 } while (valuePtr->type != Type::Unknown);
173 return nullptr;
174 }
176 any::operator long() const {
177 RETURN_VALUE(Type::Integer, i,)
178 }
180 any::operator double() const {
181 RETURN_VALUE(Type::Double, d,)
182 }
184 any::operator bool() const {
185 RETURN_VALUE(Type::Boolean, b,)
186 }
188 any::operator const string&() const {
189 RETURN_VALUE(Type::String, s, *)
190 }
192 any::operator const map&() const {
193 RETURN_VALUE(Type::Map, m, *)
194 }
196 any::operator const vector&() const {
197 RETURN_VALUE(Type::Vector, v, *)
198 }
200 auto any::extractPointer() const -> const void* {
201 RETURN_VALUE(Type::Pointer, p.get(),)
202 }
204 auto any::extract_value(const any& a) -> const any& {
205 if (a.type != Type::Thunk) {
206 return a;
207 }
208 const any* valuePtr = &a;
209 do {
210 const any& value = (*valuePtr->t)(unthunk);
211 if (value.type != Type::Thunk) {
212 return value;
213 }
214 valuePtr = &value;
215 } while (true);
216 }
218 auto any::operator[](const map_key_t rhs) const -> const any& {
219 RETURN_VALUE(Type::Map, m->at(rhs),)
220 }
222 auto any::operator[](const vector::size_type rhs) const -> const any& {
223 RETURN_VALUE(Type::Vector, v->at(rhs),)
224 }
226 auto any::operator[](const any& rhs) const -> const any& {
227 RETURN_VALUE(Type::Vector, v->at(rhs.cast<long>()),)
228 }
230#define DEFINE_OPERATOR_LHS(K, T, OP, V, R, P) \
231auto operator OP(const T lhs, const any& rhs_) -> R { \
232 auto& rhs = any::extract_value(rhs_); \
233 assert(rhs.type == any::Type::K); \
234 return lhs OP P(rhs.V); \
237#define DEFINE_OPERATOR_RHS(K, T, OP, V, R, P) \
238auto any::operator OP(const T rhs) const -> R { \
239 auto& lhs = any::extract_value(*this); \
240 assert(lhs.type == Type::K); \
241 return P(lhs.V) OP rhs; \
244auto any::operator==(const any& rhs_) const -> bool {
245 auto& lhs = extract_value(*this);
246 auto& rhs = extract_value(rhs_);
247 assert(lhs.type == rhs.type);
248 switch (lhs.type) {
249 case Type::Integer: return lhs.i == rhs.i;
250 case Type::Double: return lhs.d == rhs.d;
251 case Type::Character: return lhs.c == rhs.c;
252 case Type::Boolean: return lhs.b == rhs.b;
253 case Type::String: return (*lhs.s) == (*rhs.s);
254 case Type::Pointer: return lhs.p == rhs.p;
255 default: assert(false && "Unsupported type for '==' operator");
256 }
257 return false;
260DEFINE_OPERATOR_RHS(Integer, long, ==, i, bool,)
261DEFINE_OPERATOR_RHS(Double, double, ==, d, bool,)
262DEFINE_OPERATOR_RHS(Character, char, ==, c, bool,)
263DEFINE_OPERATOR_RHS(Boolean, bool, ==, b, bool,)
264DEFINE_OPERATOR_RHS(String, string&, ==, s, bool, *)
265DEFINE_OPERATOR_RHS(String, char* const, ==, s, bool, *)
267auto any::operator!=(const any& rhs_) const -> bool {
268 auto& lhs = extract_value(*this);
269 auto& rhs = extract_value(rhs_);
270 assert(lhs.type == rhs.type);
271 switch (lhs.type) {
272 case Type::Integer: return lhs.i != rhs.i;
273 case Type::Double: return lhs.d != rhs.d;
274 case Type::Character: return lhs.c != rhs.c;
275 case Type::Boolean: return lhs.b != rhs.b;
276 case Type::String: return (*lhs.s) != (*rhs.s);
277 case Type::Pointer: return lhs.p != rhs.p;
278 default: assert(false && "Unsupported type for '!=' operator");
279 }
280 return false;
283DEFINE_OPERATOR_RHS(Integer, long, !=, i, bool,)
284DEFINE_OPERATOR_RHS(Double, double, !=, d, bool,)
285DEFINE_OPERATOR_RHS(Character, char, !=, c, bool,)
286DEFINE_OPERATOR_RHS(Boolean, bool, !=, b, bool,)
287DEFINE_OPERATOR_RHS(String, string&, !=, s, bool, *)
288DEFINE_OPERATOR_RHS(String, char* const, !=, s, bool, *)
290auto any::operator<(const any& rhs_) const -> bool {
291 auto& lhs = extract_value(*this);
292 auto& rhs = extract_value(rhs_);
293 assert(lhs.type == rhs.type);
294 switch (lhs.type) {
295 case Type::Integer: return lhs.i < rhs.i;
296 case Type::Double: return lhs.d < rhs.d;
297 case Type::Character: return lhs.c < rhs.c;
298 case Type::Boolean: return lhs.b < rhs.b;
299 case Type::String: return (*lhs.s) < (*rhs.s);
300 default: assert(false && "Unsupported type for '<' operator");
301 }
302 return false;
305DEFINE_OPERATOR_RHS(Integer, long, <, i, bool,)
306DEFINE_OPERATOR_RHS(Double, double, <, d, bool,)
307DEFINE_OPERATOR_RHS(Character, char, <, c, bool,)
308DEFINE_OPERATOR_RHS(Boolean, bool, <, b, bool,)
309DEFINE_OPERATOR_RHS(String, string&, <, s, bool, *)
310DEFINE_OPERATOR_RHS(String, char* const, <, s, bool, *)
312auto any::operator<=(const any& rhs_) const -> bool {
313 auto& lhs = extract_value(*this);
314 auto& rhs = extract_value(rhs_);
315 assert(lhs.type == rhs.type);
316 switch (lhs.type) {
317 case Type::Integer: return lhs.i <= rhs.i;
318 case Type::Double: return lhs.d <= rhs.d;
319 case Type::Character: return lhs.c <= rhs.c;
320 case Type::Boolean: return lhs.b <= rhs.b;
321 case Type::String: return (*lhs.s) <= (*rhs.s);
322 default: assert(false && "Unsupported type for '<' operator");
323 }
324 return false;
327DEFINE_OPERATOR_RHS(Integer, long, <=, i, bool,)
328DEFINE_OPERATOR_RHS(Double, double, <=, d, bool,)
329DEFINE_OPERATOR_RHS(Character, char, <=, c, bool,)
330DEFINE_OPERATOR_RHS(Boolean, bool, <=, b, bool,)
331DEFINE_OPERATOR_RHS(String, string&, <=, s, bool, *)
332DEFINE_OPERATOR_RHS(String, char* const, <=, s, bool, *)
334auto any::operator>(const any& rhs_) const -> bool {
335 auto& lhs = extract_value(*this);
336 auto& rhs = extract_value(rhs_);
337 assert(lhs.type == rhs.type);
338 switch (lhs.type) {
339 case Type::Integer: return lhs.i > rhs.i;
340 case Type::Double: return lhs.d > rhs.d;
341 case Type::Character: return lhs.c > rhs.c;
342 case Type::Boolean: return lhs.b > rhs.b;
343 case Type::String: return (*lhs.s) > (*rhs.s);
344 default: assert(false && "Unsupported type for '>' operator");
345 }
346 return false;
349DEFINE_OPERATOR_RHS(Integer, long, >, i, bool,)
350DEFINE_OPERATOR_RHS(Double, double, >, d, bool,)
351DEFINE_OPERATOR_RHS(Character, char, >, c, bool,)
352DEFINE_OPERATOR_RHS(Boolean, bool, >, b, bool,)
353DEFINE_OPERATOR_RHS(String, string&, >, s, bool, *)
354DEFINE_OPERATOR_RHS(String, char* const, >, s, bool, *)
356auto any::operator>=(const any& rhs_) const -> bool {
357 auto& lhs = extract_value(*this);
358 auto& rhs = extract_value(rhs_);
359 assert(lhs.type == rhs.type);
360 switch (lhs.type) {
361 case Type::Integer: return lhs.i >= rhs.i;
362 case Type::Double: return lhs.d >= rhs.d;
363 case Type::Character: return lhs.c >= rhs.c;
364 case Type::Boolean: return lhs.b >= rhs.b;
365 case Type::String: return (*lhs.s) >= (*rhs.s);
366 default: assert(false && "Unsupported type for '>' operator");
367 }
368 return false;
371DEFINE_OPERATOR_RHS(Integer, long, >=, i, bool,)
372DEFINE_OPERATOR_RHS(Double, double, >=, d, bool,)
373DEFINE_OPERATOR_RHS(Character, char, >=, c, bool,)
374DEFINE_OPERATOR_RHS(Boolean, bool, >=, b, bool,)
375DEFINE_OPERATOR_RHS(String, string&, >=, s, bool, *)
376DEFINE_OPERATOR_RHS(String, char* const, >=, s, bool, *)
378auto any::operator+(const any& rhs_) const -> any {
379 auto& lhs = extract_value(*this);
380 auto& rhs = extract_value(rhs_);
381 assert(lhs.type == rhs.type);
382 switch (lhs.type) {
383 case Type::Integer: return lhs.i + rhs.i;
384 case Type::Double: return lhs.d + rhs.d;
385 case Type::Character: return any(char(lhs.c + rhs.c));
386 case Type::String: return (*lhs.s) + (*rhs.s);
387 default: assert(false && "Unsupported type for '+' operator");
388 }
389 return nullptr;
392DEFINE_OPERATOR_RHS(Integer, long, +, i, long,)
393DEFINE_OPERATOR_RHS(Double, double, +, d, double,)
394DEFINE_OPERATOR_RHS(Character, char, +, c, char,)
395DEFINE_OPERATOR_RHS(String, string&, +, s, string, *)
396DEFINE_OPERATOR_RHS(String, char* const, +, s, string, *)
398auto any::operator-(const any& rhs_) const -> any {
399 auto& lhs = extract_value(*this);
400 auto& rhs = extract_value(rhs_);
401 assert(lhs.type == rhs.type);
402 switch (lhs.type) {
403 case Type::Integer: return lhs.i - rhs.i;
404 case Type::Double: return lhs.d - rhs.d;
405 case Type::Character: return any(char(lhs.c - rhs.c));
406 default: assert(false && "Unsupported type for '-' binary operator");
407 }
408 return nullptr;
411DEFINE_OPERATOR_RHS(Integer, long, -, i, long,)
412DEFINE_OPERATOR_RHS(Double, double, -, d, double,)
413DEFINE_OPERATOR_RHS(Character, char, -, c, char,)
415auto any::operator*(const any& rhs_) const -> any {
416 auto& lhs = extract_value(*this);
417 auto& rhs = extract_value(rhs_);
418 assert(lhs.type == rhs.type);
419 switch (lhs.type) {
420 case Type::Integer: return lhs.i * rhs.i;
421 case Type::Double: return lhs.d * rhs.d;
422 default: assert(false && "Unsupported type for '*' operator");
423 }
424 return nullptr;
427DEFINE_OPERATOR_RHS(Integer, long, *, i, long,)
428DEFINE_OPERATOR_RHS(Double, double, *, d, double,)
430auto any::operator/(const any& rhs_) const -> any {
431 auto& lhs = extract_value(*this);
432 auto& rhs = extract_value(rhs_);
433 assert(lhs.type == rhs.type);
434 switch (lhs.type) {
435 case Type::Integer: return lhs.i / rhs.i;
436 case Type::Double: return lhs.d / rhs.d;
437 default: assert(false && "Unsupported type for '/' operator");
438 }
439 return nullptr;
442DEFINE_OPERATOR_RHS(Integer, long, /, i, long,)
443DEFINE_OPERATOR_RHS(Double, double, /, d, double,)
445auto any::operator%(const any& rhs_) const -> any {
446 auto& lhs = extract_value(*this);
447 auto& rhs = extract_value(rhs_);
448 assert(lhs.type == rhs.type);
449 switch (lhs.type) {
450 case Type::Integer: return lhs.i % rhs.i;
451 default: assert(false && "Unsupported type for '%' operator");
452 }
453 return nullptr;
456DEFINE_OPERATOR_RHS(Integer, long, %, i, long,)
458auto any::operator-() const -> any {
459 auto& lhs = any::extract_value(*this);
460 switch (lhs.type) {
461 case Type::Integer: return (- lhs.i);
462 case Type::Double: return (- lhs.d);
463 default: assert(false && "Unsupported type for unary '-' operator");
464 }
465 return nullptr;
468DEFINE_OPERATOR_LHS(Integer, long, ==, i, bool,)
469DEFINE_OPERATOR_LHS(Integer, long, !=, i, bool,)
470DEFINE_OPERATOR_LHS(Integer, long, <, i, bool,)
471DEFINE_OPERATOR_LHS(Integer, long, <=, i, bool,)
472DEFINE_OPERATOR_LHS(Integer, long, >, i, bool,)
473DEFINE_OPERATOR_LHS(Integer, long, >=, i, bool,)
475DEFINE_OPERATOR_LHS(Double, double, ==, d, bool,)
476DEFINE_OPERATOR_LHS(Double, double, !=, d, bool,)
477DEFINE_OPERATOR_LHS(Double, double, <, d, bool,)
478DEFINE_OPERATOR_LHS(Double, double, <=, d, bool,)
479DEFINE_OPERATOR_LHS(Double, double, >, d, bool,)
480DEFINE_OPERATOR_LHS(Double, double, >=, d, bool,)
482DEFINE_OPERATOR_LHS(Character, char, ==, c, bool,)
483DEFINE_OPERATOR_LHS(Character, char, !=, c, bool,)
484DEFINE_OPERATOR_LHS(Character, char, <, c, bool,)
485DEFINE_OPERATOR_LHS(Character, char, <=, c, bool,)
486DEFINE_OPERATOR_LHS(Character, char, >, c, bool,)
487DEFINE_OPERATOR_LHS(Character, char, >=, c, bool,)
489DEFINE_OPERATOR_LHS(Boolean, bool, ==, b, bool,)
490DEFINE_OPERATOR_LHS(Boolean, bool, !=, b, bool,)
491DEFINE_OPERATOR_LHS(Boolean, bool, <, b, bool,)
492DEFINE_OPERATOR_LHS(Boolean, bool, <=, b, bool,)
493DEFINE_OPERATOR_LHS(Boolean, bool, >, b, bool,)
494DEFINE_OPERATOR_LHS(Boolean, bool, >=, b, bool,)
496DEFINE_OPERATOR_LHS(String, string&, ==, s, bool, *)
497DEFINE_OPERATOR_LHS(String, string&, !=, s, bool, *)
498DEFINE_OPERATOR_LHS(String, string&, <, s, bool, *)
499DEFINE_OPERATOR_LHS(String, string&, <=, s, bool, *)
500DEFINE_OPERATOR_LHS(String, string&, >, s, bool, *)
501DEFINE_OPERATOR_LHS(String, string&, >=, s, bool, *)
503DEFINE_OPERATOR_LHS(String, char* const, ==, s, bool, *)
504DEFINE_OPERATOR_LHS(String, char* const, !=, s, bool, *)
505DEFINE_OPERATOR_LHS(String, char* const, <, s, bool, *)
506DEFINE_OPERATOR_LHS(String, char* const, <=, s, bool, *)
507DEFINE_OPERATOR_LHS(String, char* const, >, s, bool, *)
508DEFINE_OPERATOR_LHS(String, char* const, >=, s, bool, *)
510DEFINE_OPERATOR_LHS(Integer, long, +, i, long,)
511DEFINE_OPERATOR_LHS(Integer, long, -, i, long,)
512DEFINE_OPERATOR_LHS(Integer, long, *, i, long,)
513DEFINE_OPERATOR_LHS(Integer, long, /, i, long,)
514DEFINE_OPERATOR_LHS(Integer, long, %, i, long,)
516DEFINE_OPERATOR_LHS(Double, double, +, d, double,)
517DEFINE_OPERATOR_LHS(Double, double, -, d, double,)
518DEFINE_OPERATOR_LHS(Double, double, *, d, double,)
519DEFINE_OPERATOR_LHS(Double, double, /, d, double,)
521DEFINE_OPERATOR_LHS(Character, char, +, i, char,)
522DEFINE_OPERATOR_LHS(Character, char, -, i, char,)
524DEFINE_OPERATOR_LHS(String, string&, +, s, string, *)
525DEFINE_OPERATOR_LHS(String, char* const, +, s, string, *)
528} // namespace PureScript