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///////////////////////////////////////////////////////////////////////////////
16#include "PureScript.hh"
20#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) \
41 case Type::Integer: i = src.i; break; \
42 case Type::Double: d = src.d; break; \
43 case Type::Character: c = src.c; break; \
44 case Type::Boolean: b = src.b; break; \
45 case Type::StringLiteral: r = src.r; break; \
46 case Type::String: new (&s) shared<std::string>(std::move(src.s)); break; \
47 case Type::Map: new (&m) shared<map>(std::move(src.m)); break; \
48 case Type::Vector: new (&v) shared<vector>(std::move(src.v)); break; \
49 case Type::Function: f = src.f; break; \
50 case Type::Closure: new (&l) shared<closure>(std::move(src.l)); break; \
51 case Type::EffFunction: new (&e) shared<eff_fn>(std::move(src.e)); break; \
52 case Type::Thunk: t = src.t; break; \
53 case Type::Pointer: new (&p) shared<void>(std::move(src.p)); break; \
55 default: assert(false && "Unsupported type in move"); \
58any::any(const any& other) : type(other.type) {
62any::any(any&& other) noexcept : type(other.type) {
66auto any::operator=(const any& rhs) -> any& {
72// Takes ownership -- might need to reconsider this
73auto any::operator=(any& rhs) noexcept -> any& {
79auto any::operator=(any&& rhs) noexcept -> any& {
87 case Type::Integer: ; break;
88 case Type::Double: ; break;
89 case Type::Character: ; break;
90 case Type::Boolean: ; break;
91 case Type::StringLiteral: ; break;
92 case Type::String: s.~shared<std::string>(); break;
93 case Type::Map: m.~shared<map>(); break;
94 case Type::Vector: v.~shared<vector>(); break;
95 case Type::Function: ; break;
96 case Type::Closure: l.~shared<closure>(); break;
97 case Type::EffFunction: e.~shared<eff_fn>(); break;
98 case Type::Thunk: ; break;
99 case Type::Pointer: p.~shared<void>(); break;
101 default: assert(false && "Unsupported type in destructor");
105#define RETURN_VALUE(TYPE, ACCESSOR, INDIRECTION) \
106 const any& variant = unthunkVariant(*this); \
107 assert(variant.type == TYPE); \
108 return INDIRECTION(variant.ACCESSOR); \
111auto any::cast() const -> typename std::enable_if<std::is_same<T, long>::value, T>::type {
112 RETURN_VALUE(Type::Integer, i,)
114template auto any::cast<long>() const -> long;
117auto any::cast() const -> typename std::enable_if<std::is_same<T, double>::value, T>::type {
118 RETURN_VALUE(Type::Double, d,)
120template auto any::cast<double>() const -> double;
123auto any::cast() const -> typename std::enable_if<std::is_same<T, char>::value, T>::type {
124 RETURN_VALUE(Type::Character, c,)
126template auto any::cast<char>() const -> char;
129auto any::cast() const -> typename std::enable_if<std::is_same<T, bool>::value, T>::type {
130 RETURN_VALUE(Type::Boolean, b,)
132template auto any::cast<bool>() const -> bool;
135auto any::cast() const -> typename std::enable_if<std::is_same<T, string>::value, T>::type {
136 const any& variant = unthunkVariant(*this);
137 if (variant.type == Type::StringLiteral) {
140 assert(variant.type == Type::String);
141 return variant.s->c_str();
143template auto any::cast<string>() const -> string;
146auto any::cast() const -> typename std::enable_if<std::is_same<T, map>::value, const T&>::type {
147 RETURN_VALUE(Type::Map, m, *)
149template auto any::cast<any::map>() const -> const map&;
152auto any::cast() const -> typename std::enable_if<std::is_same<T, vector>::value, const T&>::type {
153 RETURN_VALUE(Type::Vector, v, *)
155template auto any::cast<any::vector>() const -> const vector&;
157auto any::operator()(const any& arg) const -> any {
158 const any& variant = unthunkVariant(*this);
159 if (variant.type == Type::Closure) {
160 return (*variant.l)(arg);
162 assert(variant.type == Type::Function);
163 return (*variant.f)(arg);
166auto any::operator()(const as_thunk) const -> const any& {
167 assert(type == Type::Thunk);
168 return (*t)(unthunk);
171auto any::operator()() const -> any {
172 const any& variant = unthunkVariant(*this);
173 assert(variant.type == Type::EffFunction);
174 return (*variant.e)();
177any::operator long() const {
181any::operator double() const {
182 return cast<double>();
185any::operator bool() const {
189any::operator string() const {
190 return cast<string>();
193any::operator const map&() const {
197any::operator const vector&() const {
198 return cast<vector>();
201auto any::extractPointer() const -> void* {
202 RETURN_VALUE(Type::Pointer, p.get(),)
205auto any::unthunkVariant(const any& a) -> const any& {
206 const any * variant = &a;
207 while (variant->type == Type::Thunk) {
208 variant = &((*variant->t)(unthunk));
213auto any::operator[](const char rhs[]) const -> const any& {
214 const any& variant = unthunkVariant(*this);
215 assert(variant.type == Type::Map);
216 const any::map::const_iterator begin = variant.m->begin();
217 const any::map::const_iterator end = variant.m->end();
218 for (any::map::const_iterator it = begin; it != end; ++it) {
219 if (it->first == rhs) {
223 for (any::map::const_iterator it = begin; it != end; ++it) {
224 if (strcmp(it->first, rhs) == 0) {
228 throw runtime_error("map key not found");
231auto any::operator[](const vector::size_type rhs) const -> const any& {
232 const any& variant = unthunkVariant(*this);
233 assert(variant.type == Type::Vector);
234 return (*variant.v)[rhs];
237auto any::operator[](const any& rhs) const -> const any& {
238 const any& variant = unthunkVariant(*this);
239 assert(variant.type == Type::Vector);
240 return (*variant.v)[rhs.cast<long>()];
243auto any::contains(const char key[]) const -> bool {
244 const any& variant = unthunkVariant(*this);
245 assert(variant.type == Type::Map);
246 for (any::map::const_iterator it = variant.m->begin(), end = variant.m->end(); it != end; ++it) {
247 if (it->first == key || strcmp(it->first, key) == 0) {
254//-----------------------------------------------------------------------------
255// Operator helper macros
256//-----------------------------------------------------------------------------
258#define DEFINE_OPERATOR(op, ty, rty) \
259auto operator op (const any& lhs, ty rhs) -> rty { \
260 return lhs.cast<typename std::remove_const<std::remove_reference<ty>::type>::type>() op rhs; \
262auto operator op (ty lhs, const any& rhs) -> rty { \
263 return lhs op rhs.cast<typename std::remove_const<std::remove_reference<ty>::type>::type>(); \
266#define DEFINE_CSTR_EQUALS_OPERATOR() \
267 auto operator==(const any& lhs_, const char * rhs) -> bool { \
268 const any& lhs = any::unthunkVariant(lhs_); \
269 assert(lhs.type == any::Type::StringLiteral || lhs.type == any::Type::String); \
270 if (lhs.type == any::Type::StringLiteral) { \
271 return (lhs.r == rhs) || (strcmp(lhs.r, rhs) == 0); \
273 return strcmp(lhs.s->c_str(), rhs) == 0; \
275 auto operator==(const char * lhs, const any& rhs_) -> bool { \
276 const any& rhs = any::unthunkVariant(rhs_); \
277 assert(rhs.type == any::Type::StringLiteral || rhs.type == any::Type::String); \
278 if (rhs.type == any::Type::StringLiteral) { \
279 return (lhs == rhs.r) || (strcmp(lhs, rhs) == 0); \
281 return strcmp(lhs, rhs.s->c_str()) == 0; \
284#define DEFINE_CSTR_COMPARISON_OPERATOR(op) \
285 auto operator op (const any& lhs, const char * rhs) -> bool { \
286 return strcmp(lhs.cast<string>(), rhs) op 0; \
288 auto operator op (const char * lhs, const any& rhs) -> bool { \
289 return strcmp(lhs, rhs.cast<string>()) op 0; \
292#define DEFINE_COMPARISON_OPERATOR(op) \
293 auto operator op (const any& lhs_, const any& rhs_) -> bool { \
294 const any& lhs = any::unthunkVariant(lhs_); \
295 const any& rhs = any::unthunkVariant(rhs_); \
296 switch (lhs.type) { \
297 case any::Type::Integer: assert(lhs.type == any::Type::Integer); return lhs.i op rhs.i; \
298 case any::Type::Double: assert(lhs.type == any::Type::Double); return lhs.d op rhs.d; \
299 case any::Type::Character: assert(lhs.type == any::Type::Character); return lhs.c op rhs.c; \
300 case any::Type::Boolean: assert(lhs.type == any::Type::Boolean); return lhs.b op rhs.b; \
301 case any::Type::StringLiteral: \
302 assert(lhs.type == any::Type::StringLiteral || lhs.type == any::Type::String); \
303 assert(rhs.type == any::Type::StringLiteral || rhs.type == any::Type::String); \
304 return strcmp(lhs.r, rhs.type == any::Type::StringLiteral ? rhs.r : rhs.s->c_str()) op 0; \
305 case any::Type::String: \
306 assert(lhs.type == any::Type::StringLiteral || lhs.type == any::Type::String); \
307 assert(rhs.type == any::Type::StringLiteral || rhs.type == any::Type::String); \
308 return strcmp(lhs.s->c_str(), rhs.type == any::Type::StringLiteral ? rhs.r : rhs.s->c_str()) op 0; \
309 case any::Type::Pointer: return lhs.p op rhs.p; \
310 default: assert(false && "Unsupported type for operator " #op); \
314 DEFINE_OPERATOR(op, long, bool) \
315 DEFINE_OPERATOR(op, double, bool) \
316 DEFINE_OPERATOR(op, char, bool) \
317 DEFINE_OPERATOR(op, bool, bool) \
319//-----------------------------------------------------------------------------
320// Operator definitions
321//-----------------------------------------------------------------------------
323DEFINE_COMPARISON_OPERATOR(==)
324DEFINE_COMPARISON_OPERATOR(!=)
325DEFINE_COMPARISON_OPERATOR(<)
326DEFINE_COMPARISON_OPERATOR(<=)
327DEFINE_COMPARISON_OPERATOR(>)
328DEFINE_COMPARISON_OPERATOR(>=)
330DEFINE_CSTR_EQUALS_OPERATOR()
331DEFINE_CSTR_COMPARISON_OPERATOR(!=)
332DEFINE_CSTR_COMPARISON_OPERATOR(<)
333DEFINE_CSTR_COMPARISON_OPERATOR(<=)
334DEFINE_CSTR_COMPARISON_OPERATOR(>)
335DEFINE_CSTR_COMPARISON_OPERATOR(>=)
337auto operator+(const any& lhs_, const any& rhs_) -> any {
338 const any& lhs = any::unthunkVariant(lhs_);
339 const any& rhs = any::unthunkVariant(rhs_);
341 case any::Type::Integer: assert(lhs.type == any::Type::Integer); return lhs.i + rhs.i;
342 case any::Type::Double: assert(lhs.type == any::Type::Double); return lhs.d + rhs.d;
343 case any::Type::Character: assert(lhs.type == any::Type::Character); return any(char(lhs.c + rhs.c));
344 case any::Type::StringLiteral:
345 assert(lhs.type == any::Type::StringLiteral || lhs.type == any::Type::String);
346 assert(rhs.type == any::Type::StringLiteral || rhs.type == any::Type::String);
347 return rhs.type == any::Type::StringLiteral ? std::string(lhs.r) + rhs.r : lhs.r + *rhs.s;
348 case any::Type::String:
349 assert(lhs.type == any::Type::StringLiteral || lhs.type == any::Type::String);
350 assert(rhs.type == any::Type::StringLiteral || rhs.type == any::Type::String);
351 return rhs.type == any::Type::StringLiteral ? *lhs.s + rhs.r : *lhs.s + *rhs.s;
352 default: assert(false && "Unsupported type for '+' operator");
357DEFINE_OPERATOR(+, long, long)
358DEFINE_OPERATOR(+, double, double)
359DEFINE_OPERATOR(+, char, char)
361auto operator+(const any& lhs_, const char * rhs) -> std::string {
362 const any& lhs = any::unthunkVariant(lhs_);
363 assert(lhs.type == any::Type::StringLiteral || lhs.type == any::Type::String);
364 return lhs.type == any::Type::StringLiteral ? std::string(lhs.r) + rhs : *lhs.s + rhs;
367auto operator+(const char * lhs, const any& rhs_) -> std::string {
368 const any& rhs = any::unthunkVariant(rhs_);
369 assert(rhs.type == any::Type::StringLiteral || rhs.type == any::Type::String);
370 return rhs.type == any::Type::StringLiteral ? lhs + std::string(rhs.r) : lhs + *rhs.s;
373auto operator-(const any& lhs_, const any& rhs_) -> any {
374 const any& lhs = any::unthunkVariant(lhs_);
375 const any& rhs = any::unthunkVariant(rhs_);
376 assert(lhs.type == rhs.type);
378 case any::Type::Integer: return lhs.i - rhs.i;
379 case any::Type::Double: return lhs.d - rhs.d;
380 case any::Type::Character: return any(char(lhs.c - rhs.c));
381 default: assert(false && "Unsupported type for '-' operator");
386DEFINE_OPERATOR(-, long, long)
387DEFINE_OPERATOR(-, double, double)
388DEFINE_OPERATOR(-, char, char)
390auto operator*(const any& lhs_, const any& rhs_) -> any {
391 const any& lhs = any::unthunkVariant(lhs_);
392 const any& rhs = any::unthunkVariant(rhs_);
393 assert(lhs.type == rhs.type);
395 case any::Type::Integer: return lhs.i * rhs.i;
396 case any::Type::Double: return lhs.d * rhs.d;
397 case any::Type::Character: return any(char(lhs.c * rhs.c));
398 default: assert(false && "Unsupported type for '*' operator");
403DEFINE_OPERATOR(*, long, long)
404DEFINE_OPERATOR(*, double, double)
405DEFINE_OPERATOR(*, char, char)
407auto operator/(const any& lhs_, const any& rhs_) -> any {
408 const any& lhs = any::unthunkVariant(lhs_);
409 const any& rhs = any::unthunkVariant(rhs_);
410 assert(lhs.type == rhs.type);
412 case any::Type::Integer: return lhs.i / rhs.i;
413 case any::Type::Double: return lhs.d / rhs.d;
414 case any::Type::Character: return any(char(lhs.c / rhs.c));
415 default: assert(false && "Unsupported type for '/' operator");
420DEFINE_OPERATOR(/, long, long)
421DEFINE_OPERATOR(/, double, double)
422DEFINE_OPERATOR(/, char, char)
424auto operator%(const any& lhs_, const any& rhs_) -> any {
425 const any& lhs = any::unthunkVariant(lhs_);
426 const any& rhs = any::unthunkVariant(rhs_);
427 assert(lhs.type == rhs.type);
429 case any::Type::Integer: return lhs.i % rhs.i;
430 case any::Type::Character: return any(char(lhs.c % rhs.c));
431 default: assert(false && "Unsupported type for '%' operator");
436DEFINE_OPERATOR(%, long, long)
437DEFINE_OPERATOR(%, char, char)
440auto operator-(const any& rhs_) -> any {
441 const any& rhs = any::unthunkVariant(rhs_);
443 case any::Type::Integer: return (- rhs.i);
444 case any::Type::Double: return (- rhs.d);
445 default: assert(false && "Unsupported type for unary '-' operator");
450} // 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