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::StringLiteral: r = src.r; break; \
27 case Type::String: new (&s) shared<std::string>(src.s); break; \
28 case Type::Map: new (&m) shared<map>(src.m); break; \
29 case Type::Vector: new (&v) shared<vector>(src.v); break; \
30 case Type::Function: f = src.f; break; \
31 case Type::Closure: new (&l) shared<closure>(src.l); break; \
32 case Type::EffFunction: new (&e) shared<eff_fn>(src.e); break; \
33 case Type::Thunk: t = src.t; break; \
34 case Type::Pointer: new (&p) shared<void>(src.p); break; \
36 default: assert(false && "Unsupported type in copy"); \
39#define MOVE_DATA(src) \
42 case Type::Integer: i = src.i; break; \
43 case Type::Double: d = src.d; break; \
44 case Type::Character: c = src.c; break; \
45 case Type::Boolean: b = src.b; break; \
46 case Type::StringLiteral: r = src.r; break; \
47 case Type::String: new (&s) shared<std::string>(std::move(src.s)); break; \
48 case Type::Map: new (&m) shared<map>(std::move(src.m)); break; \
49 case Type::Vector: new (&v) shared<vector>(std::move(src.v)); break; \
50 case Type::Function: f = src.f; break; \
51 case Type::Closure: new (&l) shared<closure>(std::move(src.l)); break; \
52 case Type::EffFunction: new (&e) shared<eff_fn>(std::move(src.e)); break; \
53 case Type::Thunk: t = src.t; break; \
54 case Type::Pointer: new (&p) shared<void>(std::move(src.p)); break; \
56 default: assert(false && "Unsupported type in move"); \
59any::any(const any& other) {
63any::any(any&& other) noexcept {
67auto any::operator=(const any& rhs) -> any& {
72// Takes ownership -- might need to reconsider this
73auto any::operator=(any& rhs) noexcept -> any& {
78auto any::operator=(any&& rhs) noexcept -> any& {
84 // std::cout << "destroy" << std::endl;
86 case Type::Integer: ; break;
87 case Type::Double: ; break;
88 case Type::Character: ; break;
89 case Type::Boolean: ; break;
90 case Type::StringLiteral: ; break;
91 case Type::String: s.~shared<std::string>(); break;
92 case Type::Map: m.~shared<map>(); break;
93 case Type::Vector: v.~shared<vector>(); break;
94 case Type::Function: ; break;
95 case Type::Closure: l.~shared<closure>(); break;
96 case Type::EffFunction: e.~shared<eff_fn>(); break;
97 case Type::Thunk: ; break;
98 case Type::Pointer: p.~shared<void>(); break;
100 default: assert(false && "Unsupported type in destructor");
104#define RETURN_VALUE(TYPE, VAL, FN) \
105 if (type == TYPE) { \
108 const any* valuePtr = this; \
110 assert(valuePtr->type == Type::Thunk); \
111 const any& value = (*valuePtr->t)(unthunk); \
112 if (value.type == TYPE) { \
113 return FN(value.VAL); \
116 } while (valuePtr->type != Type::Unknown); \
117 assert(false && "Unknown value type"); \
121auto any::cast() const -> typename std::enable_if<std::is_same<T, long>::value, T>::type {
122 RETURN_VALUE(Type::Integer, i,)
124template auto any::cast<long>() const -> long;
127auto any::cast() const -> typename std::enable_if<std::is_same<T, double>::value, T>::type {
128 RETURN_VALUE(Type::Double, d,)
130template auto any::cast<double>() const -> double;
133auto any::cast() const -> typename std::enable_if<std::is_same<T, char>::value, T>::type {
134 RETURN_VALUE(Type::Character, c,)
136template auto any::cast<char>() const -> char;
139auto any::cast() const -> typename std::enable_if<std::is_same<T, bool>::value, T>::type {
140 RETURN_VALUE(Type::Boolean, b,)
142template auto any::cast<bool>() const -> bool;
145auto any::cast() const -> typename std::enable_if<std::is_same<T, string>::value, T>::type {
146 const any& val = extractValue(*this);
147 if (val.type == Type::StringLiteral) {
150 assert(val.type == Type::String);
151 return val.s->c_str();
153template auto any::cast<string>() const -> string;
156auto any::cast() const -> typename std::enable_if<std::is_same<T, map>::value, const T&>::type {
157 RETURN_VALUE(Type::Map, m, *)
159template auto any::cast<any::map>() const -> const map&;
162auto any::cast() const -> typename std::enable_if<std::is_same<T, vector>::value, const T&>::type {
163 RETURN_VALUE(Type::Vector, v, *)
165template auto any::cast<any::vector>() const -> const vector&;
167auto any::operator()(const any& arg) const -> any {
168 if (type == Type::Function) {
171 if (type == Type::Closure) {
174 const any* valuePtr = this;
176 assert(valuePtr->type == Type::Thunk);
177 const any& value = (*valuePtr->t)(unthunk);
178 if (value.type == Type::Function) {
179 return (*value.f)(arg);
181 if (value.type == Type::Closure) {
182 return (*value.l)(arg);
185 } while (valuePtr->type != Type::Unknown);
186 assert(false && "Unknown value type");
190auto any::operator()(const as_thunk) const -> const any& {
191 assert(type == Type::Thunk);
192 return (*t)(unthunk);
195auto any::operator()() const -> any {
196 if (type == Type::EffFunction) {
199 const any* valuePtr = this;
201 assert(valuePtr->type == Type::Thunk);
202 const any& value = (*valuePtr->t)(unthunk);
203 if (value.type == Type::EffFunction) {
207 } while (valuePtr->type != Type::Unknown);
208 assert(false && "Unknown value type");
212any::operator long() const {
213 RETURN_VALUE(Type::Integer, i,)
216any::operator double() const {
217 RETURN_VALUE(Type::Double, d,)
220any::operator bool() const {
221 RETURN_VALUE(Type::Boolean, b,)
224any::operator string() const {
225 return cast<string>();
228any::operator std::string() const {
229 return cast<string>();
232any::operator const map&() const {
233 RETURN_VALUE(Type::Map, m, *)
236any::operator const vector&() const {
237 RETURN_VALUE(Type::Vector, v, *)
240auto any::extractPointer() const -> void* {
241 RETURN_VALUE(Type::Pointer, p.get(),)
244auto any::extractValue(const any& a) -> const any& {
245 if (a.type != Type::Thunk) {
248 const any* valuePtr = &a;
250 const any& value = (*valuePtr->t)(unthunk);
251 if (value.type != Type::Thunk) {
255 } while (valuePtr->type != Type::Unknown);
256 assert(false && "Unknown value type");
260auto any::operator[](const map_key_t& rhs) const -> const any& {
261 RETURN_VALUE(Type::Map, m->at(rhs),)
264auto any::operator[](const vector::size_type rhs) const -> const any& {
265 RETURN_VALUE(Type::Vector, v->at(rhs),)
268auto any::operator[](const any& rhs) const -> const any& {
269 RETURN_VALUE(Type::Vector, v->at(rhs.cast<long>()),)
272//-----------------------------------------------------------------------------
273// Operator helper macros
274//-----------------------------------------------------------------------------
276#define DEFINE_OPERATOR(op, ty, rty) \
277auto operator op (const any& lhs, ty rhs) -> rty { \
278 return lhs.cast<typename std::remove_const<std::remove_reference<ty>::type>::type>() op rhs; \
280auto operator op (ty lhs, const any& rhs) -> rty { \
281 return lhs op rhs.cast<typename std::remove_const<std::remove_reference<ty>::type>::type>(); \
284#define DEFINE_CSTR_EQUALS_OPERATOR() \
285 auto operator==(const any& lhs_, const char * rhs) -> bool { \
286 const any& lhs = any::extractValue(lhs_); \
287 assert(lhs.type == any::Type::StringLiteral || lhs.type == any::Type::String); \
288 if (lhs.type == any::Type::StringLiteral) { \
289 return (lhs.r == rhs) || (strcmp(lhs.r, rhs) == 0); \
291 return strcmp(lhs.s->c_str(), rhs) == 0; \
293 auto operator==(const char * lhs, const any& rhs_) -> bool { \
294 const any& rhs = any::extractValue(rhs_); \
295 assert(rhs.type == any::Type::StringLiteral || rhs.type == any::Type::String); \
296 if (rhs.type == any::Type::StringLiteral) { \
297 return (lhs == rhs.r) || (strcmp(lhs, rhs) == 0); \
299 return strcmp(lhs, rhs.s->c_str()) == 0; \
302#define DEFINE_CSTR_COMPARISON_OPERATOR(op) \
303 auto operator op (const any& lhs, const char * rhs) -> bool { \
304 return strcmp(lhs.cast<string>(), rhs) op 0; \
306 auto operator op (const char * lhs, const any& rhs) -> bool { \
307 return strcmp(lhs, rhs.cast<string>()) op 0; \
310#define DEFINE_COMPARISON_OPERATOR(op) \
311 auto operator op (const any& lhs_, const any& rhs_) -> bool { \
312 const any& lhs = any::extractValue(lhs_); \
313 const any& rhs = any::extractValue(rhs_); \
314 switch (lhs.type) { \
315 case any::Type::Integer: assert(lhs.type == any::Type::Integer); return lhs.i op rhs.i; \
316 case any::Type::Double: assert(lhs.type == any::Type::Double); return lhs.d op rhs.d; \
317 case any::Type::Character: assert(lhs.type == any::Type::Character); return lhs.c op rhs.c; \
318 case any::Type::Boolean: assert(lhs.type == any::Type::Boolean); return lhs.b op rhs.b; \
319 case any::Type::StringLiteral: \
320 assert(lhs.type == any::Type::StringLiteral || lhs.type == any::Type::String); \
321 assert(rhs.type == any::Type::StringLiteral || rhs.type == any::Type::String); \
322 return strcmp(lhs.r, rhs.type == any::Type::StringLiteral ? rhs.r : rhs.s->c_str()) op 0; \
323 case any::Type::String: \
324 assert(lhs.type == any::Type::StringLiteral || lhs.type == any::Type::String); \
325 assert(rhs.type == any::Type::StringLiteral || rhs.type == any::Type::String); \
326 return strcmp(lhs.s->c_str(), rhs.type == any::Type::StringLiteral ? rhs.r : rhs.s->c_str()) op 0; \
327 case any::Type::Pointer: return lhs.p op rhs.p; \
328 default: assert(false && "Unsupported type for operator " #op); \
332 DEFINE_OPERATOR(op, long, bool) \
333 DEFINE_OPERATOR(op, double, bool) \
334 DEFINE_OPERATOR(op, char, bool) \
335 DEFINE_OPERATOR(op, bool, bool) \
337//-----------------------------------------------------------------------------
338// Operator definitions
339//-----------------------------------------------------------------------------
341DEFINE_COMPARISON_OPERATOR(==)
342DEFINE_COMPARISON_OPERATOR(!=)
343DEFINE_COMPARISON_OPERATOR(<)
344DEFINE_COMPARISON_OPERATOR(<=)
345DEFINE_COMPARISON_OPERATOR(>)
346DEFINE_COMPARISON_OPERATOR(>=)
348DEFINE_CSTR_EQUALS_OPERATOR()
349DEFINE_CSTR_COMPARISON_OPERATOR(!=)
350DEFINE_CSTR_COMPARISON_OPERATOR(<)
351DEFINE_CSTR_COMPARISON_OPERATOR(<=)
352DEFINE_CSTR_COMPARISON_OPERATOR(>)
353DEFINE_CSTR_COMPARISON_OPERATOR(>=)
355auto operator+(const any& lhs_, const any& rhs_) -> any {
356 const any& lhs = any::extractValue(lhs_);
357 const any& rhs = any::extractValue(rhs_);
359 case any::Type::Integer: assert(lhs.type == any::Type::Integer); return lhs.i + rhs.i;
360 case any::Type::Double: assert(lhs.type == any::Type::Double); return lhs.d + rhs.d;
361 case any::Type::Character: assert(lhs.type == any::Type::Character); return any(char(lhs.c + rhs.c));
362 case any::Type::StringLiteral:
363 assert(lhs.type == any::Type::StringLiteral || lhs.type == any::Type::String);
364 assert(rhs.type == any::Type::StringLiteral || rhs.type == any::Type::String);
365 return rhs.type == any::Type::StringLiteral ? std::string(lhs.r) + rhs.r : lhs.r + *rhs.s;
366 case any::Type::String:
367 assert(lhs.type == any::Type::StringLiteral || lhs.type == any::Type::String);
368 assert(rhs.type == any::Type::StringLiteral || rhs.type == any::Type::String);
369 return rhs.type == any::Type::StringLiteral ? *lhs.s + rhs.r : *lhs.s + *rhs.s;
370 default: assert(false && "Unsupported type for '+' operator");
375DEFINE_OPERATOR(+, long, long)
376DEFINE_OPERATOR(+, double, double)
377DEFINE_OPERATOR(+, char, char)
379auto operator+(const any& lhs_, const char * rhs) -> std::string {
380 const any& lhs = any::extractValue(lhs_);
381 assert(lhs.type == any::Type::StringLiteral || lhs.type == any::Type::String);
382 return lhs.type == any::Type::StringLiteral ? std::string(lhs.r) + rhs : *lhs.s + rhs;
385auto operator+(const char * lhs, const any& rhs_) -> std::string {
386 const any& rhs = any::extractValue(rhs_);
387 assert(rhs.type == any::Type::StringLiteral || rhs.type == any::Type::String);
388 return rhs.type == any::Type::StringLiteral ? lhs + std::string(rhs.r) : lhs + *rhs.s;
391auto operator-(const any& lhs_, const any& rhs_) -> any {
392 const any& lhs = any::extractValue(lhs_);
393 const any& rhs = any::extractValue(rhs_);
394 assert(lhs.type == rhs.type);
396 case any::Type::Integer: return lhs.i - rhs.i;
397 case any::Type::Double: return lhs.d - rhs.d;
398 case any::Type::Character: return any(char(lhs.c - rhs.c));
399 default: assert(false && "Unsupported type for '-' operator");
404DEFINE_OPERATOR(-, long, long)
405DEFINE_OPERATOR(-, double, double)
406DEFINE_OPERATOR(-, char, char)
408auto operator*(const any& lhs_, const any& rhs_) -> any {
409 const any& lhs = any::extractValue(lhs_);
410 const any& rhs = any::extractValue(rhs_);
411 assert(lhs.type == rhs.type);
413 case any::Type::Integer: return lhs.i * rhs.i;
414 case any::Type::Double: return lhs.d * rhs.d;
415 case any::Type::Character: return any(char(lhs.c * rhs.c));
416 default: assert(false && "Unsupported type for '*' operator");
421DEFINE_OPERATOR(*, long, long)
422DEFINE_OPERATOR(*, double, double)
423DEFINE_OPERATOR(*, char, char)
425auto operator/(const any& lhs_, const any& rhs_) -> any {
426 const any& lhs = any::extractValue(lhs_);
427 const any& rhs = any::extractValue(rhs_);
428 assert(lhs.type == rhs.type);
430 case any::Type::Integer: return lhs.i / rhs.i;
431 case any::Type::Double: return lhs.d / rhs.d;
432 case any::Type::Character: return any(char(lhs.c / rhs.c));
433 default: assert(false && "Unsupported type for '/' operator");
438DEFINE_OPERATOR(/, long, long)
439DEFINE_OPERATOR(/, double, double)
440DEFINE_OPERATOR(/, char, char)
442auto operator%(const any& lhs_, const any& rhs_) -> any {
443 const any& lhs = any::extractValue(lhs_);
444 const any& rhs = any::extractValue(rhs_);
445 assert(lhs.type == rhs.type);
447 case any::Type::Integer: return lhs.i % rhs.i;
448 case any::Type::Character: return any(char(lhs.c % rhs.c));
449 default: assert(false && "Unsupported type for '%' operator");
454DEFINE_OPERATOR(%, long, long)
455DEFINE_OPERATOR(%, char, char)
458auto operator-(const any& rhs_) -> any {
459 const any& rhs = any::extractValue(rhs_);
461 case any::Type::Integer: return (- rhs.i);
462 case any::Type::Double: return (- rhs.d);
463 default: assert(false && "Unsupported type for unary '-' operator");
468} // 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