@@ -0,0 +1,530 @@
1+///////////////////////////////////////////////////////////////////////////////
3+// Module : purescript.cc
4+// Copyright : (c) Andy Arvanitis 2015
7+// Maintainer : Andy Arvanitis <andy.arvanitis@gmail.com>
8+// Stability : experimental
11+// Basic types and functions to support purescript-to-C++1x rendering
13+///////////////////////////////////////////////////////////////////////////////
15+#include "PureScript.hh"
17+namespace PureScript {
19+any::any(const any& val) : type(val.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");
37+void any::swap(any&& val) {
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");
57+ // std::cout << "destroy" << std::endl;
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");
75+ #define RETURN_VALUE(TYPE, VAL, FN) \
76+ if (type == TYPE) { \
79+ const any* valuePtr = this; \
81+ assert(valuePtr->type == Type::Thunk); \
82+ const any& value = (*valuePtr->t)(unthunk); \
83+ if (value.type == TYPE) { \
84+ return FN(value.VAL); \
87+ } while (valuePtr->type != Type::Unknown); \
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,)
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,)
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,)
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,)
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, *)
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, *)
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, *)
130+ template auto any::cast<any::vector>() const -> const vector&;
133+ auto any::operator()(const any arg) const -> any {
134+ if (type == Type::Function) {
137+ const any* valuePtr = this;
139+ assert(valuePtr->type == Type::Thunk);
140+ const any& value = (*valuePtr->t)(unthunk);
141+ if (value.type == Type::Function) {
142+ return (*value.f)(arg);
145+ } while (valuePtr->type != Type::Unknown);
149+ auto any::operator()(const as_thunk) const -> const any& {
150+ assert(type == Type::Thunk);
151+ return (*t)(unthunk);
154+ auto any::call(const any& a) -> any {
155+ assert(a.type == Type::EffFunction || a.type == Type::Function);
156+ if (a.type == Type::EffFunction) {
159+ return (*a.f)(false);
163+ auto any::operator()() const -> any {
164+ if (type == Type::EffFunction || type == Type::Function) {
167+ assert(type == Type::Thunk);
168+ const any* valuePtr = this;
170+ const any& value = (*valuePtr->t)(unthunk);
171+ if (value.type != Type::Thunk) {
178+ any::operator long() const {
179+ RETURN_VALUE(Type::Integer, i,)
182+ any::operator double() const {
183+ RETURN_VALUE(Type::Double, d,)
186+ any::operator bool() const {
187+ RETURN_VALUE(Type::Boolean, b,)
190+ any::operator const string&() const {
191+ RETURN_VALUE(Type::String, s, *)
194+ any::operator const map&() const {
195+ RETURN_VALUE(Type::Map, m, *)
198+ any::operator const vector&() const {
199+ RETURN_VALUE(Type::Vector, v, *)
202+ auto any::extractPointer() const -> const void* {
203+ RETURN_VALUE(Type::Pointer, p.get(),)
206+ auto any::extract_value(const any& a) -> const any& {
207+ if (a.type != Type::Thunk) {
210+ const any* valuePtr = &a;
212+ const any& value = (*valuePtr->t)(unthunk);
213+ if (value.type != Type::Thunk) {
220+ auto any::operator[](const map_key_t rhs) const -> const any& {
221+ RETURN_VALUE(Type::Map, m->at(rhs),)
224+ auto any::operator[](const vector::size_type rhs) const -> const any& {
225+ RETURN_VALUE(Type::Vector, v->at(rhs),)
228+ auto any::operator[](const any& rhs) const -> const any& {
229+ RETURN_VALUE(Type::Vector, v->at(rhs.cast<long>()),)
232+#define DEFINE_OPERATOR_LHS(K, T, OP, V, R, P) \
233+auto 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) \
240+auto 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; \
246+auto 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);
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");
262+DEFINE_OPERATOR_RHS(Integer, long, ==, i, bool,)
263+DEFINE_OPERATOR_RHS(Double, double, ==, d, bool,)
264+DEFINE_OPERATOR_RHS(Character, char, ==, c, bool,)
265+DEFINE_OPERATOR_RHS(Boolean, bool, ==, b, bool,)
266+DEFINE_OPERATOR_RHS(String, string&, ==, s, bool, *)
267+DEFINE_OPERATOR_RHS(String, char* const, ==, s, bool, *)
269+auto 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);
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");
285+DEFINE_OPERATOR_RHS(Integer, long, !=, i, bool,)
286+DEFINE_OPERATOR_RHS(Double, double, !=, d, bool,)
287+DEFINE_OPERATOR_RHS(Character, char, !=, c, bool,)
288+DEFINE_OPERATOR_RHS(Boolean, bool, !=, b, bool,)
289+DEFINE_OPERATOR_RHS(String, string&, !=, s, bool, *)
290+DEFINE_OPERATOR_RHS(String, char* const, !=, s, bool, *)
292+auto 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);
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");
307+DEFINE_OPERATOR_RHS(Integer, long, <, i, bool,)
308+DEFINE_OPERATOR_RHS(Double, double, <, d, bool,)
309+DEFINE_OPERATOR_RHS(Character, char, <, c, bool,)
310+DEFINE_OPERATOR_RHS(Boolean, bool, <, b, bool,)
311+DEFINE_OPERATOR_RHS(String, string&, <, s, bool, *)
312+DEFINE_OPERATOR_RHS(String, char* const, <, s, bool, *)
314+auto 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);
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");
329+DEFINE_OPERATOR_RHS(Integer, long, <=, i, bool,)
330+DEFINE_OPERATOR_RHS(Double, double, <=, d, bool,)
331+DEFINE_OPERATOR_RHS(Character, char, <=, c, bool,)
332+DEFINE_OPERATOR_RHS(Boolean, bool, <=, b, bool,)
333+DEFINE_OPERATOR_RHS(String, string&, <=, s, bool, *)
334+DEFINE_OPERATOR_RHS(String, char* const, <=, s, bool, *)
336+auto 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);
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");
351+DEFINE_OPERATOR_RHS(Integer, long, >, i, bool,)
352+DEFINE_OPERATOR_RHS(Double, double, >, d, bool,)
353+DEFINE_OPERATOR_RHS(Character, char, >, c, bool,)
354+DEFINE_OPERATOR_RHS(Boolean, bool, >, b, bool,)
355+DEFINE_OPERATOR_RHS(String, string&, >, s, bool, *)
356+DEFINE_OPERATOR_RHS(String, char* const, >, s, bool, *)
358+auto 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);
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");
373+DEFINE_OPERATOR_RHS(Integer, long, >=, i, bool,)
374+DEFINE_OPERATOR_RHS(Double, double, >=, d, bool,)
375+DEFINE_OPERATOR_RHS(Character, char, >=, c, bool,)
376+DEFINE_OPERATOR_RHS(Boolean, bool, >=, b, bool,)
377+DEFINE_OPERATOR_RHS(String, string&, >=, s, bool, *)
378+DEFINE_OPERATOR_RHS(String, char* const, >=, s, bool, *)
380+auto 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);
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");
394+DEFINE_OPERATOR_RHS(Integer, long, +, i, long,)
395+DEFINE_OPERATOR_RHS(Double, double, +, d, double,)
396+DEFINE_OPERATOR_RHS(Character, char, +, c, char,)
397+DEFINE_OPERATOR_RHS(String, string&, +, s, string, *)
398+DEFINE_OPERATOR_RHS(String, char* const, +, s, string, *)
400+auto 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);
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");
413+DEFINE_OPERATOR_RHS(Integer, long, -, i, long,)
414+DEFINE_OPERATOR_RHS(Double, double, -, d, double,)
415+DEFINE_OPERATOR_RHS(Character, char, -, c, char,)
417+auto 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);
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");
429+DEFINE_OPERATOR_RHS(Integer, long, *, i, long,)
430+DEFINE_OPERATOR_RHS(Double, double, *, d, double,)
432+auto 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);
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");
444+DEFINE_OPERATOR_RHS(Integer, long, /, i, long,)
445+DEFINE_OPERATOR_RHS(Double, double, /, d, double,)
447+auto 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);
452+ case Type::Integer: return lhs.i % rhs.i;
453+ default: assert(false && "Unsupported type for '%' operator");
458+DEFINE_OPERATOR_RHS(Integer, long, %, i, long,)
460+auto any::operator-() const -> any {
461+ auto& lhs = any::extract_value(*this);
463+ case Type::Integer: return (- lhs.i);
464+ case Type::Double: return (- lhs.d);
465+ default: assert(false && "Unsupported type for unary '-' operator");
470+DEFINE_OPERATOR_LHS(Integer, long, ==, i, bool,)
471+DEFINE_OPERATOR_LHS(Integer, long, !=, i, bool,)
472+DEFINE_OPERATOR_LHS(Integer, long, <, i, bool,)
473+DEFINE_OPERATOR_LHS(Integer, long, <=, i, bool,)
474+DEFINE_OPERATOR_LHS(Integer, long, >, i, bool,)
475+DEFINE_OPERATOR_LHS(Integer, long, >=, i, bool,)
477+DEFINE_OPERATOR_LHS(Double, double, ==, d, bool,)
478+DEFINE_OPERATOR_LHS(Double, double, !=, d, bool,)
479+DEFINE_OPERATOR_LHS(Double, double, <, d, bool,)
480+DEFINE_OPERATOR_LHS(Double, double, <=, d, bool,)
481+DEFINE_OPERATOR_LHS(Double, double, >, d, bool,)
482+DEFINE_OPERATOR_LHS(Double, double, >=, d, bool,)
484+DEFINE_OPERATOR_LHS(Character, char, ==, c, bool,)
485+DEFINE_OPERATOR_LHS(Character, char, !=, c, bool,)
486+DEFINE_OPERATOR_LHS(Character, char, <, c, bool,)
487+DEFINE_OPERATOR_LHS(Character, char, <=, c, bool,)
488+DEFINE_OPERATOR_LHS(Character, char, >, c, bool,)
489+DEFINE_OPERATOR_LHS(Character, char, >=, c, bool,)
491+DEFINE_OPERATOR_LHS(Boolean, bool, ==, b, bool,)
492+DEFINE_OPERATOR_LHS(Boolean, bool, !=, b, bool,)
493+DEFINE_OPERATOR_LHS(Boolean, bool, <, b, bool,)
494+DEFINE_OPERATOR_LHS(Boolean, bool, <=, b, bool,)
495+DEFINE_OPERATOR_LHS(Boolean, bool, >, b, bool,)
496+DEFINE_OPERATOR_LHS(Boolean, bool, >=, b, bool,)
498+DEFINE_OPERATOR_LHS(String, string&, ==, s, bool, *)
499+DEFINE_OPERATOR_LHS(String, string&, !=, s, bool, *)
500+DEFINE_OPERATOR_LHS(String, string&, <, s, bool, *)
501+DEFINE_OPERATOR_LHS(String, string&, <=, s, bool, *)
502+DEFINE_OPERATOR_LHS(String, string&, >, s, bool, *)
503+DEFINE_OPERATOR_LHS(String, string&, >=, s, bool, *)
505+DEFINE_OPERATOR_LHS(String, char* const, ==, s, bool, *)
506+DEFINE_OPERATOR_LHS(String, char* const, !=, s, bool, *)
507+DEFINE_OPERATOR_LHS(String, char* const, <, s, bool, *)
508+DEFINE_OPERATOR_LHS(String, char* const, <=, s, bool, *)
509+DEFINE_OPERATOR_LHS(String, char* const, >, s, bool, *)
510+DEFINE_OPERATOR_LHS(String, char* const, >=, s, bool, *)
512+DEFINE_OPERATOR_LHS(Integer, long, +, i, long,)
513+DEFINE_OPERATOR_LHS(Integer, long, -, i, long,)
514+DEFINE_OPERATOR_LHS(Integer, long, *, i, long,)
515+DEFINE_OPERATOR_LHS(Integer, long, /, i, long,)
516+DEFINE_OPERATOR_LHS(Integer, long, %, i, long,)
518+DEFINE_OPERATOR_LHS(Double, double, +, d, double,)
519+DEFINE_OPERATOR_LHS(Double, double, -, d, double,)
520+DEFINE_OPERATOR_LHS(Double, double, *, d, double,)
521+DEFINE_OPERATOR_LHS(Double, double, /, d, double,)
523+DEFINE_OPERATOR_LHS(Character, char, +, i, char,)
524+DEFINE_OPERATOR_LHS(Character, char, -, i, char,)
526+DEFINE_OPERATOR_LHS(String, string&, +, s, string, *)
527+DEFINE_OPERATOR_LHS(String, char* const, +, s, string, *)
530+} // namespace PureScript