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(TAG, ACCESSOR, INDIRECTION) \
21 const any& variant = unthunkVariant(*this); \
22 assert(variant.tag == TAG); \
23 return INDIRECTION(variant.ACCESSOR); \
25auto any::operator()(const any& arg) const -> any {
26 const any& variant = unthunkVariant(*this);
27 if (variant.tag == tag_t::Closure) {
28 return (*variant.l)(arg);
30 assert(variant.tag == tag_t::Function);
31 return (*variant.f)(arg);
34auto any::operator()(const as_thunk) const -> const any& {
35 assert(tag == tag_t::Thunk);
39auto any::operator()() const -> any {
40 const any& variant = unthunkVariant(*this);
41 if (variant.tag == tag_t::EffClosure) {
42 return (*variant.k)();
44 assert(variant.tag == tag_t::EffFunction);
45 return (*variant.e)();
48any::operator int() const {
49 RETURN_VALUE(tag_t::Integer, i,)
52any::operator double() const {
53 RETURN_VALUE(tag_t::Double, d,)
56any::operator bool() const {
57 RETURN_VALUE(tag_t::Boolean, b,)
60any::operator char() const {
61 RETURN_VALUE(tag_t::Character, c,)
64any::operator cstring() const {
65 const any& variant = unthunkVariant(*this);
66 if (variant.tag == tag_t::StringLiteral) {
69 assert(variant.tag == tag_t::String);
70 return variant.s->c_str();
73any::operator const array&() const {
74 RETURN_VALUE(tag_t::Array, a, *)
77auto any::extractPointer(IF_DEBUG(const any::tag_t t)) const -> void* {
78 RETURN_VALUE(t, POINTER_FROM_MEMBER(p),)
81auto any::unthunkVariant(const any& a) -> const any& {
82 const any * variant = &a;
83 while (variant->tag == tag_t::Thunk) {
84 variant = &((*variant->t)(unthunk));
89auto any::operator[](const symbol_t key) const -> const any& {
90 return get(key, cast<map<unknown_size>>(*this));
93auto any::operator[](const size_t rhs) const -> const any& {
94 const auto& xs = cast<array>(*this);
98auto any::operator[](const any& rhs) const -> const any& {
99 const auto& xs = cast<array>(*this);
100 return xs[cast<int>(rhs)];
103auto any::contains(const symbol_t key) const -> bool {
104 // TODO: assumes at least one element -- safe assumption?
105 const auto& m = cast<map<unknown_size>>(*this);
106 std::remove_reference<decltype(m)>::type::size_type i = 0;
108 if (m[i].first == key) {
111 } while (m[++i].first != nullptr);
115//-----------------------------------------------------------------------------
116// Operator helper macros
117//-----------------------------------------------------------------------------
119#define DEFINE_CSTR_EQUALS_OPERATOR() \
120 auto operator==(const any& lhs_, const char * rhs) -> bool { \
121 const any& lhs = any::unthunkVariant(lhs_); \
122 assert(lhs.tag == any::tag_t::StringLiteral || lhs.tag == any::tag_t::String); \
123 if (lhs.tag == any::tag_t::StringLiteral) { \
124 return (lhs.r == rhs) || (strcmp(lhs.r, rhs) == 0); \
126 return strcmp(lhs.s->c_str(), rhs) == 0; \
128 auto operator==(const char * lhs, const any& rhs_) -> bool { \
129 const any& rhs = any::unthunkVariant(rhs_); \
130 assert(rhs.tag == any::tag_t::StringLiteral || rhs.tag == any::tag_t::String); \
131 if (rhs.tag == any::tag_t::StringLiteral) { \
132 return (lhs == rhs.r) || (strcmp(lhs, rhs) == 0); \
134 return strcmp(lhs, rhs.s->c_str()) == 0; \
137#define DEFINE_CSTR_COMPARISON_OPERATOR(op) \
138 auto operator op (const any& lhs, const char * rhs) -> bool { \
139 return strcmp(cast<cstring>(lhs), rhs) op 0; \
141 auto operator op (const char * lhs, const any& rhs) -> bool { \
142 return strcmp(lhs, cast<cstring>(rhs)) op 0; \
145#define DEFINE_COMPARISON_OPERATOR(op) \
146 auto operator op (const any& lhs_, const any& rhs_) -> bool { \
147 const any& lhs = any::unthunkVariant(lhs_); \
148 const any& rhs = any::unthunkVariant(rhs_); \
150 case any::tag_t::Integer: assert(lhs.tag == any::tag_t::Integer); return lhs.i op rhs.i; \
151 case any::tag_t::Double: assert(lhs.tag == any::tag_t::Double); return lhs.d op rhs.d; \
152 case any::tag_t::Character: assert(lhs.tag == any::tag_t::Character); return lhs.c op rhs.c; \
153 case any::tag_t::Boolean: assert(lhs.tag == any::tag_t::Boolean); return lhs.b op rhs.b; \
154 case any::tag_t::StringLiteral: \
155 assert(lhs.tag == any::tag_t::StringLiteral || lhs.tag == any::tag_t::String); \
156 assert(rhs.tag == any::tag_t::StringLiteral || rhs.tag == any::tag_t::String); \
157 return strcmp(lhs.r, rhs.tag == any::tag_t::StringLiteral ? rhs.r : rhs.s->c_str()) op 0; \
158 case any::tag_t::String: \
159 assert(lhs.tag == any::tag_t::StringLiteral || lhs.tag == any::tag_t::String); \
160 assert(rhs.tag == any::tag_t::StringLiteral || rhs.tag == any::tag_t::String); \
161 return strcmp(lhs.s->c_str(), rhs.tag == any::tag_t::StringLiteral ? rhs.r : rhs.s->c_str()) op 0; \
162 case any::tag_t::Pointer: return lhs.p op rhs.p; \
163 default: assert(false && "Unsupported tag for operator " #op); \
168//-----------------------------------------------------------------------------
169// Operator definitions
170//-----------------------------------------------------------------------------
172DEFINE_COMPARISON_OPERATOR(==)
173DEFINE_COMPARISON_OPERATOR(!=)
174DEFINE_COMPARISON_OPERATOR(<)
175DEFINE_COMPARISON_OPERATOR(<=)
176DEFINE_COMPARISON_OPERATOR(>)
177DEFINE_COMPARISON_OPERATOR(>=)
179DEFINE_CSTR_EQUALS_OPERATOR()
180DEFINE_CSTR_COMPARISON_OPERATOR(!=)
181DEFINE_CSTR_COMPARISON_OPERATOR(<)
182DEFINE_CSTR_COMPARISON_OPERATOR(<=)
183DEFINE_CSTR_COMPARISON_OPERATOR(>)
184DEFINE_CSTR_COMPARISON_OPERATOR(>=)
186auto operator+(const any& lhs_, const any& rhs_) -> any {
187 const any& lhs = any::unthunkVariant(lhs_);
188 const any& rhs = any::unthunkVariant(rhs_);
190 case any::tag_t::Integer: assert(lhs.tag == any::tag_t::Integer); return lhs.i + rhs.i;
191 case any::tag_t::Double: assert(lhs.tag == any::tag_t::Double); return lhs.d + rhs.d;
192 case any::tag_t::Character: assert(lhs.tag == any::tag_t::Character); return any(char(lhs.c + rhs.c));
193 case any::tag_t::StringLiteral:
194 assert(lhs.tag == any::tag_t::StringLiteral || lhs.tag == any::tag_t::String);
195 assert(rhs.tag == any::tag_t::StringLiteral || rhs.tag == any::tag_t::String);
196 return rhs.tag == any::tag_t::StringLiteral ? std::string(lhs.r) + rhs.r : lhs.r + *rhs.s;
197 case any::tag_t::String:
198 assert(lhs.tag == any::tag_t::StringLiteral || lhs.tag == any::tag_t::String);
199 assert(rhs.tag == any::tag_t::StringLiteral || rhs.tag == any::tag_t::String);
200 return rhs.tag == any::tag_t::StringLiteral ? *lhs.s + rhs.r : *lhs.s + *rhs.s;
201 default: assert(false && "Unsupported tag for '+' operator");
206auto operator+(const any& lhs_, const char * rhs) -> std::string {
207 const any& lhs = any::unthunkVariant(lhs_);
208 assert(lhs.tag == any::tag_t::StringLiteral || lhs.tag == any::tag_t::String);
209 return lhs.tag == any::tag_t::StringLiteral ? std::string(lhs.r) + rhs : *lhs.s + rhs;
212auto operator+(const char * lhs, const any& rhs_) -> std::string {
213 const any& rhs = any::unthunkVariant(rhs_);
214 assert(rhs.tag == any::tag_t::StringLiteral || rhs.tag == any::tag_t::String);
215 return rhs.tag == any::tag_t::StringLiteral ? lhs + std::string(rhs.r) : lhs + *rhs.s;
218auto operator-(const any& lhs_, const any& rhs_) -> any {
219 const any& lhs = any::unthunkVariant(lhs_);
220 const any& rhs = any::unthunkVariant(rhs_);
221 assert(lhs.tag == rhs.tag);
223 case any::tag_t::Integer: return lhs.i - rhs.i;
224 case any::tag_t::Double: return lhs.d - rhs.d;
225 case any::tag_t::Character: return any(char(lhs.c - rhs.c));
226 default: assert(false && "Unsupported tag for '-' operator");
231auto operator*(const any& lhs_, const any& rhs_) -> any {
232 const any& lhs = any::unthunkVariant(lhs_);
233 const any& rhs = any::unthunkVariant(rhs_);
234 assert(lhs.tag == rhs.tag);
236 case any::tag_t::Integer: return lhs.i * rhs.i;
237 case any::tag_t::Double: return lhs.d * rhs.d;
238 case any::tag_t::Character: return any(char(lhs.c * rhs.c));
239 default: assert(false && "Unsupported tag for '*' operator");
244auto operator/(const any& lhs_, const any& rhs_) -> any {
245 const any& lhs = any::unthunkVariant(lhs_);
246 const any& rhs = any::unthunkVariant(rhs_);
247 assert(lhs.tag == rhs.tag);
249 case any::tag_t::Integer: return lhs.i / rhs.i;
250 case any::tag_t::Double: return lhs.d / rhs.d;
251 case any::tag_t::Character: return any(char(lhs.c / rhs.c));
252 default: assert(false && "Unsupported tag for '/' operator");
257auto operator%(const any& lhs_, const any& rhs_) -> any {
258 const any& lhs = any::unthunkVariant(lhs_);
259 const any& rhs = any::unthunkVariant(rhs_);
260 assert(lhs.tag == rhs.tag);
262 case any::tag_t::Integer: return lhs.i % rhs.i;
263 case any::tag_t::Character: return any(char(lhs.c % rhs.c));
264 default: assert(false && "Unsupported tag for '%' operator");
270auto operator-(const any& rhs_) -> any {
271 const any& rhs = any::unthunkVariant(rhs_);
273 case any::tag_t::Integer: return (- rhs.i);
274 case any::tag_t::Double: return (- rhs.d);
275 default: assert(false && "Unsupported tag for unary '-' operator");
280} // 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