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 (*static_cast<const Closure*>(POINTER_FROM_MEMBER(variant.p)))(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 (*static_cast<const EffClosure*>(POINTER_FROM_MEMBER(variant.p)))();
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 = static_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 val = static_cast<decltype(i)>(*this);
76 return static_cast<size_t>(val);
79any::operator const string&() const {
80 return *static_cast<const string*>(extractPointer(IF_DEBUG(Tag::String)));
83any::operator const char *() const {
84 return static_cast<const string*>(extractPointer(IF_DEBUG(Tag::String)))->c_str();
87any::operator const array&() const {
88 return *static_cast<const array*>(extractPointer(IF_DEBUG(Tag::Array)));
91any::operator const record&() const {
92 return *static_cast<const record*>(extractPointer(IF_DEBUG(Tag::Record)));
95auto any::extractPointer(IF_DEBUG(const any::Tag t)) const -> void* {
96 RETURN_VALUE(t, POINTER_FROM_MEMBER(p),)
99auto any::unthunkVariant(const any& a) -> const any& {
100 const any * variant = &a;
101 while (variant->tag == Tag::Thunk) {
102 variant = &((*variant->t)(unthunk));
107auto any::operator[](const int rhs) const -> const any& {
109 const auto& xs = static_cast<const array&>(*this);
113auto any::size() const -> size_t {
114 return static_cast<const array&>(*this).size();
117auto any::empty() const -> bool {
118 return static_cast<const array&>(*this).empty();
121auto any::contains(const Private::Symbol key) const -> bool {
122 // TODO: assumes at least one element -- safe assumption?
124 *static_cast<const any::dict<unknown_size>*>(this->extractPointer(IF_DEBUG(any::Tag::Dictionary)));
125 std::remove_reference<decltype(m)>::type::size_type i = 0;
127 if (m[i].first == key) {
130 } while (m[++i].first != nullptr);
134auto any::cstr_cmp::operator ()(const char * a, const char * b) const -> bool {
135 return a == b ? false : std::strcmp(a, b) < 0;
138auto any::at(const char * key) const -> const any& {
139 return static_cast<const record&>(*this).at(key);
142//-----------------------------------------------------------------------------
143// Operator helper macros
144//-----------------------------------------------------------------------------
146#define DEFINE_COMPARISON_OPERATOR(op) \
147 auto operator op (const any& lhs_, const any& rhs) -> bool { \
148 const any& lhs = any::unthunkVariant(lhs_); \
150 case any::Tag::Integer: return lhs.i op static_cast<decltype(any::i)>(rhs); \
151 case any::Tag::Double: return lhs.d op static_cast<decltype(any::d)>(rhs); \
152 case any::Tag::Character: return lhs.c op static_cast<decltype(any::c)>(rhs); \
153 case any::Tag::Boolean: return lhs.b op static_cast<decltype(any::b)>(rhs); \
154 case any::Tag::String: return *static_cast<const string*>(POINTER_FROM_MEMBER(lhs.p)) \
155 op static_cast<const string&>(rhs); \
156 case any::Tag::RawPointer: return lhs.v op static_cast<decltype(any::v)>(rhs); \
157 case any::Tag::Pointer: return lhs.p op any::unthunkVariant(rhs).p; \
158 default: assert(false && "Unsupported tag for operator " #op); \
163//-----------------------------------------------------------------------------
164// Operator definitions
165//-----------------------------------------------------------------------------
167DEFINE_COMPARISON_OPERATOR(==)
168DEFINE_COMPARISON_OPERATOR(!=)
169DEFINE_COMPARISON_OPERATOR(<)
170DEFINE_COMPARISON_OPERATOR(<=)
171DEFINE_COMPARISON_OPERATOR(>)
172DEFINE_COMPARISON_OPERATOR(>=)
174auto operator+(const any& lhs_, const any& rhs) -> any {
175 const any& lhs = any::unthunkVariant(lhs_);
177 case any::Tag::Integer: return lhs.i + static_cast<decltype(any::i)>(rhs);
178 case any::Tag::Double: return lhs.d + static_cast<decltype(any::d)>(rhs);
179 case any::Tag::Character: return decltype(any::c){lhs.c + static_cast<decltype(any::c)>(rhs)};
180 case any::Tag::String: return *static_cast<const string*>(POINTER_FROM_MEMBER(lhs.p))
181 + static_cast<const string&>(rhs);
182 default: assert(false && "Unsupported tag for '+' operator");
187auto operator-(const any& lhs_, const any& rhs) -> any {
188 const any& lhs = any::unthunkVariant(lhs_);
190 case any::Tag::Integer: return lhs.i - static_cast<decltype(any::i)>(rhs);
191 case any::Tag::Double: return lhs.d - static_cast<decltype(any::d)>(rhs);
192 case any::Tag::Character: return decltype(any::c){lhs.c - static_cast<decltype(any::c)>(rhs)};
193 default: assert(false && "Unsupported tag for '-' operator");
198auto operator*(const any& lhs_, const any& rhs) -> any {
199 const any& lhs = any::unthunkVariant(lhs_);
201 case any::Tag::Integer: return lhs.i * static_cast<decltype(any::i)>(rhs);
202 case any::Tag::Double: return lhs.d * static_cast<decltype(any::d)>(rhs);
203 case any::Tag::Character: return decltype(lhs.c){lhs.c - static_cast<decltype(any::c)>(rhs)};
204 default: assert(false && "Unsupported tag for '*' operator");
209auto operator/(const any& lhs_, const any& rhs) -> any {
210 const any& lhs = any::unthunkVariant(lhs_);
212 case any::Tag::Integer: return lhs.i / static_cast<decltype(any::i)>(rhs);
213 case any::Tag::Double: return lhs.d / static_cast<decltype(any::d)>(rhs);
214 case any::Tag::Character: return decltype(any::c){lhs.c / static_cast<decltype(any::c)>(rhs)};
215 default: assert(false && "Unsupported tag for '/' operator");
220auto operator%(const any& lhs_, const any& rhs) -> any {
221 const any& lhs = any::unthunkVariant(lhs_);
223 case any::Tag::Integer: return lhs.i % static_cast<decltype(any::i)>(rhs);
224 case any::Tag::Character: return decltype(any::c){lhs.c % static_cast<decltype(any::c)>(rhs)};
225 default: assert(false && "Unsupported tag for '%' operator");
231auto operator-(const any& rhs_) -> any {
232 const any& rhs = any::unthunkVariant(rhs_);
234 case any::Tag::Integer: return (- rhs.i);
235 case any::Tag::Double: return (- rhs.d);
236 default: assert(false && "Unsupported tag for unary '-' operator");
241} // 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