git.iko.soy/rowtype-yoga/purescript-native
on golang help sign in
C++: nicer casts
6e277f4Andy Arvanitis
pcc/include/purescript.cc+20−64
@@ -22,59 +22,6 @@ namespace PureScript {
22 assert(variant.type == TYPE); \
22 assert(variant.type == TYPE); \
23 return INDIRECTION(variant.ACCESSOR); \
23 return INDIRECTION(variant.ACCESSOR); \
24
24
25−template <typename T>
26−auto any::cast() const -> typename std::enable_if<std::is_same<T, long>::value, T>::type {
27− RETURN_VALUE(Type::Integer, i,)
28−}
29−template auto any::cast<long>() const -> long;
30−
31−template <typename T>
32−auto any::cast() const -> typename std::enable_if<std::is_same<T, double>::value, T>::type {
33− RETURN_VALUE(Type::Double, d,)
34−}
35−template auto any::cast<double>() const -> double;
36−
37−template <typename T>
38−auto any::cast() const -> typename std::enable_if<std::is_same<T, char>::value, T>::type {
39− RETURN_VALUE(Type::Character, c,)
40−}
41−template auto any::cast<char>() const -> char;
42−
43−template <typename T>
44−auto any::cast() const -> typename std::enable_if<std::is_same<T, bool>::value, T>::type {
45− RETURN_VALUE(Type::Boolean, b,)
46−}
47−template auto any::cast<bool>() const -> bool;
48−
49−template <typename T>
50−auto any::cast() const -> typename std::enable_if<std::is_same<T, string>::value, T>::type {
51− const any& variant = unthunkVariant(*this);
52− if (variant.type == Type::StringLiteral) {
53− return variant.r;
54− }
55− assert(variant.type == Type::String);
56− return variant.s->c_str();
57−}
58−template auto any::cast<string>() const -> string;
59−
60−template <typename T>
61−auto any::cast() const -> typename std::enable_if<std::is_same<T, map>::value, const T&>::type {
62− RETURN_VALUE(Type::Map, m, *)
63−}
64−template auto any::cast<any::map>() const -> const map&;
65−
66−template <typename T>
67−auto any::cast() const -> typename std::enable_if<std::is_same<T, data>::value, const T&>::type {
68− RETURN_VALUE(Type::Data, v, *)
69−}
70−template auto any::cast<any::data>() const -> const data&;
71−
72−template <typename T>
73−auto any::cast() const -> typename std::enable_if<std::is_same<T, array>::value, const T&>::type {
74− RETURN_VALUE(Type::Array, a, *)
75−}
76−template auto any::cast<any::array>() const -> const array&;
77−
78auto any::operator()(const any& arg) const -> any {
25auto any::operator()(const any& arg) const -> any {
79 const any& variant = unthunkVariant(*this);
26 const any& variant = unthunkVariant(*this);
80 if (variant.type == Type::Closure) {
27 if (variant.type == Type::Closure) {
@@ -96,31 +43,40 @@ auto any::operator()() const -> any {
96}
43}
97
44
98any::operator long() const {
45any::operator long() const {
99− return cast<long>();
46+ RETURN_VALUE(Type::Integer, i,)
100}
47}
101
48
102any::operator double() const {
49any::operator double() const {
103− return cast<double>();
50+ RETURN_VALUE(Type::Double, d,)
104}
51}
105
52
106any::operator bool() const {
53any::operator bool() const {
107− return cast<bool>();
54+ RETURN_VALUE(Type::Boolean, b,)
55+}
56+
57+any::operator char() const {
58+ RETURN_VALUE(Type::Character, c,)
108}
59}
109
60
110−any::operator string() const {
61+any::operator cstring() const {
62+ const any& variant = unthunkVariant(*this);
63+ if (variant.type == Type::StringLiteral) {
111− return cast<string>();
64+ return variant.r;
65+ }
66+ assert(variant.type == Type::String);
67+ return variant.s->c_str();
112}
68}
113
69
114any::operator const map&() const {
70any::operator const map&() const {
115− return cast<map>();
71+ RETURN_VALUE(Type::Map, m, *)
116}
72}
117
73
118any::operator const data&() const {
74any::operator const data&() const {
119− return cast<data>();
75+ RETURN_VALUE(Type::Data, v, *)
120}
76}
121
77
122any::operator const array&() const {
78any::operator const array&() const {
123− return cast<array>();
79+ RETURN_VALUE(Type::Array, a, *)
124}
80}
125
81
126auto any::extractPointer() const -> void* {
82auto any::extractPointer() const -> void* {
@@ -162,7 +118,7 @@ auto any::operator[](const size_t rhs) const -> const any& {
162auto any::operator[](const any& rhs) const -> const any& {
118auto any::operator[](const any& rhs) const -> const any& {
163 const any& variant = unthunkVariant(*this);
119 const any& variant = unthunkVariant(*this);
164 assert(variant.type == Type::Array);
120 assert(variant.type == Type::Array);
165− return (*variant.a)[rhs.cast<long>()];
121+ return (*variant.a)[cast<long>(rhs)];
166}
122}
167
123
168auto any::contains(const char key[]) const -> bool {
124auto any::contains(const char key[]) const -> bool {
@@ -207,10 +163,10 @@ auto any::contains(const char key[]) const -> bool {
207
163
208#define DEFINE_CSTR_COMPARISON_OPERATOR(op) \
164#define DEFINE_CSTR_COMPARISON_OPERATOR(op) \
209 auto operator op (const any& lhs, const char * rhs) -> bool { \
165 auto operator op (const any& lhs, const char * rhs) -> bool { \
210− return strcmp(lhs.cast<string>(), rhs) op 0; \
166+ return strcmp(cast<cstring>(lhs), rhs) op 0; \
211 } \
167 } \
212 auto operator op (const char * lhs, const any& rhs) -> bool { \
168 auto operator op (const char * lhs, const any& rhs) -> bool { \
213− return strcmp(lhs, rhs.cast<string>()) op 0; \
169+ return strcmp(lhs, cast<cstring>(rhs)) op 0; \
214 }
170 }
215
171
216#define DEFINE_COMPARISON_OPERATOR(op) \
172#define DEFINE_COMPARISON_OPERATOR(op) \
pcc/include/purescript.hh+52−58
@@ -34,34 +34,9 @@
34#include <stdexcept>
34#include <stdexcept>
35#include <iso646.h> // mostly for MS Visual Studio compiler
35#include <iso646.h> // mostly for MS Visual Studio compiler
36
36
37−#define DEFINE_OPERATOR(op, ty, rty) \
38− inline friend auto operator op (const any& lhs, ty rhs) -> rty { \
39− return lhs.cast<ty>() op rhs; \
40− } \
41− inline friend auto operator op (ty lhs, const any& rhs) -> rty { \
42− return lhs op rhs.cast<ty>(); \
43− } \
44−
45−#define DEFINE_INT_OPERATOR(op, rty) \
46− inline friend auto operator op (const any& lhs, int rhs) -> rty { \
47− return lhs.cast<long>() op (long)rhs; \
48− } \
49− inline friend auto operator op (int lhs, const any& rhs) -> rty { \
50− return (long)lhs op rhs.cast<long>(); \
51− }
52−
53−#define DECLARE_COMPARISON_OPERATOR(op) \
54− friend auto operator op (const any&, const any&) -> bool; \
55− DEFINE_OPERATOR(op, long, bool) \
56− DEFINE_OPERATOR(op, double, bool) \
57− DEFINE_OPERATOR(op, char, bool) \
58− DEFINE_INT_OPERATOR(op, bool) \
59− friend auto operator op (const any&, const char * const) -> bool; \
60− friend auto operator op (const char * const, const any&) -> bool;
61−
62namespace PureScript {
37namespace PureScript {
63
38
64−using string = const char *;
39+using cstring = const char *;
65using nullptr_t = std::nullptr_t;
40using nullptr_t = std::nullptr_t;
66
41
67// Workaround for missing C++11 version in gcc
42// Workaround for missing C++11 version in gcc
@@ -158,7 +133,7 @@ class any {
158 mutable double d;
133 mutable double d;
159 mutable char c;
134 mutable char c;
160 mutable bool b;
135 mutable bool b;
161− mutable string r;
136+ mutable cstring r;
162 mutable fn f;
137 mutable fn f;
163 mutable shared<std::string> s;
138 mutable shared<std::string> s;
164 mutable shared<map> m;
139 mutable shared<map> m;
@@ -280,35 +255,6 @@ class any {
280 destruct();
255 destruct();
281 }
256 }
282
257
283− template <typename T>
284− auto cast() const -> typename std::enable_if<std::is_same<T, long>::value, T>::type;
285−
286− template <typename T>
287− auto cast() const -> typename std::enable_if<std::is_same<T, double>::value, T>::type;
288−
289− template <typename T>
290− auto cast() const -> typename std::enable_if<std::is_same<T, char>::value, T>::type;
291−
292− template <typename T>
293− auto cast() const -> typename std::enable_if<std::is_same<T, bool>::value, T>::type;
294−
295− template <typename T>
296− auto cast() const -> typename std::enable_if<std::is_same<T, string>::value, T>::type;
297−
298− template <typename T>
299− auto cast() const -> typename std::enable_if<std::is_same<T, map>::value, const T&>::type;
300−
301− template <typename T>
302− auto cast() const -> typename std::enable_if<std::is_same<T, data>::value, const T&>::type;
303−
304− template <typename T>
305− auto cast() const -> typename std::enable_if<std::is_same<T, array>::value, const T&>::type;
306−
307− template <typename T>
308− auto cast() const -> typename std::enable_if<std::is_assignable<shared<void>,T>::value, typename T::element_type*>::type {
309− return static_cast<typename T::element_type*>(extractPointer());
310− }
311−
312 auto operator()(const any&) const -> any;
258 auto operator()(const any&) const -> any;
313 auto operator()(const as_thunk) const -> const any&;
259 auto operator()(const as_thunk) const -> const any&;
314 auto operator()() const -> any;
260 auto operator()() const -> any;
@@ -316,8 +262,8 @@ class any {
316 operator long() const;
262 operator long() const;
317 operator double() const;
263 operator double() const;
318 operator bool() const;
264 operator bool() const;
319−
265+ operator char() const;
320− operator string() const;
266+ operator cstring() const;
321 operator const map&() const;
267 operator const map&() const;
322 operator const data&() const;
268 operator const data&() const;
323 operator const array&() const;
269 operator const array&() const;
@@ -332,6 +278,31 @@ class any {
332
278
333 static auto unthunkVariant(const any&) -> const any&;
279 static auto unthunkVariant(const any&) -> const any&;
334
280
281+ #define DEFINE_OPERATOR(op, ty, rty) \
282+ inline friend auto operator op (const any& lhs, ty rhs) -> rty { \
283+ return (ty)lhs op rhs; \
284+ } \
285+ inline friend auto operator op (ty lhs, const any& rhs) -> rty { \
286+ return lhs op (ty)rhs; \
287+ } \
288+
289+ #define DEFINE_INT_OPERATOR(op, rty) \
290+ inline friend auto operator op (const any& lhs, int rhs) -> rty { \
291+ return (long)lhs op (long)rhs; \
292+ } \
293+ inline friend auto operator op (int lhs, const any& rhs) -> rty { \
294+ return (long)lhs op (long)rhs; \
295+ }
296+
297+ #define DECLARE_COMPARISON_OPERATOR(op) \
298+ friend auto operator op (const any&, const any&) -> bool; \
299+ DEFINE_OPERATOR(op, long, bool) \
300+ DEFINE_OPERATOR(op, double, bool) \
301+ DEFINE_OPERATOR(op, char, bool) \
302+ DEFINE_INT_OPERATOR(op, bool) \
303+ friend auto operator op (const any&, const char * const) -> bool; \
304+ friend auto operator op (const char * const, const any&) -> bool;
305+
335 DECLARE_COMPARISON_OPERATOR(==)
306 DECLARE_COMPARISON_OPERATOR(==)
336 DECLARE_COMPARISON_OPERATOR(!=)
307 DECLARE_COMPARISON_OPERATOR(!=)
337 DECLARE_COMPARISON_OPERATOR(<)
308 DECLARE_COMPARISON_OPERATOR(<)
@@ -378,6 +349,29 @@ class any {
378 friend auto operator-(const any&) -> any; // unary negate
349 friend auto operator-(const any&) -> any; // unary negate
379};
350};
380
351
352+template <typename T>
353+inline auto cast(const any& a) ->
354+ typename std::enable_if<std::is_arithmetic<T>::value ||
355+ std::is_same<T,cstring>::value, T>::type {
356+ return a;
357+}
358+
359+template <typename T>
360+inline auto cast(const any& a) ->
361+ typename std::enable_if<std::is_same<T, any::map>::value ||
362+ std::is_same<T, any::data>::value ||
363+ std::is_same<T, any::array>::value, const T&>::type {
364+ return a;
365+}
366+
367+template <typename T, typename = typename std::enable_if<std::is_class<T>::value>::type>
368+inline auto cast(const any& a) ->
369+ typename std::enable_if<!std::is_same<T, any::map>::value &&
370+ !std::is_same<T, any::data>::value &&
371+ !std::is_same<T, any::array>::value, T&>::type {
372+ return *static_cast<T*>(a.extractPointer());
373+}
374+
381} // namespace PureScript
375} // namespace PureScript
382
376
383#undef DEFINE_OPERATOR
377#undef DEFINE_OPERATOR
src/Language/PureScript/Pretty/Cpp.hs+1−1
@@ -229,7 +229,7 @@ literals = mkPattern' match
229 CppNumericLiteral {} -> vstr
229 CppNumericLiteral {} -> vstr
230 CppStringLiteral {} -> vstr
230 CppStringLiteral {} -> vstr
231 CppBooleanLiteral {} -> vstr
231 CppBooleanLiteral {} -> vstr
232− _ -> val' ++ ".cast" ++ angles (runType typ) ++ parens []
232+ _ -> "cast" ++ angles (runType typ) ++ parens val'
233 where
233 where
234 vstr = prettyPrintCpp1 val
234 vstr = prettyPrintCpp1 val
235 val' | '(' `elem` vstr || '[' `elem` vstr = parens vstr
235 val' | '(' `elem` vstr || '[' `elem` vstr = parens vstr