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"
20any::Closure::~Closure() {}
21any::EffClosure::~EffClosure() {}
23#define RETURN_VALUE(TAG, ACCESSOR, INDIRECTION) \
24 const any& variant = unthunkVariant(*this); \
25 assert(variant.tag == TAG); \
26 return INDIRECTION(variant.ACCESSOR); \
28auto any::operator()(const any& arg) const -> any {
29 const any& variant = unthunkVariant(*this);
30 if (variant.tag == Tag::Closure) {
31 return (*variant.l)(arg);
33 assert(variant.tag == Tag::Function);
34 return (*variant.f)(arg);
37auto any::operator()(const as_thunk) const -> const any& {
38 assert(tag == Tag::Thunk);
42auto any::operator()() const -> any {
43 const any& variant = unthunkVariant(*this);
44 if (variant.tag == Tag::EffClosure) {
45 return (*variant.k)();
47 assert(variant.tag == Tag::EffFunction);
48 return (*variant.e)();
51any::operator int() const {
52 RETURN_VALUE(Tag::Integer, i,)
55any::operator double() const {
56 RETURN_VALUE(Tag::Double, d,)
59any::operator bool() const {
60 RETURN_VALUE(Tag::Boolean, b,)
63any::operator char32_t() const {
64 RETURN_VALUE(Tag::Character, c,)
67any::operator char() const {
68 const auto val = cast<decltype(c)>(*this);
69 assert(val <= std::numeric_limits<char>::max());
70 return static_cast<char>(val);
73any::operator size_t() const {
74 const auto sz = cast<int>(*this);
76 return static_cast<size_t>(sz);
79any::operator const char *() const {
80 const any& variant = unthunkVariant(*this);
81 if (variant.tag == Tag::StringLiteral) {
84 assert(variant.tag == Tag::String);
85 return variant.s->c_str();
88any::operator const array&() const {
89 RETURN_VALUE(Tag::Array, a, *)
92auto any::extractPointer(IF_DEBUG(const any::Tag t)) const -> void* {
93 RETURN_VALUE(t, POINTER_FROM_MEMBER(p),)
96auto any::unthunkVariant(const any& a) -> const any& {
97 const any * variant = &a;
98 while (variant->tag == Tag::Thunk) {
99 variant = &((*variant->t)(unthunk));
104auto any::operator[](const size_t rhs) const -> const any& {
105 const auto& xs = cast<array>(*this);
109auto any::size() const -> size_t {
110 return cast<array>(*this).size();
113auto any::empty() const -> bool {
114 return cast<array>(*this).empty();
117auto any::contains(const Private::Symbol key) const -> bool {
118 // TODO: assumes at least one element -- safe assumption?
119 const auto& m = cast<map<unknown_size>>(*this);
120 std::remove_reference<decltype(m)>::type::size_type i = 0;
122 if (m[i].first == key) {
125 } while (m[++i].first != nullptr);
129//-----------------------------------------------------------------------------
130// Operator helper macros
131//-----------------------------------------------------------------------------
133#define DEFINE_CSTR_EQUALS_OPERATOR() \
134 auto operator==(const any& lhs_, const char * rhs) -> bool { \
135 const any& lhs = any::unthunkVariant(lhs_); \
136 assert(lhs.tag == any::Tag::StringLiteral || lhs.tag == any::Tag::String); \
137 if (lhs.tag == any::Tag::StringLiteral) { \
138 return (lhs.r == rhs) || (strcmp(lhs.r, rhs) == 0); \
140 return strcmp(lhs.s->c_str(), rhs) == 0; \
142 auto operator==(const char * lhs, const any& rhs_) -> bool { \
143 const any& rhs = any::unthunkVariant(rhs_); \
144 assert(rhs.tag == any::Tag::StringLiteral || rhs.tag == any::Tag::String); \
145 if (rhs.tag == any::Tag::StringLiteral) { \
146 return (lhs == rhs.r) || (strcmp(lhs, rhs) == 0); \
148 return strcmp(lhs, rhs.s->c_str()) == 0; \
151#define DEFINE_CSTR_COMPARISON_OPERATOR(op) \
152 auto operator op (const any& lhs, const char * rhs) -> bool { \
153 return strcmp(cast<const char *>(lhs), rhs) op 0; \
155 auto operator op (const char * lhs, const any& rhs) -> bool { \
156 return strcmp(lhs, cast<const char *>(rhs)) op 0; \
159#define DEFINE_COMPARISON_OPERATOR(op) \
160 auto operator op (const any& lhs_, const any& rhs_) -> bool { \
161 const any& lhs = any::unthunkVariant(lhs_); \
162 const any& rhs = any::unthunkVariant(rhs_); \
164 case any::Tag::Integer: assert(lhs.tag == any::Tag::Integer); return lhs.i op rhs.i; \
165 case any::Tag::Double: assert(lhs.tag == any::Tag::Double); return lhs.d op rhs.d; \
166 case any::Tag::Character: assert(lhs.tag == any::Tag::Character); return lhs.c op rhs.c; \
167 case any::Tag::Boolean: assert(lhs.tag == any::Tag::Boolean); return lhs.b op rhs.b; \
168 case any::Tag::StringLiteral: \
169 assert(lhs.tag == any::Tag::StringLiteral || lhs.tag == any::Tag::String); \
170 assert(rhs.tag == any::Tag::StringLiteral || rhs.tag == any::Tag::String); \
171 return strcmp(lhs.r, rhs.tag == any::Tag::StringLiteral ? rhs.r : rhs.s->c_str()) op 0; \
172 case any::Tag::String: \
173 assert(lhs.tag == any::Tag::StringLiteral || lhs.tag == any::Tag::String); \
174 assert(rhs.tag == any::Tag::StringLiteral || rhs.tag == any::Tag::String); \
175 return strcmp(lhs.s->c_str(), rhs.tag == any::Tag::StringLiteral ? rhs.r : rhs.s->c_str()) op 0; \
176 case any::Tag::Pointer: return lhs.p op rhs.p; \
177 default: assert(false && "Unsupported tag for operator " #op); \
182//-----------------------------------------------------------------------------
183// Operator definitions
184//-----------------------------------------------------------------------------
186DEFINE_COMPARISON_OPERATOR(==)
187DEFINE_COMPARISON_OPERATOR(!=)
188DEFINE_COMPARISON_OPERATOR(<)
189DEFINE_COMPARISON_OPERATOR(<=)
190DEFINE_COMPARISON_OPERATOR(>)
191DEFINE_COMPARISON_OPERATOR(>=)
193DEFINE_CSTR_EQUALS_OPERATOR()
194DEFINE_CSTR_COMPARISON_OPERATOR(!=)
195DEFINE_CSTR_COMPARISON_OPERATOR(<)
196DEFINE_CSTR_COMPARISON_OPERATOR(<=)
197DEFINE_CSTR_COMPARISON_OPERATOR(>)
198DEFINE_CSTR_COMPARISON_OPERATOR(>=)
200auto operator+(const any& lhs_, const any& rhs_) -> any {
201 const any& lhs = any::unthunkVariant(lhs_);
202 const any& rhs = any::unthunkVariant(rhs_);
204 case any::Tag::Integer: assert(lhs.tag == any::Tag::Integer); return lhs.i + rhs.i;
205 case any::Tag::Double: assert(lhs.tag == any::Tag::Double); return lhs.d + rhs.d;
206 case any::Tag::Character: assert(lhs.tag == any::Tag::Character); return decltype(any::c){lhs.c + rhs.c};
207 case any::Tag::StringLiteral:
208 assert(lhs.tag == any::Tag::StringLiteral || lhs.tag == any::Tag::String);
209 assert(rhs.tag == any::Tag::StringLiteral || rhs.tag == any::Tag::String);
210 return rhs.tag == any::Tag::StringLiteral ? string(lhs.r) + rhs.r : lhs.r + *rhs.s;
211 case any::Tag::String:
212 assert(lhs.tag == any::Tag::StringLiteral || lhs.tag == any::Tag::String);
213 assert(rhs.tag == any::Tag::StringLiteral || rhs.tag == any::Tag::String);
214 return rhs.tag == any::Tag::StringLiteral ? *lhs.s + rhs.r : *lhs.s + *rhs.s;
215 default: assert(false && "Unsupported tag for '+' operator");
220auto operator+(const any& lhs_, const char * rhs) -> string {
221 const any& lhs = any::unthunkVariant(lhs_);
222 assert(lhs.tag == any::Tag::StringLiteral || lhs.tag == any::Tag::String);
223 return lhs.tag == any::Tag::StringLiteral ? string(lhs.r) + rhs : *lhs.s + rhs;
226auto operator+(const char * lhs, const any& rhs_) -> string {
227 const any& rhs = any::unthunkVariant(rhs_);
228 assert(rhs.tag == any::Tag::StringLiteral || rhs.tag == any::Tag::String);
229 return rhs.tag == any::Tag::StringLiteral ? lhs + string(rhs.r) : lhs + *rhs.s;
232auto operator-(const any& lhs_, const any& rhs_) -> any {
233 const any& lhs = any::unthunkVariant(lhs_);
234 const any& rhs = any::unthunkVariant(rhs_);
235 assert(lhs.tag == rhs.tag);
237 case any::Tag::Integer: return lhs.i - rhs.i;
238 case any::Tag::Double: return lhs.d - rhs.d;
239 case any::Tag::Character: return decltype(any::c){lhs.c - rhs.c};
240 default: assert(false && "Unsupported tag for '-' operator");
245auto operator*(const any& lhs_, const any& rhs_) -> any {
246 const any& lhs = any::unthunkVariant(lhs_);
247 const any& rhs = any::unthunkVariant(rhs_);
248 assert(lhs.tag == rhs.tag);
250 case any::Tag::Integer: return lhs.i * rhs.i;
251 case any::Tag::Double: return lhs.d * rhs.d;
252 case any::Tag::Character: return decltype(lhs.c){lhs.c - rhs.c};
253 default: assert(false && "Unsupported tag for '*' operator");
258auto operator/(const any& lhs_, const any& rhs_) -> any {
259 const any& lhs = any::unthunkVariant(lhs_);
260 const any& rhs = any::unthunkVariant(rhs_);
261 assert(lhs.tag == rhs.tag);
263 case any::Tag::Integer: return lhs.i / rhs.i;
264 case any::Tag::Double: return lhs.d / rhs.d;
265 case any::Tag::Character: return decltype(any::c){lhs.c / rhs.c};
266 default: assert(false && "Unsupported tag for '/' operator");
271auto operator%(const any& lhs_, const any& rhs_) -> any {
272 const any& lhs = any::unthunkVariant(lhs_);
273 const any& rhs = any::unthunkVariant(rhs_);
274 assert(lhs.tag == rhs.tag);
276 case any::Tag::Integer: return lhs.i % rhs.i;
277 case any::Tag::Character: return decltype(any::c){lhs.c % rhs.c};
278 default: assert(false && "Unsupported tag for '%' operator");
284auto operator-(const any& rhs_) -> any {
285 const any& rhs = any::unthunkVariant(rhs_);
287 case any::Tag::Integer: return (- rhs.i);
288 case any::Tag::Double: return (- rhs.d);
289 default: assert(false && "Unsupported tag for unary '-' operator");
294} // 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