1///////////////////////////////////////////////////////////////////////////////
3// Module : purescript.hh
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///////////////////////////////////////////////////////////////////////////////
35#include <iso646.h> // mostly for MS Visual Studio compiler
39using cstring = const char *;
40using nullptr_t = std::nullptr_t;
42// Workaround for missing C++11 version in gcc
43class runtime_error : public std::runtime_error {
45 runtime_error(const char message[]) : std::runtime_error(std::string(message)) {}
48const bool undefined = false;
49const size_t constructor = 0;
51// A variant data class designed to provide some features of dynamic typing.
81 static constexpr as_thunk unthunk = as_thunk{};
83 using map = std::vector<std::pair<const char * const, const any>>;
84 using data = std::vector<any>;
85 using array = std::deque<any>;
86 using fn = auto (*)(const any&) -> any;
87 using eff_fn = auto (*)() -> any;
88 using thunk = auto (*)(const as_thunk) -> const any&;
93 virtual auto operator()(const any&) const -> any = 0;
98 class _closure : public closure {
101 _closure(const T& l) noexcept : lambda(l) {}
102 auto operator()(const any& arg) const -> any {
109 virtual auto operator()() const -> any = 0;
112 template <typename T>
113 class _eff_closure : public eff_closure {
116 _eff_closure(const T& l) noexcept : lambda(l) {}
117 auto operator()() const -> any {
123 template <typename T>
124 using shared = std::shared_ptr<T>;
126 template <typename T, typename... Args>
127 inline static auto make_shared(Args&&... args) -> decltype(std::make_shared<T>(std::forward<Args>(args)...)) {
128 return std::make_shared<T>(std::forward<Args>(args)...);
141 mutable shared<std::string> s;
142 mutable shared<map> m;
143 mutable shared<data> v;
144 mutable shared<array> a;
145 mutable shared<closure> l;
146 mutable shared<eff_closure> el;
147 mutable shared<void> p;
152 any(const long val) noexcept : type(Type::Integer), i(val) {}
153 any(const int val) noexcept : type(Type::Integer), i(val) {}
154 any(const unsigned int val) noexcept : type(Type::Integer), i(val) {}
155 any(const double val) noexcept : type(Type::Double), d(val) {}
156 any(const char val) noexcept : type(Type::Character), c(val) {}
158 template <typename T, typename = typename std::enable_if<std::is_same<bool,T>::value>::type>
159 any(const T val) noexcept : type(Type::Boolean), b(val) {}
162 any(const char (&val)[N]) noexcept : type(Type::StringLiteral), r(val) {}
163 any(char * val) : type(Type::String), s(make_shared<std::string>(val)) {}
165 any(const std::string& val) : type(Type::String), s(make_shared<std::string>(val)) {}
166 any(std::string&& val) noexcept : type(Type::String), s(make_shared<std::string>(std::move(val))) {}
168 any(const shared<std::string>& val) noexcept : type(Type::String), s(val) {}
169 any(shared<std::string>&& val) noexcept : type(Type::String), s(std::move(val)) {}
171 any(const map& val) : type(Type::Map), m(make_shared<map>(val)) {}
172 any(map&& val) noexcept : type(Type::Map), m(make_shared<map>(std::move(val))) {}
174 any(const data& val) : type(Type::Data), v(make_shared<data>(val)) {}
175 any(data&& val) noexcept : type(Type::Data), v(make_shared<data>(std::move(val))) {}
177 any(const array& val) : type(Type::Array), a(make_shared<array>(val)) {}
178 any(array&& val) noexcept : type(Type::Array), a(make_shared<array>(std::move(val))) {}
180 template <typename T>
181 any(const T& val, typename std::enable_if<std::is_convertible<T,fn>::value>::type* = 0) noexcept
182 : type(Type::Function), f(val) {}
184 template <typename T, typename = typename std::enable_if<!std::is_same<any,T>::value &&
185 !std::is_convertible<T,fn>::value>::type>
186 any(const T& val, typename std::enable_if<std::is_assignable<std::function<any(const any&)>,T>::value>::type* = 0)
187 : type(Type::Closure), l(make_shared<_closure<T>>(val)) {}
189 template <typename T>
190 any(const T& val, typename std::enable_if<std::is_convertible<T,eff_fn>::value>::type* = 0) noexcept
191 : type(Type::EffFunction), e(val) {}
193 template <typename T,
194 typename = typename std::enable_if<!std::is_same<any,T>::value &&
195 !std::is_convertible<T,eff_fn>::value>::type>
196 any(const T& val, typename std::enable_if<std::is_assignable<std::function<any()>,T>::value>::type* = 0)
197 : type(Type::EffClosure), el(make_shared<_eff_closure<T>>(val)) {}
199 template <typename T>
200 any(const T& val, typename std::enable_if<std::is_convertible<T,thunk>::value>::type* = 0) noexcept
201 : type(Type::Thunk), t(val) {}
203 template <typename T>
204 any(const T& val, typename std::enable_if<std::is_assignable<shared<void>,T>::value>::type* = 0) noexcept
205 : type(Type::Pointer), p(val) {}
207 template <typename T>
208 any(T&& val, typename std::enable_if<std::is_assignable<shared<void>,T>::value>::type* = 0) noexcept
209 : type(Type::Pointer), p(std::move(val)) {}
211 any(std::nullptr_t) noexcept : type(Type::Pointer), p(nullptr) {}
215 auto copy(const any& other) const noexcept -> void {
216 if (type & Type::Shared) {
217 new (&p) shared<void>(other.p);
223 auto move(any&& other) const noexcept -> void {
224 if (type & Type::Shared) {
225 new (&p) shared<void>(std::move(other.p));
231 auto destruct() -> void {
232 if (type & Type::Shared) {
239 any(const any& other) noexcept : type(other.type) {
243 any(any&& other) noexcept : type(other.type) {
244 move(std::move(other));
247 auto operator=(const any& rhs) noexcept -> any& {
254 auto operator=(any&& rhs) noexcept -> any& {
257 move(std::move(rhs));
267 auto operator()(const any&) const -> any;
268 auto operator()(const as_thunk) const -> const any&;
269 auto operator()() const -> any;
271 operator long() const;
272 operator double() const;
273 operator bool() const;
274 operator char() const;
275 operator cstring() const;
276 operator const map&() const;
277 operator const data&() const;
278 operator const array&() const;
280 auto operator[](const char[]) const -> const any&;
281 auto operator[](const size_t) const -> const any&;
282 auto operator[](const any&) const -> const any&;
284 auto contains(const char[]) const -> bool;
286 auto extractPointer() const -> void*;
288 static auto unthunkVariant(const any&) -> const any&;
290 #define DEFINE_OPERATOR(op, ty, rty) \
291 inline friend auto operator op (const any& lhs, ty rhs) -> rty { \
292 return (ty)lhs op rhs; \
294 inline friend auto operator op (ty lhs, const any& rhs) -> rty { \
295 return lhs op (ty)rhs; \
298 #define DEFINE_INT_OPERATOR(op, rty) \
299 inline friend auto operator op (const any& lhs, int rhs) -> rty { \
300 return (long)lhs op (long)rhs; \
302 inline friend auto operator op (int lhs, const any& rhs) -> rty { \
303 return (long)lhs op (long)rhs; \
306 #define DECLARE_COMPARISON_OPERATOR(op) \
307 friend auto operator op (const any&, const any&) -> bool; \
308 DEFINE_OPERATOR(op, long, bool) \
309 DEFINE_OPERATOR(op, double, bool) \
310 DEFINE_OPERATOR(op, char, bool) \
311 DEFINE_INT_OPERATOR(op, bool) \
312 friend auto operator op (const any&, const char * const) -> bool; \
313 friend auto operator op (const char * const, const any&) -> bool;
315 DECLARE_COMPARISON_OPERATOR(==)
316 DECLARE_COMPARISON_OPERATOR(!=)
317 DECLARE_COMPARISON_OPERATOR(<)
318 DECLARE_COMPARISON_OPERATOR(<=)
319 DECLARE_COMPARISON_OPERATOR(>)
320 DECLARE_COMPARISON_OPERATOR(>=)
322 friend auto operator+(const any&, const any&) -> any;
324 DEFINE_OPERATOR(+, long, long)
325 DEFINE_OPERATOR(+, double, double)
326 DEFINE_OPERATOR(+, char, char)
327 DEFINE_INT_OPERATOR(+, long)
328 friend auto operator+(const any& lhs, const char * const rhs) -> std::string;
329 friend auto operator+(const char * const lhs, const any& rhs) -> std::string;
331 friend auto operator-(const any&, const any&) -> any;
333 DEFINE_OPERATOR(-, long, long)
334 DEFINE_OPERATOR(-, double, double)
335 DEFINE_OPERATOR(-, char, char)
336 DEFINE_INT_OPERATOR(-, long)
338 friend auto operator*(const any&, const any&) -> any;
340 DEFINE_OPERATOR(*, long, long)
341 DEFINE_OPERATOR(*, double, double)
342 DEFINE_OPERATOR(*, char, char)
343 DEFINE_INT_OPERATOR(*, long)
345 friend auto operator/(const any&, const any&) -> any;
347 DEFINE_OPERATOR(/, long, long)
348 DEFINE_OPERATOR(/, double, double)
349 DEFINE_OPERATOR(/, char, char)
350 DEFINE_INT_OPERATOR(/, long)
352 friend auto operator%(const any&, const any&) -> any;
354 DEFINE_OPERATOR(%, long, long)
355 DEFINE_OPERATOR(%, char, char)
356 DEFINE_INT_OPERATOR(%, long)
358 friend auto operator-(const any&) -> any; // unary negate
362inline auto cast(const any& a) ->
363 typename std::enable_if<std::is_arithmetic<T>::value ||
364 std::is_same<T,cstring>::value, T>::type {
369inline auto cast(const any& a) ->
370 typename std::enable_if<std::is_same<T, any::map>::value ||
371 std::is_same<T, any::data>::value ||
372 std::is_same<T, any::array>::value, const T&>::type {
376template <typename T, typename = typename std::enable_if<std::is_class<T>::value>::type>
377inline auto cast(const any& a) ->
378 typename std::enable_if<!std::is_same<T, any::map>::value &&
379 !std::is_same<T, any::data>::value &&
380 !std::is_same<T, any::array>::value, T&>::type {
381 return *static_cast<T*>(a.extractPointer());
384} // namespace PureScript
386#undef DEFINE_OPERATOR
387#undef DEFINE_INT_OPERATOR
388#undef DECLARE_COMPARISON_OPERATOR
390#endif // PureScript_HH
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