git.iko.soy/rowtype-yoga/purescript-native
on cdc44ab help sign in
308 lines 9.2 kB history raw
1///////////////////////////////////////////////////////////////////////////////
2//
3// Module : purescript.hh
4// Copyright : (c) Andy Arvanitis 2015
5// License : MIT
6//
7// Maintainer : Andy Arvanitis <andy.arvanitis@gmail.com>
8// Stability : experimental
9// Portability :
10//
11// Basic types and functions to support purescript-to-C++1x rendering
12//
13///////////////////////////////////////////////////////////////////////////////
14//
15#ifndef PureScript_HH
16#define PureScript_HH
18// Standard includes
20#if defined(DEBUG)
21 #include <cassert>
22#else
23 #define NDEBUG
24 #undef assert
25 #define assert(x)
26#endif
28#include <memory>
29#include <functional>
30#include <string>
31#include <vector>
32#include <utility>
33#include <stdexcept>
35#define DECLARE_OPERATOR(op, ty, rty) \
36 friend auto operator op (const any&, ty) -> rty; \
37 friend auto operator op (ty, const any&) -> rty;
39#define DECLARE_COMPARISON_OPERATOR(op) \
40 friend auto operator op (const any&, const any&) -> bool; \
41 DECLARE_OPERATOR(op, long, bool) \
42 DECLARE_OPERATOR(op, double, bool) \
43 DECLARE_OPERATOR(op, char, bool) \
44 DECLARE_OPERATOR(op, const char *, bool)
47namespace PureScript {
49using string = const char *;
50using nullptr_t = std::nullptr_t;
52// Workaround for missing C++11 version in gcc
53class runtime_error : public std::runtime_error {
54public:
55 runtime_error(const char message[]) : std::runtime_error(std::string(message)) {}
56};
58const bool undefined = false;
59const std::vector<int>::size_type kDataCtor = 0;
61// A variant data class designed to provide some features of dynamic typing.
62//
63class any {
65 public:
66 enum class Type : int8_t {
67 Unknown,
68 Integer,
69 Double,
70 Character,
71 Boolean,
72 StringLiteral,
73 String,
74 Map,
75 Vector,
76 Function,
77 Closure,
78 EffFunction,
79 Thunk,
80 Pointer
81 };
83 mutable Type type = Type::Unknown;
85 struct as_thunk {
86 };
87 static constexpr as_thunk unthunk = as_thunk{};
89 using map = std::vector<std::pair<const char * const, const any>>;
90 using vector = std::vector<any>;
91 using fn = auto (*)(const any&) -> any;
92 using thunk = auto (*)(const as_thunk) -> const any&;
94 class closure {
95 public:
96 virtual auto operator()(const any&) const -> any = 0;
97 };
99 template <typename T>
100 class _closure : public closure {
101 const T lambda;
102 public:
103 _closure(const T& l) noexcept : lambda(l) {}
104 auto operator()(const any& arg) const -> any {
105 return lambda(arg);
106 }
107 };
109 class eff_fn {
110 public:
111 virtual auto operator()() const -> any = 0;
112 };
114 template <typename T>
115 class _eff_fn : public eff_fn {
116 const T lambda;
117 public:
118 _eff_fn(const T& l) noexcept : lambda(l) {}
119 auto operator()() const -> any {
120 return lambda();
121 }
122 };
124 template <typename T>
125 using shared = std::shared_ptr<T>;
127 template <typename T, typename... Args>
128 inline static auto make_shared(Args&&... args) -> decltype(std::make_shared<T>(std::forward<Args>(args)...)) {
129 return std::make_shared<T>(std::forward<Args>(args)...);
130 }
132 private:
133 union {
134 mutable long i;
135 mutable double d;
136 mutable char c;
137 mutable bool b;
138 mutable string r;
139 mutable shared<std::string> s;
140 mutable shared<map> m;
141 mutable shared<vector> v;
142 mutable fn f;
143 mutable shared<closure> l;
144 mutable shared<eff_fn> e;
145 mutable thunk t;
146 mutable shared<void> p;
147 };
149 public:
151 any(const long val) : type(Type::Integer), i(val) {}
152 any(const int val) : type(Type::Integer), i(val) {}
153 any(const unsigned int val) : type(Type::Integer), i(val) {}
154 any(const double val) : type(Type::Double), d(val) {}
155 any(const char val) : type(Type::Character), c(val) {}
157 template <typename T, typename = typename std::enable_if<std::is_same<bool,T>::value>::type>
158 any(const T val) : type(Type::Boolean), b(val) {}
160 template <size_t N>
161 any(const char (&val)[N]) : type(Type::StringLiteral), r(val) {}
162 any(char * val) : type(Type::String), s(make_shared<std::string>(val)) {}
164 any(const std::string& val) : type(Type::String), s(make_shared<std::string>(val)) {}
165 any(std::string&& val) : type(Type::String), s(make_shared<std::string>(std::move(val))) {}
167 any(const shared<std::string>& val) : type(Type::String), s(val) {}
168 any(shared<std::string>&& val) noexcept : type(Type::String), s(std::move(val)) {}
170 any(const map& val) : type(Type::Map), m(make_shared<map>(val)) {}
171 any(map&& val) noexcept : type(Type::Map), m(make_shared<map>(std::move(val))) {}
173 any(const vector& val) : type(Type::Vector), v(make_shared<vector>(val)) {}
174 any(vector&& val) noexcept : type(Type::Vector), v(make_shared<vector>(std::move(val))) {}
176 template <typename T>
177 any(const T& val, typename std::enable_if<std::is_convertible<T,fn>::value>::type* = 0)
178 : type(Type::Function), f(val) {}
180 template <typename T, typename = typename std::enable_if<!std::is_same<any,T>::value &&
181 !std::is_convertible<T,fn>::value>::type>
182 any(const T& val, typename std::enable_if<std::is_assignable<std::function<any(const any&)>,T>::value>::type* = 0)
183 : type(Type::Closure), l(make_shared<_closure<T>>(val)) {}
185 template <typename T>
186 any(const T& val, typename std::enable_if<std::is_assignable<std::function<any()>,T>::value>::type* = 0)
187 : type(Type::EffFunction), e(make_shared<_eff_fn<T>>(val)) {}
189 template <typename T>
190 any(const T& val, typename std::enable_if<std::is_convertible<T,thunk>::value>::type* = 0)
191 : type(Type::Thunk), t(val) {}
193 template <typename T>
194 any(const T& val, typename std::enable_if<std::is_assignable<shared<void>,T>::value>::type* = 0)
195 : type(Type::Pointer), p(val) {}
197 template <typename T>
198 any(T&& val, typename std::enable_if<std::is_assignable<shared<void>,T>::value>::type* = 0) noexcept
199 : type(Type::Pointer), p(std::move(val)) {}
201 any(std::nullptr_t) : type(Type::Pointer), p(nullptr) {}
203 any(const any&);
204 any(any&&) noexcept;
206 auto operator=(const any&) -> any&;
207 auto operator=(any&) noexcept -> any&;
208 auto operator=(any&&) noexcept -> any&;
210 any() = delete;
211 ~any();
213 template <typename T>
214 auto cast() const -> typename std::enable_if<std::is_same<T, long>::value, T>::type;
216 template <typename T>
217 auto cast() const -> typename std::enable_if<std::is_same<T, double>::value, T>::type;
219 template <typename T>
220 auto cast() const -> typename std::enable_if<std::is_same<T, char>::value, T>::type;
222 template <typename T>
223 auto cast() const -> typename std::enable_if<std::is_same<T, bool>::value, T>::type;
225 template <typename T>
226 auto cast() const -> typename std::enable_if<std::is_same<T, string>::value, T>::type;
228 template <typename T>
229 auto cast() const -> typename std::enable_if<std::is_same<T, map>::value, const T&>::type;
231 template <typename T>
232 auto cast() const -> typename std::enable_if<std::is_same<T, vector>::value, const T&>::type;
234 template <typename T>
235 auto cast() const -> typename std::enable_if<std::is_assignable<shared<void>,T>::value, typename T::element_type*>::type {
236 return static_cast<typename T::element_type*>(extractPointer());
237 }
239 auto operator()(const any&) const -> any;
241 auto operator()(const as_thunk) const -> const any&;
243 auto operator()() const -> any;
245 operator long() const;
246 operator double() const;
247 operator bool() const;
249 operator string() const;
250 operator const map&() const;
251 operator const vector&() const;
253 auto operator[](const char[]) const -> const any&;
254 auto operator[](const vector::size_type) const -> const any&;
255 auto operator[](const any&) const -> const any&;
257 auto contains(const char[]) const -> bool;
259 auto extractPointer() const -> void*;
261 static auto unthunkVariant(const any&) -> const any&;
263 DECLARE_COMPARISON_OPERATOR(==)
264 DECLARE_COMPARISON_OPERATOR(!=)
265 DECLARE_COMPARISON_OPERATOR(<)
266 DECLARE_COMPARISON_OPERATOR(<=)
267 DECLARE_COMPARISON_OPERATOR(>)
268 DECLARE_COMPARISON_OPERATOR(>=)
270 friend auto operator+(const any&, const any&) -> any;
272 DECLARE_OPERATOR(+, long, long)
273 DECLARE_OPERATOR(+, double, double)
274 DECLARE_OPERATOR(+, char, char)
275 DECLARE_OPERATOR(+, const char *, std::string)
277 friend auto operator-(const any&, const any&) -> any;
279 DECLARE_OPERATOR(-, long, long)
280 DECLARE_OPERATOR(-, double, double)
281 DECLARE_OPERATOR(-, char, char)
283 friend auto operator*(const any&, const any&) -> any;
285 DECLARE_OPERATOR(*, long, long)
286 DECLARE_OPERATOR(*, double, double)
287 DECLARE_OPERATOR(*, char, char)
289 friend auto operator/(const any&, const any&) -> any;
291 DECLARE_OPERATOR(/, long, long)
292 DECLARE_OPERATOR(/, double, double)
293 DECLARE_OPERATOR(/, char, char)
295 friend auto operator%(const any&, const any&) -> any;
297 DECLARE_OPERATOR(%, long, long)
298 DECLARE_OPERATOR(%, char, char)
300 friend auto operator-(const any&) -> any; // unary negate
301};
303} // namespace PureScript
305#undef DECLARE_OPERATOR
306#undef DECLARE_COMPARISON_OPERATOR
308#endif // PureScript_HH