git.iko.soy/rowtype-yoga/purescript-native
on 01592a6 help sign in
530 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, map>::value, const T&>::type {
122 RETURN_VALUE(Type::Map, m, *)
123 }
124 template auto any::cast<any::map>() const -> const map&;
126 template <typename T>
127 auto any::cast() const -> typename std::enable_if<std::is_same<T, vector>::value, const T&>::type {
128 RETURN_VALUE(Type::Vector, v, *)
129 }
130 template auto any::cast<any::vector>() const -> const vector&;
133 auto any::operator()(const any arg) const -> any {
134 if (type == Type::Function) {
135 return (*f)(arg);
136 }
137 const any* valuePtr = this;
138 do {
139 assert(valuePtr->type == Type::Thunk);
140 const any& value = (*valuePtr->t)(unthunk);
141 if (value.type == Type::Function) {
142 return (*value.f)(arg);
143 }
144 valuePtr = &value;
145 } while (valuePtr->type != Type::Unknown);
146 return nullptr;
147 }
149 auto any::operator()(const as_thunk) const -> const any& {
150 assert(type == Type::Thunk);
151 return (*t)(unthunk);
152 }
154 auto any::call(const any& a) -> any {
155 assert(a.type == Type::EffFunction || a.type == Type::Function);
156 if (a.type == Type::EffFunction) {
157 return (*a.e)();
158 } else {
159 return (*a.f)(false);
160 }
161 }
163 auto any::operator()() const -> any {
164 if (type == Type::EffFunction || type == Type::Function) {
165 return call(*this);
166 }
167 assert(type == Type::Thunk);
168 const any* valuePtr = this;
169 do {
170 const any& value = (*valuePtr->t)(unthunk);
171 if (value.type != Type::Thunk) {
172 return call(value);
173 }
174 valuePtr = &value;
175 } while (true);
176 }
178 any::operator long() const {
179 RETURN_VALUE(Type::Integer, i,)
180 }
182 any::operator double() const {
183 RETURN_VALUE(Type::Double, d,)
184 }
186 any::operator bool() const {
187 RETURN_VALUE(Type::Boolean, b,)
188 }
190 any::operator const string&() const {
191 RETURN_VALUE(Type::String, s, *)
192 }
194 any::operator const map&() const {
195 RETURN_VALUE(Type::Map, m, *)
196 }
198 any::operator const vector&() const {
199 RETURN_VALUE(Type::Vector, v, *)
200 }
202 auto any::extractPointer() const -> const void* {
203 RETURN_VALUE(Type::Pointer, p.get(),)
204 }
206 auto any::extract_value(const any& a) -> const any& {
207 if (a.type != Type::Thunk) {
208 return a;
209 }
210 const any* valuePtr = &a;
211 do {
212 const any& value = (*valuePtr->t)(unthunk);
213 if (value.type != Type::Thunk) {
214 return value;
215 }
216 valuePtr = &value;
217 } while (true);
218 }
220 auto any::operator[](const map_key_t rhs) const -> const any& {
221 RETURN_VALUE(Type::Map, m->at(rhs),)
222 }
224 auto any::operator[](const vector::size_type rhs) const -> const any& {
225 RETURN_VALUE(Type::Vector, v->at(rhs),)
226 }
228 auto any::operator[](const any& rhs) const -> const any& {
229 RETURN_VALUE(Type::Vector, v->at(rhs.cast<long>()),)
230 }
232#define DEFINE_OPERATOR_LHS(K, T, OP, V, R, P) \
233auto operator OP(const T lhs, const any& rhs_) -> R { \
234 auto& rhs = any::extract_value(rhs_); \
235 assert(rhs.type == any::Type::K); \
236 return lhs OP P(rhs.V); \
239#define DEFINE_OPERATOR_RHS(K, T, OP, V, R, P) \
240auto any::operator OP(const T rhs) const -> R { \
241 auto& lhs = any::extract_value(*this); \
242 assert(lhs.type == Type::K); \
243 return P(lhs.V) OP rhs; \
246auto any::operator==(const any& rhs_) const -> bool {
247 auto& lhs = extract_value(*this);
248 auto& rhs = extract_value(rhs_);
249 assert(lhs.type == rhs.type);
250 switch (lhs.type) {
251 case Type::Integer: return lhs.i == rhs.i;
252 case Type::Double: return lhs.d == rhs.d;
253 case Type::Character: return lhs.c == rhs.c;
254 case Type::Boolean: return lhs.b == rhs.b;
255 case Type::String: return (*lhs.s) == (*rhs.s);
256 case Type::Pointer: return lhs.p == rhs.p;
257 default: assert(false && "Unsupported type for '==' operator");
258 }
259 return false;
262DEFINE_OPERATOR_RHS(Integer, long, ==, i, bool,)
263DEFINE_OPERATOR_RHS(Double, double, ==, d, bool,)
264DEFINE_OPERATOR_RHS(Character, char, ==, c, bool,)
265DEFINE_OPERATOR_RHS(Boolean, bool, ==, b, bool,)
266DEFINE_OPERATOR_RHS(String, string&, ==, s, bool, *)
267DEFINE_OPERATOR_RHS(String, char* const, ==, s, bool, *)
269auto any::operator!=(const any& rhs_) const -> bool {
270 auto& lhs = extract_value(*this);
271 auto& rhs = extract_value(rhs_);
272 assert(lhs.type == rhs.type);
273 switch (lhs.type) {
274 case Type::Integer: return lhs.i != rhs.i;
275 case Type::Double: return lhs.d != rhs.d;
276 case Type::Character: return lhs.c != rhs.c;
277 case Type::Boolean: return lhs.b != rhs.b;
278 case Type::String: return (*lhs.s) != (*rhs.s);
279 case Type::Pointer: return lhs.p != rhs.p;
280 default: assert(false && "Unsupported type for '!=' operator");
281 }
282 return false;
285DEFINE_OPERATOR_RHS(Integer, long, !=, i, bool,)
286DEFINE_OPERATOR_RHS(Double, double, !=, d, bool,)
287DEFINE_OPERATOR_RHS(Character, char, !=, c, bool,)
288DEFINE_OPERATOR_RHS(Boolean, bool, !=, b, bool,)
289DEFINE_OPERATOR_RHS(String, string&, !=, s, bool, *)
290DEFINE_OPERATOR_RHS(String, char* const, !=, s, bool, *)
292auto any::operator<(const any& rhs_) const -> bool {
293 auto& lhs = extract_value(*this);
294 auto& rhs = extract_value(rhs_);
295 assert(lhs.type == rhs.type);
296 switch (lhs.type) {
297 case Type::Integer: return lhs.i < rhs.i;
298 case Type::Double: return lhs.d < rhs.d;
299 case Type::Character: return lhs.c < rhs.c;
300 case Type::Boolean: return lhs.b < rhs.b;
301 case Type::String: return (*lhs.s) < (*rhs.s);
302 default: assert(false && "Unsupported type for '<' operator");
303 }
304 return false;
307DEFINE_OPERATOR_RHS(Integer, long, <, i, bool,)
308DEFINE_OPERATOR_RHS(Double, double, <, d, bool,)
309DEFINE_OPERATOR_RHS(Character, char, <, c, bool,)
310DEFINE_OPERATOR_RHS(Boolean, bool, <, b, bool,)
311DEFINE_OPERATOR_RHS(String, string&, <, s, bool, *)
312DEFINE_OPERATOR_RHS(String, char* const, <, s, bool, *)
314auto any::operator<=(const any& rhs_) const -> bool {
315 auto& lhs = extract_value(*this);
316 auto& rhs = extract_value(rhs_);
317 assert(lhs.type == rhs.type);
318 switch (lhs.type) {
319 case Type::Integer: return lhs.i <= rhs.i;
320 case Type::Double: return lhs.d <= rhs.d;
321 case Type::Character: return lhs.c <= rhs.c;
322 case Type::Boolean: return lhs.b <= rhs.b;
323 case Type::String: return (*lhs.s) <= (*rhs.s);
324 default: assert(false && "Unsupported type for '<' operator");
325 }
326 return false;
329DEFINE_OPERATOR_RHS(Integer, long, <=, i, bool,)
330DEFINE_OPERATOR_RHS(Double, double, <=, d, bool,)
331DEFINE_OPERATOR_RHS(Character, char, <=, c, bool,)
332DEFINE_OPERATOR_RHS(Boolean, bool, <=, b, bool,)
333DEFINE_OPERATOR_RHS(String, string&, <=, s, bool, *)
334DEFINE_OPERATOR_RHS(String, char* const, <=, s, bool, *)
336auto any::operator>(const any& rhs_) const -> bool {
337 auto& lhs = extract_value(*this);
338 auto& rhs = extract_value(rhs_);
339 assert(lhs.type == rhs.type);
340 switch (lhs.type) {
341 case Type::Integer: return lhs.i > rhs.i;
342 case Type::Double: return lhs.d > rhs.d;
343 case Type::Character: return lhs.c > rhs.c;
344 case Type::Boolean: return lhs.b > rhs.b;
345 case Type::String: return (*lhs.s) > (*rhs.s);
346 default: assert(false && "Unsupported type for '>' operator");
347 }
348 return false;
351DEFINE_OPERATOR_RHS(Integer, long, >, i, bool,)
352DEFINE_OPERATOR_RHS(Double, double, >, d, bool,)
353DEFINE_OPERATOR_RHS(Character, char, >, c, bool,)
354DEFINE_OPERATOR_RHS(Boolean, bool, >, b, bool,)
355DEFINE_OPERATOR_RHS(String, string&, >, s, bool, *)
356DEFINE_OPERATOR_RHS(String, char* const, >, s, bool, *)
358auto any::operator>=(const any& rhs_) const -> bool {
359 auto& lhs = extract_value(*this);
360 auto& rhs = extract_value(rhs_);
361 assert(lhs.type == rhs.type);
362 switch (lhs.type) {
363 case Type::Integer: return lhs.i >= rhs.i;
364 case Type::Double: return lhs.d >= rhs.d;
365 case Type::Character: return lhs.c >= rhs.c;
366 case Type::Boolean: return lhs.b >= rhs.b;
367 case Type::String: return (*lhs.s) >= (*rhs.s);
368 default: assert(false && "Unsupported type for '>' operator");
369 }
370 return false;
373DEFINE_OPERATOR_RHS(Integer, long, >=, i, bool,)
374DEFINE_OPERATOR_RHS(Double, double, >=, d, bool,)
375DEFINE_OPERATOR_RHS(Character, char, >=, c, bool,)
376DEFINE_OPERATOR_RHS(Boolean, bool, >=, b, bool,)
377DEFINE_OPERATOR_RHS(String, string&, >=, s, bool, *)
378DEFINE_OPERATOR_RHS(String, char* const, >=, s, bool, *)
380auto any::operator+(const any& rhs_) const -> any {
381 auto& lhs = extract_value(*this);
382 auto& rhs = extract_value(rhs_);
383 assert(lhs.type == rhs.type);
384 switch (lhs.type) {
385 case Type::Integer: return lhs.i + rhs.i;
386 case Type::Double: return lhs.d + rhs.d;
387 case Type::Character: return any(char(lhs.c + rhs.c));
388 case Type::String: return (*lhs.s) + (*rhs.s);
389 default: assert(false && "Unsupported type for '+' operator");
390 }
391 return nullptr;
394DEFINE_OPERATOR_RHS(Integer, long, +, i, long,)
395DEFINE_OPERATOR_RHS(Double, double, +, d, double,)
396DEFINE_OPERATOR_RHS(Character, char, +, c, char,)
397DEFINE_OPERATOR_RHS(String, string&, +, s, string, *)
398DEFINE_OPERATOR_RHS(String, char* const, +, s, string, *)
400auto any::operator-(const any& rhs_) const -> any {
401 auto& lhs = extract_value(*this);
402 auto& rhs = extract_value(rhs_);
403 assert(lhs.type == rhs.type);
404 switch (lhs.type) {
405 case Type::Integer: return lhs.i - rhs.i;
406 case Type::Double: return lhs.d - rhs.d;
407 case Type::Character: return any(char(lhs.c - rhs.c));
408 default: assert(false && "Unsupported type for '-' binary operator");
409 }
410 return nullptr;
413DEFINE_OPERATOR_RHS(Integer, long, -, i, long,)
414DEFINE_OPERATOR_RHS(Double, double, -, d, double,)
415DEFINE_OPERATOR_RHS(Character, char, -, c, char,)
417auto any::operator*(const any& rhs_) const -> any {
418 auto& lhs = extract_value(*this);
419 auto& rhs = extract_value(rhs_);
420 assert(lhs.type == rhs.type);
421 switch (lhs.type) {
422 case Type::Integer: return lhs.i * rhs.i;
423 case Type::Double: return lhs.d * rhs.d;
424 default: assert(false && "Unsupported type for '*' operator");
425 }
426 return nullptr;
429DEFINE_OPERATOR_RHS(Integer, long, *, i, long,)
430DEFINE_OPERATOR_RHS(Double, double, *, d, double,)
432auto any::operator/(const any& rhs_) const -> any {
433 auto& lhs = extract_value(*this);
434 auto& rhs = extract_value(rhs_);
435 assert(lhs.type == rhs.type);
436 switch (lhs.type) {
437 case Type::Integer: return lhs.i / rhs.i;
438 case Type::Double: return lhs.d / rhs.d;
439 default: assert(false && "Unsupported type for '/' operator");
440 }
441 return nullptr;
444DEFINE_OPERATOR_RHS(Integer, long, /, i, long,)
445DEFINE_OPERATOR_RHS(Double, double, /, d, double,)
447auto any::operator%(const any& rhs_) const -> any {
448 auto& lhs = extract_value(*this);
449 auto& rhs = extract_value(rhs_);
450 assert(lhs.type == rhs.type);
451 switch (lhs.type) {
452 case Type::Integer: return lhs.i % rhs.i;
453 default: assert(false && "Unsupported type for '%' operator");
454 }
455 return nullptr;
458DEFINE_OPERATOR_RHS(Integer, long, %, i, long,)
460auto any::operator-() const -> any {
461 auto& lhs = any::extract_value(*this);
462 switch (lhs.type) {
463 case Type::Integer: return (- lhs.i);
464 case Type::Double: return (- lhs.d);
465 default: assert(false && "Unsupported type for unary '-' operator");
466 }
467 return nullptr;
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,)
474DEFINE_OPERATOR_LHS(Integer, long, >, i, bool,)
475DEFINE_OPERATOR_LHS(Integer, long, >=, i, 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,)
481DEFINE_OPERATOR_LHS(Double, double, >, d, bool,)
482DEFINE_OPERATOR_LHS(Double, double, >=, d, 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,)
488DEFINE_OPERATOR_LHS(Character, char, >, c, bool,)
489DEFINE_OPERATOR_LHS(Character, char, >=, c, 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,)
495DEFINE_OPERATOR_LHS(Boolean, bool, >, b, bool,)
496DEFINE_OPERATOR_LHS(Boolean, bool, >=, b, 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, *)
502DEFINE_OPERATOR_LHS(String, string&, >, s, bool, *)
503DEFINE_OPERATOR_LHS(String, string&, >=, 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, *)
509DEFINE_OPERATOR_LHS(String, char* const, >, s, bool, *)
510DEFINE_OPERATOR_LHS(String, char* const, >=, s, bool, *)
512DEFINE_OPERATOR_LHS(Integer, long, +, i, long,)
513DEFINE_OPERATOR_LHS(Integer, long, -, i, long,)
514DEFINE_OPERATOR_LHS(Integer, long, *, i, long,)
515DEFINE_OPERATOR_LHS(Integer, long, /, i, long,)
516DEFINE_OPERATOR_LHS(Integer, long, %, i, long,)
518DEFINE_OPERATOR_LHS(Double, double, +, d, double,)
519DEFINE_OPERATOR_LHS(Double, double, -, d, double,)
520DEFINE_OPERATOR_LHS(Double, double, *, d, double,)
521DEFINE_OPERATOR_LHS(Double, double, /, d, double,)
523DEFINE_OPERATOR_LHS(Character, char, +, i, char,)
524DEFINE_OPERATOR_LHS(Character, char, -, i, char,)
526DEFINE_OPERATOR_LHS(String, string&, +, s, string, *)
527DEFINE_OPERATOR_LHS(String, char* const, +, s, string, *)
530} // namespace PureScript