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"
19#define copy_data(src) \
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; \
34 default: assert(false && "Unsupported type in copy"); \
37#define move_data(src) \
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; \
52 default: assert(false && "Unsupported type in move"); \
55any::any(const any& other) {
59any::any(any&& other) {
63auto any::operator=(const any& rhs) -> any& {
68// Takes ownership -- might need to reconsider this
69auto any::operator=(any& rhs) -> any& {
74auto any::operator=(any&& rhs) -> any& {
80 // std::cout << "destroy" << std::endl;
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");
98 #define RETURN_VALUE(TYPE, VAL, FN) \
102 const any* valuePtr = this; \
104 assert(valuePtr->type == Type::Thunk); \
105 const any& value = (*valuePtr->t)(unthunk); \
106 if (value.type == TYPE) { \
107 return FN(value.VAL); \
110 } while (valuePtr->type != Type::Unknown); \
113 template <typename T>
114 auto any::cast() const -> typename std::enable_if<std::is_same<T, long>::value, T>::type {
115 RETURN_VALUE(Type::Integer, i,)
117 template auto any::cast<long>() const -> long;
119 template <typename T>
120 auto any::cast() const -> typename std::enable_if<std::is_same<T, double>::value, T>::type {
121 RETURN_VALUE(Type::Double, d,)
123 template auto any::cast<double>() const -> double;
125 template <typename T>
126 auto any::cast() const -> typename std::enable_if<std::is_same<T, char>::value, T>::type {
127 RETURN_VALUE(Type::Character, c,)
129 template auto any::cast<char>() const -> char;
131 template <typename T>
132 auto any::cast() const -> typename std::enable_if<std::is_same<T, bool>::value, T>::type {
133 RETURN_VALUE(Type::Boolean, b,)
135 template auto any::cast<bool>() const -> bool;
137 template <typename T>
138 auto any::cast() const -> typename std::enable_if<std::is_same<T, string>::value, const T&>::type {
139 RETURN_VALUE(Type::String, s, *)
141 template auto any::cast<string>() const -> const string&;
143 template <typename T>
144 auto any::cast() const -> typename std::enable_if<std::is_same<T, const char*>::value, const T>::type {
145 RETURN_VALUE(Type::String, s->c_str(),)
147 template auto any::cast<const char*>() const -> const char* const;
149 template <typename T>
150 auto any::cast() const -> typename std::enable_if<std::is_same<T, map>::value, const T&>::type {
151 RETURN_VALUE(Type::Map, m, *)
153 template auto any::cast<any::map>() const -> const map&;
155 template <typename T>
156 auto any::cast() const -> typename std::enable_if<std::is_same<T, vector>::value, const T&>::type {
157 RETURN_VALUE(Type::Vector, v, *)
159 template auto any::cast<any::vector>() const -> const vector&;
162 auto any::operator()(const any& arg) const -> any {
163 if (type == Type::Function) {
166 const any* valuePtr = this;
168 assert(valuePtr->type == Type::Thunk);
169 const any& value = (*valuePtr->t)(unthunk);
170 if (value.type == Type::Function) {
171 return (*value.f)(arg);
174 } while (valuePtr->type != Type::Unknown);
178 auto any::operator()(const as_thunk) const -> const any& {
179 assert(type == Type::Thunk);
180 return (*t)(unthunk);
183 auto any::operator()() const -> any {
184 if (type == Type::EffFunction) {
187 const any* valuePtr = this;
189 assert(valuePtr->type == Type::Thunk);
190 const any& value = (*valuePtr->t)(unthunk);
191 if (value.type == Type::EffFunction) {
195 } while (valuePtr->type != Type::Unknown);
199 any::operator long() const {
200 RETURN_VALUE(Type::Integer, i,)
203 any::operator double() const {
204 RETURN_VALUE(Type::Double, d,)
207 any::operator bool() const {
208 RETURN_VALUE(Type::Boolean, b,)
211 any::operator const string&() const {
212 RETURN_VALUE(Type::String, s, *)
215 any::operator const map&() const {
216 RETURN_VALUE(Type::Map, m, *)
219 any::operator const vector&() const {
220 RETURN_VALUE(Type::Vector, v, *)
223 auto any::extractPointer() const -> const void* {
224 RETURN_VALUE(Type::Pointer, p.get(),)
227 auto any::extract_value(const any& a) -> const any& {
228 if (a.type != Type::Thunk) {
231 const any* valuePtr = &a;
233 const any& value = (*valuePtr->t)(unthunk);
234 if (value.type != Type::Thunk) {
241 auto any::operator[](const map_key_t& rhs) const -> const any& {
242 RETURN_VALUE(Type::Map, m->at(rhs),)
245 auto any::operator[](const vector::size_type rhs) const -> const any& {
246 RETURN_VALUE(Type::Vector, v->at(rhs),)
249 auto any::operator[](const any& rhs) const -> const any& {
250 RETURN_VALUE(Type::Vector, v->at(rhs.cast<long>()),)
253#define DEFINE_OPERATOR_LHS(K, T, OP, V, R, P) \
254auto operator OP(const T lhs, const any& rhs_) -> R { \
255 const any& rhs = any::extract_value(rhs_); \
256 assert(rhs.type == any::Type::K); \
257 return lhs OP P(rhs.V); \
260#define DEFINE_OPERATOR_RHS(K, T, OP, V, R, P) \
261auto any::operator OP(const T rhs) const -> R { \
262 const any& lhs = any::extract_value(*this); \
263 assert(lhs.type == Type::K); \
264 return P(lhs.V) OP rhs; \
267auto any::operator==(const any& rhs_) const -> bool {
268 const any& lhs = extract_value(*this);
269 const any& rhs = extract_value(rhs_);
270 assert(lhs.type == rhs.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");
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 const any& lhs = extract_value(*this);
292 const any& rhs = extract_value(rhs_);
293 assert(lhs.type == rhs.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 case Type::Pointer: return lhs.p != rhs.p;
301 default: assert(false && "Unsupported type for '!=' operator");
306DEFINE_OPERATOR_RHS(Integer, long, !=, i, bool,)
307DEFINE_OPERATOR_RHS(Double, double, !=, d, bool,)
308DEFINE_OPERATOR_RHS(Character, char, !=, c, bool,)
309DEFINE_OPERATOR_RHS(Boolean, bool, !=, b, bool,)
310DEFINE_OPERATOR_RHS(String, string&, !=, s, bool, *)
311DEFINE_OPERATOR_RHS(String, char* const, !=, s, bool, *)
313auto any::operator<(const any& rhs_) const -> bool {
314 const any& lhs = extract_value(*this);
315 const any& rhs = extract_value(rhs_);
316 assert(lhs.type == rhs.type);
318 case Type::Integer: return lhs.i < rhs.i;
319 case Type::Double: return lhs.d < rhs.d;
320 case Type::Character: return lhs.c < rhs.c;
321 case Type::Boolean: return lhs.b < rhs.b;
322 case Type::String: return (*lhs.s) < (*rhs.s);
323 default: assert(false && "Unsupported type for '<' operator");
328DEFINE_OPERATOR_RHS(Integer, long, <, i, bool,)
329DEFINE_OPERATOR_RHS(Double, double, <, d, bool,)
330DEFINE_OPERATOR_RHS(Character, char, <, c, bool,)
331DEFINE_OPERATOR_RHS(Boolean, bool, <, b, bool,)
332DEFINE_OPERATOR_RHS(String, string&, <, s, bool, *)
333DEFINE_OPERATOR_RHS(String, char* const, <, s, bool, *)
335auto any::operator<=(const any& rhs_) const -> bool {
336 const any& lhs = extract_value(*this);
337 const any& rhs = extract_value(rhs_);
338 assert(lhs.type == rhs.type);
340 case Type::Integer: return lhs.i <= rhs.i;
341 case Type::Double: return lhs.d <= rhs.d;
342 case Type::Character: return lhs.c <= rhs.c;
343 case Type::Boolean: return lhs.b <= rhs.b;
344 case Type::String: return (*lhs.s) <= (*rhs.s);
345 default: assert(false && "Unsupported type for '<' operator");
350DEFINE_OPERATOR_RHS(Integer, long, <=, i, bool,)
351DEFINE_OPERATOR_RHS(Double, double, <=, d, bool,)
352DEFINE_OPERATOR_RHS(Character, char, <=, c, bool,)
353DEFINE_OPERATOR_RHS(Boolean, bool, <=, b, bool,)
354DEFINE_OPERATOR_RHS(String, string&, <=, s, bool, *)
355DEFINE_OPERATOR_RHS(String, char* const, <=, s, bool, *)
357auto any::operator>(const any& rhs_) const -> bool {
358 const any& lhs = extract_value(*this);
359 const any& rhs = extract_value(rhs_);
360 assert(lhs.type == rhs.type);
362 case Type::Integer: return lhs.i > rhs.i;
363 case Type::Double: return lhs.d > rhs.d;
364 case Type::Character: return lhs.c > rhs.c;
365 case Type::Boolean: return lhs.b > rhs.b;
366 case Type::String: return (*lhs.s) > (*rhs.s);
367 default: assert(false && "Unsupported type for '>' operator");
372DEFINE_OPERATOR_RHS(Integer, long, >, i, bool,)
373DEFINE_OPERATOR_RHS(Double, double, >, d, bool,)
374DEFINE_OPERATOR_RHS(Character, char, >, c, bool,)
375DEFINE_OPERATOR_RHS(Boolean, bool, >, b, bool,)
376DEFINE_OPERATOR_RHS(String, string&, >, s, bool, *)
377DEFINE_OPERATOR_RHS(String, char* const, >, s, bool, *)
379auto any::operator>=(const any& rhs_) const -> bool {
380 const any& lhs = extract_value(*this);
381 const any& rhs = extract_value(rhs_);
382 assert(lhs.type == rhs.type);
384 case Type::Integer: return lhs.i >= rhs.i;
385 case Type::Double: return lhs.d >= rhs.d;
386 case Type::Character: return lhs.c >= rhs.c;
387 case Type::Boolean: return lhs.b >= rhs.b;
388 case Type::String: return (*lhs.s) >= (*rhs.s);
389 default: assert(false && "Unsupported type for '>' operator");
394DEFINE_OPERATOR_RHS(Integer, long, >=, i, bool,)
395DEFINE_OPERATOR_RHS(Double, double, >=, d, bool,)
396DEFINE_OPERATOR_RHS(Character, char, >=, c, bool,)
397DEFINE_OPERATOR_RHS(Boolean, bool, >=, b, bool,)
398DEFINE_OPERATOR_RHS(String, string&, >=, s, bool, *)
399DEFINE_OPERATOR_RHS(String, char* const, >=, s, bool, *)
401auto any::operator+(const any& rhs_) const -> any {
402 const any& lhs = extract_value(*this);
403 const any& rhs = extract_value(rhs_);
404 assert(lhs.type == rhs.type);
406 case Type::Integer: return lhs.i + rhs.i;
407 case Type::Double: return lhs.d + rhs.d;
408 case Type::Character: return any(char(lhs.c + rhs.c));
409 case Type::String: return (*lhs.s) + (*rhs.s);
410 default: assert(false && "Unsupported type for '+' operator");
415DEFINE_OPERATOR_RHS(Integer, long, +, i, long,)
416DEFINE_OPERATOR_RHS(Double, double, +, d, double,)
417DEFINE_OPERATOR_RHS(Character, char, +, c, char,)
418DEFINE_OPERATOR_RHS(String, string&, +, s, string, *)
419DEFINE_OPERATOR_RHS(String, char* const, +, s, string, *)
421auto any::operator-(const any& rhs_) const -> any {
422 const any& lhs = extract_value(*this);
423 const any& rhs = extract_value(rhs_);
424 assert(lhs.type == rhs.type);
426 case Type::Integer: return lhs.i - rhs.i;
427 case Type::Double: return lhs.d - rhs.d;
428 case Type::Character: return any(char(lhs.c - rhs.c));
429 default: assert(false && "Unsupported type for '-' binary operator");
434DEFINE_OPERATOR_RHS(Integer, long, -, i, long,)
435DEFINE_OPERATOR_RHS(Double, double, -, d, double,)
436DEFINE_OPERATOR_RHS(Character, char, -, c, char,)
438auto any::operator*(const any& rhs_) const -> any {
439 const any& lhs = extract_value(*this);
440 const any& rhs = extract_value(rhs_);
441 assert(lhs.type == rhs.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");
450DEFINE_OPERATOR_RHS(Integer, long, *, i, long,)
451DEFINE_OPERATOR_RHS(Double, double, *, d, double,)
453auto any::operator/(const any& rhs_) const -> any {
454 const any& lhs = extract_value(*this);
455 const any& rhs = extract_value(rhs_);
456 assert(lhs.type == rhs.type);
458 case Type::Integer: return lhs.i / rhs.i;
459 case Type::Double: return lhs.d / rhs.d;
460 default: assert(false && "Unsupported type for '/' operator");
465DEFINE_OPERATOR_RHS(Integer, long, /, i, long,)
466DEFINE_OPERATOR_RHS(Double, double, /, d, double,)
468auto any::operator%(const any& rhs_) const -> any {
469 const any& lhs = extract_value(*this);
470 const any& rhs = extract_value(rhs_);
471 assert(lhs.type == rhs.type);
473 case Type::Integer: return lhs.i % rhs.i;
474 default: assert(false && "Unsupported type for '%' operator");
479DEFINE_OPERATOR_RHS(Integer, long, %, i, long,)
481auto any::operator-() const -> any {
482 const any& lhs = any::extract_value(*this);
484 case Type::Integer: return (- lhs.i);
485 case Type::Double: return (- lhs.d);
486 default: assert(false && "Unsupported type for unary '-' operator");
491DEFINE_OPERATOR_LHS(Integer, long, ==, i, bool,)
492DEFINE_OPERATOR_LHS(Integer, long, !=, i, bool,)
493DEFINE_OPERATOR_LHS(Integer, long, <, i, bool,)
494DEFINE_OPERATOR_LHS(Integer, long, <=, i, bool,)
495DEFINE_OPERATOR_LHS(Integer, long, >, i, bool,)
496DEFINE_OPERATOR_LHS(Integer, long, >=, i, bool,)
498DEFINE_OPERATOR_LHS(Double, double, ==, d, bool,)
499DEFINE_OPERATOR_LHS(Double, double, !=, d, bool,)
500DEFINE_OPERATOR_LHS(Double, double, <, d, bool,)
501DEFINE_OPERATOR_LHS(Double, double, <=, d, bool,)
502DEFINE_OPERATOR_LHS(Double, double, >, d, bool,)
503DEFINE_OPERATOR_LHS(Double, double, >=, d, bool,)
505DEFINE_OPERATOR_LHS(Character, char, ==, c, bool,)
506DEFINE_OPERATOR_LHS(Character, char, !=, c, bool,)
507DEFINE_OPERATOR_LHS(Character, char, <, c, bool,)
508DEFINE_OPERATOR_LHS(Character, char, <=, c, bool,)
509DEFINE_OPERATOR_LHS(Character, char, >, c, bool,)
510DEFINE_OPERATOR_LHS(Character, char, >=, c, bool,)
512DEFINE_OPERATOR_LHS(Boolean, bool, ==, b, bool,)
513DEFINE_OPERATOR_LHS(Boolean, bool, !=, b, bool,)
514DEFINE_OPERATOR_LHS(Boolean, bool, <, b, bool,)
515DEFINE_OPERATOR_LHS(Boolean, bool, <=, b, bool,)
516DEFINE_OPERATOR_LHS(Boolean, bool, >, b, bool,)
517DEFINE_OPERATOR_LHS(Boolean, bool, >=, b, bool,)
519DEFINE_OPERATOR_LHS(String, string&, ==, s, bool, *)
520DEFINE_OPERATOR_LHS(String, string&, !=, s, bool, *)
521DEFINE_OPERATOR_LHS(String, string&, <, s, bool, *)
522DEFINE_OPERATOR_LHS(String, string&, <=, s, bool, *)
523DEFINE_OPERATOR_LHS(String, string&, >, s, bool, *)
524DEFINE_OPERATOR_LHS(String, string&, >=, s, bool, *)
526DEFINE_OPERATOR_LHS(String, char* const, ==, s, bool, *)
527DEFINE_OPERATOR_LHS(String, char* const, !=, s, bool, *)
528DEFINE_OPERATOR_LHS(String, char* const, <, s, bool, *)
529DEFINE_OPERATOR_LHS(String, char* const, <=, s, bool, *)
530DEFINE_OPERATOR_LHS(String, char* const, >, s, bool, *)
531DEFINE_OPERATOR_LHS(String, char* const, >=, s, bool, *)
533DEFINE_OPERATOR_LHS(Integer, long, +, i, long,)
534DEFINE_OPERATOR_LHS(Integer, long, -, i, long,)
535DEFINE_OPERATOR_LHS(Integer, long, *, i, long,)
536DEFINE_OPERATOR_LHS(Integer, long, /, i, long,)
537DEFINE_OPERATOR_LHS(Integer, long, %, i, long,)
539DEFINE_OPERATOR_LHS(Double, double, +, d, double,)
540DEFINE_OPERATOR_LHS(Double, double, -, d, double,)
541DEFINE_OPERATOR_LHS(Double, double, *, d, double,)
542DEFINE_OPERATOR_LHS(Double, double, /, d, double,)
544DEFINE_OPERATOR_LHS(Character, char, +, i, char,)
545DEFINE_OPERATOR_LHS(Character, char, -, i, char,)
547DEFINE_OPERATOR_LHS(String, string&, +, s, string, *)
548DEFINE_OPERATOR_LHS(String, char* const, +, s, string, *)
551} // namespace PureScript
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list