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); \
25auto any::operator()(const any& arg) const -> any {
26 const any& variant = unthunkVariant(*this);
27 if (variant.type == Type::Closure) {
28 return (*variant.l)(arg);
30 assert(variant.type == Type::Function);
31 return (*variant.f)(arg);
34auto any::operator()(const as_thunk) const -> const any& {
35 assert(type == Type::Thunk);
39auto any::operator()() const -> any {
40 const any& variant = unthunkVariant(*this);
41 if (variant.type == Type::EffClosure) {
42 return (*variant.k)();
44 assert(variant.type == Type::EffFunction);
45 return (*variant.e)();
48any::operator int() const {
49 RETURN_VALUE(Type::Integer, i,)
52any::operator double() const {
53 RETURN_VALUE(Type::Double, d,)
56any::operator bool() const {
57 RETURN_VALUE(Type::Boolean, b,)
60any::operator char() const {
61 RETURN_VALUE(Type::Character, c,)
64any::operator cstring() const {
65 const any& variant = unthunkVariant(*this);
66 if (variant.type == Type::StringLiteral) {
69 assert(variant.type == Type::String);
70 return variant.s->c_str();
73any::operator const map&() const {
74 RETURN_VALUE(Type::Map, m, *)
77any::operator const data&() const {
78 RETURN_VALUE(Type::Data, v, *)
81any::operator const array&() const {
82 RETURN_VALUE(Type::Array, a, *)
85auto any::extractPointer() const -> void* {
86 RETURN_VALUE(Type::Pointer, POINTER_FROM_MEMBER(p),)
89auto any::unthunkVariant(const any& a) -> const any& {
90 const any * variant = &a;
91 while (variant->type == Type::Thunk) {
92 variant = &((*variant->t)(unthunk));
97auto any::operator[](const char rhs[]) const -> const any& {
98 const any& variant = unthunkVariant(*this);
99 assert(variant.type == Type::Map);
100 const auto begin = variant.m->cbegin();
101 const auto end = variant.m->cend();
102 for (auto it = begin; it != end; ++it) {
103 if (it->first == rhs) {
107 for (auto it = begin; it != end; ++it) {
108 if (strcmp(it->first, rhs) == 0) {
112 throw runtime_error("map key not found");
115auto any::operator[](const size_t rhs) const -> const any& {
116 const any& variant = unthunkVariant(*this);
117 assert(variant.type == Type::Array);
118 return (*variant.a)[rhs];
121auto any::operator[](const any& rhs) const -> const any& {
122 const any& variant = unthunkVariant(*this);
123 assert(variant.type == Type::Array);
124 return (*variant.a)[cast<int>(rhs)];
127auto any::contains(const char key[]) const -> bool {
128 const any& variant = unthunkVariant(*this);
129 assert(variant.type == Type::Map);
130 const auto begin = variant.m->cbegin();
131 const auto end = variant.m->cend();
132 for (auto it = begin; it != end; ++it) {
133 if (it->first == key) {
137 for (auto it = begin; it != end; ++it) {
138 if (strcmp(it->first, key) == 0) {
145//-----------------------------------------------------------------------------
146// Operator helper macros
147//-----------------------------------------------------------------------------
149#define DEFINE_CSTR_EQUALS_OPERATOR() \
150 auto operator==(const any& lhs_, const char * rhs) -> bool { \
151 const any& lhs = any::unthunkVariant(lhs_); \
152 assert(lhs.type == any::Type::StringLiteral || lhs.type == any::Type::String); \
153 if (lhs.type == any::Type::StringLiteral) { \
154 return (lhs.r == rhs) || (strcmp(lhs.r, rhs) == 0); \
156 return strcmp(lhs.s->c_str(), rhs) == 0; \
158 auto operator==(const char * lhs, const any& rhs_) -> bool { \
159 const any& rhs = any::unthunkVariant(rhs_); \
160 assert(rhs.type == any::Type::StringLiteral || rhs.type == any::Type::String); \
161 if (rhs.type == any::Type::StringLiteral) { \
162 return (lhs == rhs.r) || (strcmp(lhs, rhs) == 0); \
164 return strcmp(lhs, rhs.s->c_str()) == 0; \
167#define DEFINE_CSTR_COMPARISON_OPERATOR(op) \
168 auto operator op (const any& lhs, const char * rhs) -> bool { \
169 return strcmp(cast<cstring>(lhs), rhs) op 0; \
171 auto operator op (const char * lhs, const any& rhs) -> bool { \
172 return strcmp(lhs, cast<cstring>(rhs)) op 0; \
175#define DEFINE_COMPARISON_OPERATOR(op) \
176 auto operator op (const any& lhs_, const any& rhs_) -> bool { \
177 const any& lhs = any::unthunkVariant(lhs_); \
178 const any& rhs = any::unthunkVariant(rhs_); \
179 switch (lhs.type) { \
180 case any::Type::Integer: assert(lhs.type == any::Type::Integer); return lhs.i op rhs.i; \
181 case any::Type::Double: assert(lhs.type == any::Type::Double); return lhs.d op rhs.d; \
182 case any::Type::Character: assert(lhs.type == any::Type::Character); return lhs.c op rhs.c; \
183 case any::Type::Boolean: assert(lhs.type == any::Type::Boolean); return lhs.b op rhs.b; \
184 case any::Type::StringLiteral: \
185 assert(lhs.type == any::Type::StringLiteral || lhs.type == any::Type::String); \
186 assert(rhs.type == any::Type::StringLiteral || rhs.type == any::Type::String); \
187 return strcmp(lhs.r, rhs.type == any::Type::StringLiteral ? rhs.r : rhs.s->c_str()) op 0; \
188 case any::Type::String: \
189 assert(lhs.type == any::Type::StringLiteral || lhs.type == any::Type::String); \
190 assert(rhs.type == any::Type::StringLiteral || rhs.type == any::Type::String); \
191 return strcmp(lhs.s->c_str(), rhs.type == any::Type::StringLiteral ? rhs.r : rhs.s->c_str()) op 0; \
192 case any::Type::Pointer: return lhs.p op rhs.p; \
193 default: assert(false && "Unsupported type for operator " #op); \
198//-----------------------------------------------------------------------------
199// Operator definitions
200//-----------------------------------------------------------------------------
202DEFINE_COMPARISON_OPERATOR(==)
203DEFINE_COMPARISON_OPERATOR(!=)
204DEFINE_COMPARISON_OPERATOR(<)
205DEFINE_COMPARISON_OPERATOR(<=)
206DEFINE_COMPARISON_OPERATOR(>)
207DEFINE_COMPARISON_OPERATOR(>=)
209DEFINE_CSTR_EQUALS_OPERATOR()
210DEFINE_CSTR_COMPARISON_OPERATOR(!=)
211DEFINE_CSTR_COMPARISON_OPERATOR(<)
212DEFINE_CSTR_COMPARISON_OPERATOR(<=)
213DEFINE_CSTR_COMPARISON_OPERATOR(>)
214DEFINE_CSTR_COMPARISON_OPERATOR(>=)
216auto operator+(const any& lhs_, const any& rhs_) -> any {
217 const any& lhs = any::unthunkVariant(lhs_);
218 const any& rhs = any::unthunkVariant(rhs_);
220 case any::Type::Integer: assert(lhs.type == any::Type::Integer); return lhs.i + rhs.i;
221 case any::Type::Double: assert(lhs.type == any::Type::Double); return lhs.d + rhs.d;
222 case any::Type::Character: assert(lhs.type == any::Type::Character); return any(char(lhs.c + rhs.c));
223 case any::Type::StringLiteral:
224 assert(lhs.type == any::Type::StringLiteral || lhs.type == any::Type::String);
225 assert(rhs.type == any::Type::StringLiteral || rhs.type == any::Type::String);
226 return rhs.type == any::Type::StringLiteral ? std::string(lhs.r) + rhs.r : lhs.r + *rhs.s;
227 case any::Type::String:
228 assert(lhs.type == any::Type::StringLiteral || lhs.type == any::Type::String);
229 assert(rhs.type == any::Type::StringLiteral || rhs.type == any::Type::String);
230 return rhs.type == any::Type::StringLiteral ? *lhs.s + rhs.r : *lhs.s + *rhs.s;
231 default: assert(false && "Unsupported type for '+' operator");
236auto operator+(const any& lhs_, const char * rhs) -> std::string {
237 const any& lhs = any::unthunkVariant(lhs_);
238 assert(lhs.type == any::Type::StringLiteral || lhs.type == any::Type::String);
239 return lhs.type == any::Type::StringLiteral ? std::string(lhs.r) + rhs : *lhs.s + rhs;
242auto operator+(const char * lhs, const any& rhs_) -> std::string {
243 const any& rhs = any::unthunkVariant(rhs_);
244 assert(rhs.type == any::Type::StringLiteral || rhs.type == any::Type::String);
245 return rhs.type == any::Type::StringLiteral ? lhs + std::string(rhs.r) : lhs + *rhs.s;
248auto operator-(const any& lhs_, const any& rhs_) -> any {
249 const any& lhs = any::unthunkVariant(lhs_);
250 const any& rhs = any::unthunkVariant(rhs_);
251 assert(lhs.type == rhs.type);
253 case any::Type::Integer: return lhs.i - rhs.i;
254 case any::Type::Double: return lhs.d - rhs.d;
255 case any::Type::Character: return any(char(lhs.c - rhs.c));
256 default: assert(false && "Unsupported type for '-' operator");
261auto operator*(const any& lhs_, const any& rhs_) -> any {
262 const any& lhs = any::unthunkVariant(lhs_);
263 const any& rhs = any::unthunkVariant(rhs_);
264 assert(lhs.type == rhs.type);
266 case any::Type::Integer: return lhs.i * rhs.i;
267 case any::Type::Double: return lhs.d * rhs.d;
268 case any::Type::Character: return any(char(lhs.c * rhs.c));
269 default: assert(false && "Unsupported type for '*' operator");
274auto operator/(const any& lhs_, const any& rhs_) -> any {
275 const any& lhs = any::unthunkVariant(lhs_);
276 const any& rhs = any::unthunkVariant(rhs_);
277 assert(lhs.type == rhs.type);
279 case any::Type::Integer: return lhs.i / rhs.i;
280 case any::Type::Double: return lhs.d / rhs.d;
281 case any::Type::Character: return any(char(lhs.c / rhs.c));
282 default: assert(false && "Unsupported type for '/' operator");
287auto operator%(const any& lhs_, const any& rhs_) -> any {
288 const any& lhs = any::unthunkVariant(lhs_);
289 const any& rhs = any::unthunkVariant(rhs_);
290 assert(lhs.type == rhs.type);
292 case any::Type::Integer: return lhs.i % rhs.i;
293 case any::Type::Character: return any(char(lhs.c % rhs.c));
294 default: assert(false && "Unsupported type for '%' operator");
300auto operator-(const any& rhs_) -> any {
301 const any& rhs = any::unthunkVariant(rhs_);
303 case any::Type::Integer: return (- rhs.i);
304 case any::Type::Double: return (- rhs.d);
305 default: assert(false && "Unsupported type for unary '-' operator");
310} // 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