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 RETURN_VALUE(TYPE, ACCESSOR, INDIRECTION) \
21 const any& variant = unthunkVariant(*this); \
22 assert(variant.type == TYPE); \
23 return INDIRECTION(variant.ACCESSOR); \
26auto any::cast() const -> typename std::enable_if<std::is_same<T, long>::value, T>::type {
27 RETURN_VALUE(Type::Integer, i,)
29template auto any::cast<long>() const -> long;
32auto any::cast() const -> typename std::enable_if<std::is_same<T, double>::value, T>::type {
33 RETURN_VALUE(Type::Double, d,)
35template auto any::cast<double>() const -> double;
38auto any::cast() const -> typename std::enable_if<std::is_same<T, char>::value, T>::type {
39 RETURN_VALUE(Type::Character, c,)
41template auto any::cast<char>() const -> char;
44auto any::cast() const -> typename std::enable_if<std::is_same<T, bool>::value, T>::type {
45 RETURN_VALUE(Type::Boolean, b,)
47template auto any::cast<bool>() const -> bool;
50auto any::cast() const -> typename std::enable_if<std::is_same<T, string>::value, T>::type {
51 const any& variant = unthunkVariant(*this);
52 if (variant.type == Type::StringLiteral) {
55 assert(variant.type == Type::String);
56 return variant.s->c_str();
58template auto any::cast<string>() const -> string;
61auto any::cast() const -> typename std::enable_if<std::is_same<T, map>::value, const T&>::type {
62 RETURN_VALUE(Type::Map, m, *)
64template auto any::cast<any::map>() const -> const map&;
67auto any::cast() const -> typename std::enable_if<std::is_same<T, data>::value, const T&>::type {
68 RETURN_VALUE(Type::Data, v, *)
70template auto any::cast<any::data>() const -> const data&;
73auto any::cast() const -> typename std::enable_if<std::is_same<T, array>::value, const T&>::type {
74 RETURN_VALUE(Type::Array, a, *)
76template auto any::cast<any::array>() const -> const array&;
78auto any::operator()(const any& arg) const -> any {
79 const any& variant = unthunkVariant(*this);
80 if (variant.type == Type::Closure) {
81 return (*variant.l)(arg);
83 assert(variant.type == Type::Function);
84 return (*variant.f)(arg);
87auto any::operator()(const any& arg1, const any& arg2) const -> any {
88 const any& variant = unthunkVariant(*this);
89 if (variant.type == Type::Closure) {
90 return (*variant.l)(arg1, arg2);
92 assert(variant.type == Type::Function);
93 return (*variant.f)(arg1)(arg2);
96auto any::operator()(const any& arg1, const any& arg2, const any& arg3) const -> any {
97 const any& variant = unthunkVariant(*this);
98 if (variant.type == Type::Closure) {
99 return (*variant.l)(arg1, arg2, arg3);
101 assert(variant.type == Type::Function);
102 return (*variant.f)(arg1)(arg2)(arg3);
105auto any::operator()(const as_thunk) const -> const any& {
106 assert(type == Type::Thunk);
107 return (*t)(unthunk);
110auto any::operator()() const -> any {
111 const any& variant = unthunkVariant(*this);
112 assert(variant.type == Type::EffFunction);
113 return (*variant.e)();
116any::operator long() const {
120any::operator double() const {
121 return cast<double>();
124any::operator bool() const {
128any::operator string() const {
129 return cast<string>();
132any::operator const map&() const {
136any::operator const data&() const {
140any::operator const array&() const {
141 return cast<array>();
144auto any::extractPointer() const -> void* {
145 RETURN_VALUE(Type::Pointer, p.get(),)
148auto any::unthunkVariant(const any& a) -> const any& {
149 const any * variant = &a;
150 while (variant->type == Type::Thunk) {
151 variant = &((*variant->t)(unthunk));
156auto any::operator[](const char rhs[]) const -> const any& {
157 const any& variant = unthunkVariant(*this);
158 assert(variant.type == Type::Map);
159 const auto begin = variant.m->cbegin();
160 const auto end = variant.m->cend();
161 for (auto it = begin; it != end; ++it) {
162 if (it->first == rhs) {
166 for (auto it = begin; it != end; ++it) {
167 if (strcmp(it->first, rhs) == 0) {
171 throw runtime_error("map key not found");
174auto any::operator[](const size_t rhs) const -> const any& {
175 const any& variant = unthunkVariant(*this);
176 assert(variant.type == Type::Array);
177 return (*variant.a)[rhs];
180auto any::operator[](const any& rhs) const -> const any& {
181 const any& variant = unthunkVariant(*this);
182 assert(variant.type == Type::Array);
183 return (*variant.a)[rhs.cast<long>()];
186auto any::contains(const char key[]) const -> bool {
187 const any& variant = unthunkVariant(*this);
188 assert(variant.type == Type::Map);
189 const auto begin = variant.m->cbegin();
190 const auto end = variant.m->cend();
191 for (auto it = begin; it != end; ++it) {
192 if (it->first == key) {
196 for (auto it = begin; it != end; ++it) {
197 if (strcmp(it->first, key) == 0) {
204//-----------------------------------------------------------------------------
205// Operator helper macros
206//-----------------------------------------------------------------------------
208#define DEFINE_OPERATOR(op, ty, rty) \
209auto operator op (const any& lhs, ty rhs) -> rty { \
210 return lhs.cast<typename std::remove_const<std::remove_reference<ty>::type>::type>() op rhs; \
212auto operator op (ty lhs, const any& rhs) -> rty { \
213 return lhs op rhs.cast<typename std::remove_const<std::remove_reference<ty>::type>::type>(); \
216#define DEFINE_CSTR_EQUALS_OPERATOR() \
217 auto operator==(const any& lhs_, const char * rhs) -> bool { \
218 const any& lhs = any::unthunkVariant(lhs_); \
219 assert(lhs.type == any::Type::StringLiteral || lhs.type == any::Type::String); \
220 if (lhs.type == any::Type::StringLiteral) { \
221 return (lhs.r == rhs) || (strcmp(lhs.r, rhs) == 0); \
223 return strcmp(lhs.s->c_str(), rhs) == 0; \
225 auto operator==(const char * lhs, const any& rhs_) -> bool { \
226 const any& rhs = any::unthunkVariant(rhs_); \
227 assert(rhs.type == any::Type::StringLiteral || rhs.type == any::Type::String); \
228 if (rhs.type == any::Type::StringLiteral) { \
229 return (lhs == rhs.r) || (strcmp(lhs, rhs) == 0); \
231 return strcmp(lhs, rhs.s->c_str()) == 0; \
234#define DEFINE_CSTR_COMPARISON_OPERATOR(op) \
235 auto operator op (const any& lhs, const char * rhs) -> bool { \
236 return strcmp(lhs.cast<string>(), rhs) op 0; \
238 auto operator op (const char * lhs, const any& rhs) -> bool { \
239 return strcmp(lhs, rhs.cast<string>()) op 0; \
242#define DEFINE_COMPARISON_OPERATOR(op) \
243 auto operator op (const any& lhs_, const any& rhs_) -> bool { \
244 const any& lhs = any::unthunkVariant(lhs_); \
245 const any& rhs = any::unthunkVariant(rhs_); \
246 switch (lhs.type) { \
247 case any::Type::Integer: assert(lhs.type == any::Type::Integer); return lhs.i op rhs.i; \
248 case any::Type::Double: assert(lhs.type == any::Type::Double); return lhs.d op rhs.d; \
249 case any::Type::Character: assert(lhs.type == any::Type::Character); return lhs.c op rhs.c; \
250 case any::Type::Boolean: assert(lhs.type == any::Type::Boolean); return lhs.b op rhs.b; \
251 case any::Type::StringLiteral: \
252 assert(lhs.type == any::Type::StringLiteral || lhs.type == any::Type::String); \
253 assert(rhs.type == any::Type::StringLiteral || rhs.type == any::Type::String); \
254 return strcmp(lhs.r, rhs.type == any::Type::StringLiteral ? rhs.r : rhs.s->c_str()) op 0; \
255 case any::Type::String: \
256 assert(lhs.type == any::Type::StringLiteral || lhs.type == any::Type::String); \
257 assert(rhs.type == any::Type::StringLiteral || rhs.type == any::Type::String); \
258 return strcmp(lhs.s->c_str(), rhs.type == any::Type::StringLiteral ? rhs.r : rhs.s->c_str()) op 0; \
259 case any::Type::Pointer: return lhs.p op rhs.p; \
260 default: assert(false && "Unsupported type for operator " #op); \
264 DEFINE_OPERATOR(op, long, bool) \
265 DEFINE_OPERATOR(op, double, bool) \
266 DEFINE_OPERATOR(op, char, bool) \
267 DEFINE_OPERATOR(op, bool, bool) \
269//-----------------------------------------------------------------------------
270// Operator definitions
271//-----------------------------------------------------------------------------
273DEFINE_COMPARISON_OPERATOR(==)
274DEFINE_COMPARISON_OPERATOR(!=)
275DEFINE_COMPARISON_OPERATOR(<)
276DEFINE_COMPARISON_OPERATOR(<=)
277DEFINE_COMPARISON_OPERATOR(>)
278DEFINE_COMPARISON_OPERATOR(>=)
280DEFINE_CSTR_EQUALS_OPERATOR()
281DEFINE_CSTR_COMPARISON_OPERATOR(!=)
282DEFINE_CSTR_COMPARISON_OPERATOR(<)
283DEFINE_CSTR_COMPARISON_OPERATOR(<=)
284DEFINE_CSTR_COMPARISON_OPERATOR(>)
285DEFINE_CSTR_COMPARISON_OPERATOR(>=)
287auto operator+(const any& lhs_, const any& rhs_) -> any {
288 const any& lhs = any::unthunkVariant(lhs_);
289 const any& rhs = any::unthunkVariant(rhs_);
291 case any::Type::Integer: assert(lhs.type == any::Type::Integer); return lhs.i + rhs.i;
292 case any::Type::Double: assert(lhs.type == any::Type::Double); return lhs.d + rhs.d;
293 case any::Type::Character: assert(lhs.type == any::Type::Character); return any(char(lhs.c + rhs.c));
294 case any::Type::StringLiteral:
295 assert(lhs.type == any::Type::StringLiteral || lhs.type == any::Type::String);
296 assert(rhs.type == any::Type::StringLiteral || rhs.type == any::Type::String);
297 return rhs.type == any::Type::StringLiteral ? std::string(lhs.r) + rhs.r : lhs.r + *rhs.s;
298 case any::Type::String:
299 assert(lhs.type == any::Type::StringLiteral || lhs.type == any::Type::String);
300 assert(rhs.type == any::Type::StringLiteral || rhs.type == any::Type::String);
301 return rhs.type == any::Type::StringLiteral ? *lhs.s + rhs.r : *lhs.s + *rhs.s;
302 default: assert(false && "Unsupported type for '+' operator");
307DEFINE_OPERATOR(+, long, long)
308DEFINE_OPERATOR(+, double, double)
309DEFINE_OPERATOR(+, char, char)
311auto operator+(const any& lhs_, const char * rhs) -> std::string {
312 const any& lhs = any::unthunkVariant(lhs_);
313 assert(lhs.type == any::Type::StringLiteral || lhs.type == any::Type::String);
314 return lhs.type == any::Type::StringLiteral ? std::string(lhs.r) + rhs : *lhs.s + rhs;
317auto operator+(const char * lhs, const any& rhs_) -> std::string {
318 const any& rhs = any::unthunkVariant(rhs_);
319 assert(rhs.type == any::Type::StringLiteral || rhs.type == any::Type::String);
320 return rhs.type == any::Type::StringLiteral ? lhs + std::string(rhs.r) : lhs + *rhs.s;
323auto operator-(const any& lhs_, const any& rhs_) -> any {
324 const any& lhs = any::unthunkVariant(lhs_);
325 const any& rhs = any::unthunkVariant(rhs_);
326 assert(lhs.type == rhs.type);
328 case any::Type::Integer: return lhs.i - rhs.i;
329 case any::Type::Double: return lhs.d - rhs.d;
330 case any::Type::Character: return any(char(lhs.c - rhs.c));
331 default: assert(false && "Unsupported type for '-' operator");
336DEFINE_OPERATOR(-, long, long)
337DEFINE_OPERATOR(-, double, double)
338DEFINE_OPERATOR(-, char, char)
340auto operator*(const any& lhs_, const any& rhs_) -> any {
341 const any& lhs = any::unthunkVariant(lhs_);
342 const any& rhs = any::unthunkVariant(rhs_);
343 assert(lhs.type == rhs.type);
345 case any::Type::Integer: return lhs.i * rhs.i;
346 case any::Type::Double: return lhs.d * rhs.d;
347 case any::Type::Character: return any(char(lhs.c * rhs.c));
348 default: assert(false && "Unsupported type for '*' operator");
353DEFINE_OPERATOR(*, long, long)
354DEFINE_OPERATOR(*, double, double)
355DEFINE_OPERATOR(*, char, char)
357auto operator/(const any& lhs_, const any& rhs_) -> any {
358 const any& lhs = any::unthunkVariant(lhs_);
359 const any& rhs = any::unthunkVariant(rhs_);
360 assert(lhs.type == rhs.type);
362 case any::Type::Integer: return lhs.i / rhs.i;
363 case any::Type::Double: return lhs.d / rhs.d;
364 case any::Type::Character: return any(char(lhs.c / rhs.c));
365 default: assert(false && "Unsupported type for '/' operator");
370DEFINE_OPERATOR(/, long, long)
371DEFINE_OPERATOR(/, double, double)
372DEFINE_OPERATOR(/, char, char)
374auto operator%(const any& lhs_, const any& rhs_) -> any {
375 const any& lhs = any::unthunkVariant(lhs_);
376 const any& rhs = any::unthunkVariant(rhs_);
377 assert(lhs.type == rhs.type);
379 case any::Type::Integer: return lhs.i % rhs.i;
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(%, char, char)
390auto operator-(const any& rhs_) -> any {
391 const any& rhs = any::unthunkVariant(rhs_);
393 case any::Type::Integer: return (- rhs.i);
394 case any::Type::Double: return (- rhs.d);
395 default: assert(false && "Unsupported type for unary '-' operator");
400} // 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