git.iko.soy/rowtype-yoga/purescript-native
on golang help sign in
Merge remote-tracking branch 'origin/pure11' into pure11-0.8
800e33cAndy Arvanitis
pcc/Make.hs−1
@@ -122,7 +122,6 @@ buildMakeActions outputDir filePathMap usePrefix =
122 writeTextFile (outputDir </> "CMakeLists.txt") (fromString cmakeListsTxt)
122 writeTextFile (outputDir </> "CMakeLists.txt") (fromString cmakeListsTxt)
123 writeTextFile (supportDir </> "PureScript.hh") $ B.unpack $(embedFile "pcc/include/purescript.hh")
123 writeTextFile (supportDir </> "PureScript.hh") $ B.unpack $(embedFile "pcc/include/purescript.hh")
124 writeTextFile (supportDir </> "PureScript.cc") $ B.unpack $(embedFile "pcc/include/purescript.cc")
124 writeTextFile (supportDir </> "PureScript.cc") $ B.unpack $(embedFile "pcc/include/purescript.cc")
125− writeTextFile (supportDir </> "map_key.hh") $ B.unpack $(embedFile "pcc/include/map_key.hh")
126
125
127 let inputPath = dropExtension $ getInputFile mn
126 let inputPath = dropExtension $ getInputFile mn
128 hfile = addExtension inputPath "hh"
127 hfile = addExtension inputPath "hh"
pcc/include/map_key.hhdeleted−56
@@ -1,56 +0,0 @@
1−///////////////////////////////////////////////////////////////////////////////
2−//
3−// Module : map_key.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−// Support for maps using keys with compile-time hashes.
12−//
13−///////////////////////////////////////////////////////////////////////////////
14−//
15−#ifndef PS_MapKey_HH
16−#define PS_MapKey_HH
17−
18−#include <cstring>
19−
20−namespace PureScript {
21−
22− struct map_key_t {
23−
24− const uint64_t hash;
25− const char * const cstr;
26−
27− // Compile-time (fnv-1a) hash function
28− static constexpr auto fnv1a(const char s[], const uint64_t hash = 14695981039346656037UL) -> uint64_t {
29− return !s[0] ? hash : fnv1a(s + 1, (hash ^ static_cast<unsigned char>(s[0])) * 1099511628211UL);
30− }
31−
32− class hasher {
33− public:
34− auto operator() (const map_key_t& key) const -> size_t {
35− return key.hash;
36− }
37− };
38−
39− class equal {
40− public:
41− auto operator() (const map_key_t& key1, const map_key_t& key2) const -> bool {
42− return (key1.cstr == key2.cstr) || strcmp(key1.cstr, key2.cstr) == 0;
43− }
44− };
45− };
46−
47− template <uint64_t H>
48− constexpr auto make_map_key(const char s[]) -> const map_key_t {
49− return map_key_t{H, s};
50− }
51−
52− #define KEY(k) make_map_key<map_key_t::fnv1a(k)>(k)
53−
54−} // namespace PureScript
55−
56−#endif // PS_MapKey_HH
pcc/include/purescript.cc+338−416
@@ -12,517 +12,439 @@
12//
12//
13///////////////////////////////////////////////////////////////////////////////
13///////////////////////////////////////////////////////////////////////////////
14//
14//
15+#include <cstring>
15#include "PureScript.hh"
16#include "PureScript.hh"
16
17
17namespace PureScript {
18namespace PureScript {
18
19
20+#define COPY_DATA(src) \
21+ switch (type) { \
22+ case Type::Integer: i = src.i; break; \
23+ case Type::Double: d = src.d; break; \
24+ case Type::Character: c = src.c; break; \
25+ case Type::Boolean: b = src.b; break; \
26+ case Type::StringLiteral: r = src.r; break; \
27+ case Type::String: new (&s) shared<std::string>(src.s); break; \
28+ case Type::Map: new (&m) shared<map>(src.m); break; \
29+ case Type::Vector: new (&v) shared<vector>(src.v); break; \
30+ case Type::Function: f = src.f; break; \
31+ case Type::Closure: new (&l) shared<closure>(src.l); break; \
32+ case Type::EffFunction: new (&e) shared<eff_fn>(src.e); break; \
33+ case Type::Thunk: t = src.t; break; \
34+ case Type::Pointer: new (&p) shared<void>(src.p); break; \
35+ \
36+ default: assert(false && "Unsupported type in copy"); \
37+ }
38+
39+#define MOVE_DATA(src) \
40+ switch (type) { \
41+ case Type::Integer: i = src.i; break; \
42+ case Type::Double: d = src.d; break; \
43+ case Type::Character: c = src.c; break; \
44+ case Type::Boolean: b = src.b; break; \
45+ case Type::StringLiteral: r = src.r; break; \
46+ case Type::String: new (&s) shared<std::string>(std::move(src.s)); break; \
47+ case Type::Map: new (&m) shared<map>(std::move(src.m)); break; \
48+ case Type::Vector: new (&v) shared<vector>(std::move(src.v)); break; \
49+ case Type::Function: f = src.f; break; \
50+ case Type::Closure: new (&l) shared<closure>(std::move(src.l)); break; \
51+ case Type::EffFunction: new (&e) shared<eff_fn>(std::move(src.e)); break; \
52+ case Type::Thunk: t = src.t; break; \
53+ case Type::Pointer: new (&p) shared<void>(std::move(src.p)); break; \
54+ \
55+ default: assert(false && "Unsupported type in move"); \
56+ }
57+
19−any::any(const any& val) : type(val.type) {
58+any::any(const any& other) : type(other.type) {
20− switch (type) {
59+ COPY_DATA(other);
21− case Type::Integer: i = val.i; break;
22− case Type::Double: d = val.d; break;
23− case Type::Character: c = val.c; break;
24− case Type::Boolean: b = val.b; break;
25− case Type::String: new (&s) shared<string> (val.s); break;
26− case Type::Map: new (&m) shared<map> (val.m); break;
27− case Type::Vector: new (&v) shared<vector> (val.v); break;
28− case Type::Function: new (&f) shared<fn> (val.f); break;
29− case Type::EffFunction: new (&e) shared<eff_fn> (val.e); break;
30− case Type::Thunk: new (&t) shared<thunk> (val.t); break;
31− case Type::Pointer: new (&p) shared<void> (val.p); break;
32−
33− default: assert(false && "Unsupported type in copy ctor");
34− }
35}
60}
36
61
37−void any::swap(any&& val) const {
62+any::any(any&& other) noexcept : type(other.type) {
63+ MOVE_DATA(other);
64+}
65+
66+auto any::operator=(const any& rhs) -> any& {
38− type = val.type;
67+ type = rhs.type;
39− switch (type) {
68+ COPY_DATA(rhs);
40− case Type::Integer: i = val.i; break;
69+ return *this;
41− case Type::Double: d = val.d; break;
70+}
42− case Type::Character: c = val.c; break;
71+
43− case Type::Boolean: b = val.b; break;
72+// Takes ownership -- might need to reconsider this
44− case Type::String: new (&s) shared<string> (std::move(val.s)); break;
73+auto any::operator=(any& rhs) noexcept -> any& {
45− case Type::Map: new (&m) shared<map> (std::move(val.m)); break;
74+ type = rhs.type;
46− case Type::Vector: new (&v) shared<vector> (std::move(val.v)); break;
75+ MOVE_DATA(rhs);
47− case Type::Function: new (&f) shared<fn> (std::move(val.f)); break;
76+ return *this;
48− case Type::EffFunction: new (&e) shared<eff_fn> (std::move(val.e)); break;
77+}
49− case Type::Thunk: new (&t) shared<thunk> (std::move(val.t)); break;
78+
50− case Type::Pointer: new (&p) shared<void> (std::move(val.p)); break;
79+auto any::operator=(any&& rhs) noexcept -> any& {
51−
80+ type = rhs.type;
52− default: assert(false && "Unsupported type in move ctor");
81+ MOVE_DATA(rhs);
53− }
82+ return *this;
54}
83}
55
84
56any::~any() {
85any::~any() {
57− // std::cout << "destroy" << std::endl;
58 switch (type) {
86 switch (type) {
59− case Type::Integer: ; break;
87+ case Type::Integer: ; break;
60− case Type::Double: ; break;
88+ case Type::Double: ; break;
61− case Type::Character: ; break;
89+ case Type::Character: ; break;
62− case Type::Boolean: ; break;
90+ case Type::Boolean: ; break;
91+ case Type::StringLiteral: ; break;
63− case Type::String: s.~shared<string>(); break;
92+ case Type::String: s.~shared<std::string>(); break;
64− case Type::Map: m.~shared<map>(); break;
93+ case Type::Map: m.~shared<map>(); break;
65− case Type::Vector: v.~shared<vector>(); break;
94+ case Type::Vector: v.~shared<vector>(); break;
66− case Type::Function: f.~shared<fn>(); break;
95+ case Type::Function: ; break;
96+ case Type::Closure: l.~shared<closure>(); break;
67− case Type::EffFunction: e.~shared<eff_fn>(); break;
97+ case Type::EffFunction: e.~shared<eff_fn>(); break;
68− case Type::Thunk: t.~shared<thunk>(); break;
98+ case Type::Thunk: ; break;
69− case Type::Pointer: p.~shared<void>(); break;
99+ case Type::Pointer: p.~shared<void>(); break;
70
100
71 default: assert(false && "Unsupported type in destructor");
101 default: assert(false && "Unsupported type in destructor");
72 }
102 }
73};
103};
74
104
75− #define RETURN_VALUE(TYPE, VAL, FN) \
105+#define RETURN_VALUE(TYPE, ACCESSOR, INDIRECTION) \
76− if (type == TYPE) { \
106+ const any& variant = unthunkVariant(*this); \
77− return FN(VAL); \
78− } \
79− const any* valuePtr = this; \
80− do { \
81− assert(valuePtr->type == Type::Thunk); \
82− const any& value = (*valuePtr->t)(unthunk); \
83− if (value.type == TYPE) { \
107+ assert(variant.type == TYPE); \
84− return FN(value.VAL); \
108+ return INDIRECTION(variant.ACCESSOR); \
85− } \
86− valuePtr = &value; \
87− } while (valuePtr->type != Type::Unknown); \
88− return FN(VAL);
89−
90− template <typename T>
91− auto any::cast() const -> typename std::enable_if<std::is_same<T, long>::value, T>::type {
92− RETURN_VALUE(Type::Integer, i,)
93− }
94− template auto any::cast<long>() const -> long;
95−
96− template <typename T>
97− auto any::cast() const -> typename std::enable_if<std::is_same<T, double>::value, T>::type {
98− RETURN_VALUE(Type::Double, d,)
99− }
100− template auto any::cast<double>() const -> double;
101−
102− template <typename T>
103− auto any::cast() const -> typename std::enable_if<std::is_same<T, char>::value, T>::type {
104− RETURN_VALUE(Type::Character, c,)
105− }
106− template auto any::cast<char>() const -> char;
107−
108− template <typename T>
109− auto any::cast() const -> typename std::enable_if<std::is_same<T, bool>::value, T>::type {
110− RETURN_VALUE(Type::Boolean, b,)
111− }
112− template auto any::cast<bool>() const -> bool;
113−
114− template <typename T>
115− auto any::cast() const -> typename std::enable_if<std::is_same<T, string>::value, const T&>::type {
116− RETURN_VALUE(Type::String, s, *)
117− }
118− template auto any::cast<string>() const -> const string&;
119−
120− template <typename T>
121− auto any::cast() const -> typename std::enable_if<std::is_same<T, const char*>::value, const T>::type {
122− RETURN_VALUE(Type::String, s->c_str(),)
123− }
124− template auto any::cast<const char*>() const -> const char* const;
125−
126− template <typename T>
127− auto any::cast() const -> typename std::enable_if<std::is_same<T, map>::value, const T&>::type {
128− RETURN_VALUE(Type::Map, m, *)
129− }
130− template auto any::cast<any::map>() const -> const map&;
131−
132− template <typename T>
133− auto any::cast() const -> typename std::enable_if<std::is_same<T, vector>::value, const T&>::type {
134− RETURN_VALUE(Type::Vector, v, *)
135− }
136− template auto any::cast<any::vector>() const -> const vector&;
137−
138−
139− auto any::operator()(const any& arg) const -> any {
140− if (type == Type::Function) {
141− return (*f)(arg);
142− }
143− const any* valuePtr = this;
144− do {
145− assert(valuePtr->type == Type::Thunk);
146− const any& value = (*valuePtr->t)(unthunk);
147− if (value.type == Type::Function) {
148− return (*value.f)(arg);
149− }
150− valuePtr = &value;
151− } while (valuePtr->type != Type::Unknown);
152− return nullptr;
153− }
154
109
155− auto any::operator()(const as_thunk) const -> const any& {
110+template <typename T>
156− assert(type == Type::Thunk);
111+auto any::cast() const -> typename std::enable_if<std::is_same<T, long>::value, T>::type {
157− return (*t)(unthunk);
112+ RETURN_VALUE(Type::Integer, i,)
158− }
113+}
114+template auto any::cast<long>() const -> long;
159
115
160− auto any::operator()() const -> any {
116+template <typename T>
161− if (type == Type::EffFunction) {
117+auto any::cast() const -> typename std::enable_if<std::is_same<T, double>::value, T>::type {
162− return (*e)();
118+ RETURN_VALUE(Type::Double, d,)
163− }
164− const any* valuePtr = this;
165− do {
166− assert(valuePtr->type == Type::Thunk);
167− const any& value = (*valuePtr->t)(unthunk);
168− if (value.type == Type::EffFunction) {
169− return (*value.e)();
170− }
119+}
171− valuePtr = &value;
120+template auto any::cast<double>() const -> double;
172− } while (valuePtr->type != Type::Unknown);
173− return nullptr;
174− }
175
121
176− any::operator long() const {
122+template <typename T>
123+auto any::cast() const -> typename std::enable_if<std::is_same<T, char>::value, T>::type {
177− RETURN_VALUE(Type::Integer, i,)
124+ RETURN_VALUE(Type::Character, c,)
178− }
125+}
126+template auto any::cast<char>() const -> char;
179
127
180− any::operator double() const {
128+template <typename T>
129+auto any::cast() const -> typename std::enable_if<std::is_same<T, bool>::value, T>::type {
181− RETURN_VALUE(Type::Double, d,)
130+ RETURN_VALUE(Type::Boolean, b,)
182− }
131+}
132+template auto any::cast<bool>() const -> bool;
183
133
184− any::operator bool() const {
134+template <typename T>
185− RETURN_VALUE(Type::Boolean, b,)
135+auto any::cast() const -> typename std::enable_if<std::is_same<T, string>::value, T>::type {
136+ const any& variant = unthunkVariant(*this);
137+ if (variant.type == Type::StringLiteral) {
138+ return variant.r;
186 }
139 }
140+ assert(variant.type == Type::String);
141+ return variant.s->c_str();
142+}
143+template auto any::cast<string>() const -> string;
187
144
188− any::operator const string&() const {
145+template <typename T>
146+auto any::cast() const -> typename std::enable_if<std::is_same<T, map>::value, const T&>::type {
189− RETURN_VALUE(Type::String, s, *)
147+ RETURN_VALUE(Type::Map, m, *)
190− }
148+}
149+template auto any::cast<any::map>() const -> const map&;
191
150
192− any::operator const map&() const {
151+template <typename T>
152+auto any::cast() const -> typename std::enable_if<std::is_same<T, vector>::value, const T&>::type {
193− RETURN_VALUE(Type::Map, m, *)
153+ RETURN_VALUE(Type::Vector, v, *)
194− }
154+}
155+template auto any::cast<any::vector>() const -> const vector&;
195
156
196− any::operator const vector&() const {
157+auto any::operator()(const any& arg) const -> any {
197− RETURN_VALUE(Type::Vector, v, *)
158+ const any& variant = unthunkVariant(*this);
159+ if (variant.type == Type::Closure) {
160+ return (*variant.l)(arg);
198 }
161 }
162+ assert(variant.type == Type::Function);
163+ return (*variant.f)(arg);
164+}
199
165
200− auto any::extractPointer() const -> const void* {
166+auto any::operator()(const as_thunk) const -> const any& {
201− RETURN_VALUE(Type::Pointer, p.get(),)
167+ assert(type == Type::Thunk);
168+ return (*t)(unthunk);
202− }
169+}
203
170
204− auto any::extract_value(const any& a) -> const any& {
171+auto any::operator()() const -> any {
205− if (a.type != Type::Thunk) {
172+ const any& variant = unthunkVariant(*this);
206− return a;
173+ assert(variant.type == Type::EffFunction);
207− }
208− const any* valuePtr = &a;
209− do {
210− const any& value = (*valuePtr->t)(unthunk);
211− if (value.type != Type::Thunk) {
212− return value;
174+ return (*variant.e)();
213− }
214− valuePtr = &value;
215− } while (true);
216− }
175+}
217
176
218− auto any::operator[](const map_key_t& rhs) const -> const any& {
177+any::operator long() const {
219− RETURN_VALUE(Type::Map, m->at(rhs),)
178+ return cast<long>();
220− }
179+}
221
180
222− auto any::operator[](const vector::size_type rhs) const -> const any& {
181+any::operator double() const {
223− RETURN_VALUE(Type::Vector, v->at(rhs),)
182+ return cast<double>();
224− }
183+}
225
184
226− auto any::operator[](const any& rhs) const -> const any& {
185+any::operator bool() const {
227− RETURN_VALUE(Type::Vector, v->at(rhs.cast<long>()),)
186+ return cast<bool>();
228− }
187+}
229
188
230−#define DEFINE_OPERATOR_LHS(K, T, OP, V, R, P) \
189+any::operator string() const {
231−auto operator OP(const T lhs, const any& rhs_) -> R { \
190+ return cast<string>();
232− const any& rhs = any::extract_value(rhs_); \
233− assert(rhs.type == any::Type::K); \
234− return lhs OP P(rhs.V); \
235}
191}
236
192
237−#define DEFINE_OPERATOR_RHS(K, T, OP, V, R, P) \
238−auto any::operator OP(const T rhs) const -> R { \
193+any::operator const map&() const {
239− const any& lhs = any::extract_value(*this); \
240− assert(lhs.type == Type::K); \
241− return P(lhs.V) OP rhs; \
194+ return cast<map>();
242}
195}
243
196
244−auto any::operator==(const any& rhs_) const -> bool {
197+any::operator const vector&() const {
245− const any& lhs = extract_value(*this);
198+ return cast<vector>();
246− const any& rhs = extract_value(rhs_);
247− assert(lhs.type == rhs.type);
248− switch (lhs.type) {
249− case Type::Integer: return lhs.i == rhs.i;
250− case Type::Double: return lhs.d == rhs.d;
251− case Type::Character: return lhs.c == rhs.c;
252− case Type::Boolean: return lhs.b == rhs.b;
253− case Type::String: return (*lhs.s) == (*rhs.s);
254− case Type::Pointer: return lhs.p == rhs.p;
255− default: assert(false && "Unsupported type for '==' operator");
256− }
257− return false;
258}
199}
259
200
260−DEFINE_OPERATOR_RHS(Integer, long, ==, i, bool,)
201+auto any::extractPointer() const -> void* {
261−DEFINE_OPERATOR_RHS(Double, double, ==, d, bool,)
202+ RETURN_VALUE(Type::Pointer, p.get(),)
262−DEFINE_OPERATOR_RHS(Character, char, ==, c, bool,)
203+}
263−DEFINE_OPERATOR_RHS(Boolean, bool, ==, b, bool,)
264−DEFINE_OPERATOR_RHS(String, string&, ==, s, bool, *)
265−DEFINE_OPERATOR_RHS(String, char* const, ==, s, bool, *)
266
204
267−auto any::operator!=(const any& rhs_) const -> bool {
205+auto any::unthunkVariant(const any& a) -> const any& {
268− const any& lhs = extract_value(*this);
206+ const any * variant = &a;
269− const any& rhs = extract_value(rhs_);
207+ while (variant->type == Type::Thunk) {
270− assert(lhs.type == rhs.type);
208+ variant = &((*variant->t)(unthunk));
271− switch (lhs.type) {
272− case Type::Integer: return lhs.i != rhs.i;
273− case Type::Double: return lhs.d != rhs.d;
274− case Type::Character: return lhs.c != rhs.c;
275− case Type::Boolean: return lhs.b != rhs.b;
276− case Type::String: return (*lhs.s) != (*rhs.s);
277− case Type::Pointer: return lhs.p != rhs.p;
278− default: assert(false && "Unsupported type for '!=' operator");
279 }
209 }
280− return false;
210+ return *variant;
281}
211}
282
212
283−DEFINE_OPERATOR_RHS(Integer, long, !=, i, bool,)
284−DEFINE_OPERATOR_RHS(Double, double, !=, d, bool,)
285−DEFINE_OPERATOR_RHS(Character, char, !=, c, bool,)
286−DEFINE_OPERATOR_RHS(Boolean, bool, !=, b, bool,)
287−DEFINE_OPERATOR_RHS(String, string&, !=, s, bool, *)
288−DEFINE_OPERATOR_RHS(String, char* const, !=, s, bool, *)
289−
290−auto any::operator<(const any& rhs_) const -> bool {
213+auto any::operator[](const char rhs[]) const -> const any& {
291− const any& lhs = extract_value(*this);
214+ const any& variant = unthunkVariant(*this);
292− const any& rhs = extract_value(rhs_);
293− assert(lhs.type == rhs.type);
215+ assert(variant.type == Type::Map);
294− switch (lhs.type) {
216+ const any::map::const_iterator begin = variant.m->begin();
295− case Type::Integer: return lhs.i < rhs.i;
217+ const any::map::const_iterator end = variant.m->end();
296− case Type::Double: return lhs.d < rhs.d;
218+ for (any::map::const_iterator it = begin; it != end; ++it) {
297− case Type::Character: return lhs.c < rhs.c;
219+ if (it->first == rhs) {
298− case Type::Boolean: return lhs.b < rhs.b;
220+ return it->second;
299− case Type::String: return (*lhs.s) < (*rhs.s);
221+ }
300− default: assert(false && "Unsupported type for '<' operator");
301 }
222 }
223+ for (any::map::const_iterator it = begin; it != end; ++it) {
224+ if (strcmp(it->first, rhs) == 0) {
302− return false;
225+ return it->second;
226+ }
227+ }
228+ throw runtime_error("map key not found");
303}
229}
304
230
305−DEFINE_OPERATOR_RHS(Integer, long, <, i, bool,)
306−DEFINE_OPERATOR_RHS(Double, double, <, d, bool,)
307−DEFINE_OPERATOR_RHS(Character, char, <, c, bool,)
308−DEFINE_OPERATOR_RHS(Boolean, bool, <, b, bool,)
309−DEFINE_OPERATOR_RHS(String, string&, <, s, bool, *)
310−DEFINE_OPERATOR_RHS(String, char* const, <, s, bool, *)
311−
312−auto any::operator<=(const any& rhs_) const -> bool {
231+auto any::operator[](const vector::size_type rhs) const -> const any& {
313− const any& lhs = extract_value(*this);
232+ const any& variant = unthunkVariant(*this);
314− const any& rhs = extract_value(rhs_);
315− assert(lhs.type == rhs.type);
233+ assert(variant.type == Type::Vector);
316− switch (lhs.type) {
317− case Type::Integer: return lhs.i <= rhs.i;
318− case Type::Double: return lhs.d <= rhs.d;
319− case Type::Character: return lhs.c <= rhs.c;
320− case Type::Boolean: return lhs.b <= rhs.b;
321− case Type::String: return (*lhs.s) <= (*rhs.s);
234+ return (*variant.v)[rhs];
322− default: assert(false && "Unsupported type for '<' operator");
323− }
324− return false;
325}
235}
326
236
327−DEFINE_OPERATOR_RHS(Integer, long, <=, i, bool,)
237+auto any::operator[](const any& rhs) const -> const any& {
328−DEFINE_OPERATOR_RHS(Double, double, <=, d, bool,)
238+ const any& variant = unthunkVariant(*this);
329−DEFINE_OPERATOR_RHS(Character, char, <=, c, bool,)
239+ assert(variant.type == Type::Vector);
330−DEFINE_OPERATOR_RHS(Boolean, bool, <=, b, bool,)
240+ return (*variant.v)[rhs.cast<long>()];
331−DEFINE_OPERATOR_RHS(String, string&, <=, s, bool, *)
241+}
332−DEFINE_OPERATOR_RHS(String, char* const, <=, s, bool, *)
333
242
334−auto any::operator>(const any& rhs_) const -> bool {
243+auto any::contains(const char key[]) const -> bool {
335− const any& lhs = extract_value(*this);
244+ const any& variant = unthunkVariant(*this);
336− const any& rhs = extract_value(rhs_);
337− assert(lhs.type == rhs.type);
245+ assert(variant.type == Type::Map);
338− switch (lhs.type) {
246+ for (any::map::const_iterator it = variant.m->begin(), end = variant.m->end(); it != end; ++it) {
339− case Type::Integer: return lhs.i > rhs.i;
247+ if (it->first == key || strcmp(it->first, key) == 0) {
340− case Type::Double: return lhs.d > rhs.d;
248+ return true;
341− case Type::Character: return lhs.c > rhs.c;
249+ }
342− case Type::Boolean: return lhs.b > rhs.b;
343− case Type::String: return (*lhs.s) > (*rhs.s);
344− default: assert(false && "Unsupported type for '>' operator");
345 }
250 }
346 return false;
251 return false;
347}
252}
348
253
349−DEFINE_OPERATOR_RHS(Integer, long, >, i, bool,)
254+//-----------------------------------------------------------------------------
350−DEFINE_OPERATOR_RHS(Double, double, >, d, bool,)
255+// Operator helper macros
351−DEFINE_OPERATOR_RHS(Character, char, >, c, bool,)
256+//-----------------------------------------------------------------------------
352−DEFINE_OPERATOR_RHS(Boolean, bool, >, b, bool,)
353−DEFINE_OPERATOR_RHS(String, string&, >, s, bool, *)
354−DEFINE_OPERATOR_RHS(String, char* const, >, s, bool, *)
355
257
356−auto any::operator>=(const any& rhs_) const -> bool {
258+#define DEFINE_OPERATOR(op, ty, rty) \
357− const any& lhs = extract_value(*this);
259+auto operator op (const any& lhs, ty rhs) -> rty { \
358− const any& rhs = extract_value(rhs_);
260+ return lhs.cast<typename std::remove_const<std::remove_reference<ty>::type>::type>() op rhs; \
359− assert(lhs.type == rhs.type);
360− switch (lhs.type) {
361− case Type::Integer: return lhs.i >= rhs.i;
362− case Type::Double: return lhs.d >= rhs.d;
363− case Type::Character: return lhs.c >= rhs.c;
364− case Type::Boolean: return lhs.b >= rhs.b;
365− case Type::String: return (*lhs.s) >= (*rhs.s);
366− default: assert(false && "Unsupported type for '>' operator");
367− }
261+} \
368− return false;
262+auto operator op (ty lhs, const any& rhs) -> rty { \
263+ return lhs op rhs.cast<typename std::remove_const<std::remove_reference<ty>::type>::type>(); \
369}
264}
370
265
371−DEFINE_OPERATOR_RHS(Integer, long, >=, i, bool,)
266+#define DEFINE_CSTR_EQUALS_OPERATOR() \
372−DEFINE_OPERATOR_RHS(Double, double, >=, d, bool,)
267+ auto operator==(const any& lhs_, const char * rhs) -> bool { \
373−DEFINE_OPERATOR_RHS(Character, char, >=, c, bool,)
268+ const any& lhs = any::unthunkVariant(lhs_); \
374−DEFINE_OPERATOR_RHS(Boolean, bool, >=, b, bool,)
269+ assert(lhs.type == any::Type::StringLiteral || lhs.type == any::Type::String); \
375−DEFINE_OPERATOR_RHS(String, string&, >=, s, bool, *)
270+ if (lhs.type == any::Type::StringLiteral) { \
376−DEFINE_OPERATOR_RHS(String, char* const, >=, s, bool, *)
271+ return (lhs.r == rhs) || (strcmp(lhs.r, rhs) == 0); \
377−
272+ } \
273+ return strcmp(lhs.s->c_str(), rhs) == 0; \
274+ } \
275+ auto operator==(const char * lhs, const any& rhs_) -> bool { \
276+ const any& rhs = any::unthunkVariant(rhs_); \
277+ assert(rhs.type == any::Type::StringLiteral || rhs.type == any::Type::String); \
278+ if (rhs.type == any::Type::StringLiteral) { \
279+ return (lhs == rhs.r) || (strcmp(lhs, rhs) == 0); \
280+ } \
281+ return strcmp(lhs, rhs.s->c_str()) == 0; \
282+ }
283+
284+#define DEFINE_CSTR_COMPARISON_OPERATOR(op) \
285+ auto operator op (const any& lhs, const char * rhs) -> bool { \
286+ return strcmp(lhs.cast<string>(), rhs) op 0; \
287+ } \
288+ auto operator op (const char * lhs, const any& rhs) -> bool { \
289+ return strcmp(lhs, rhs.cast<string>()) op 0; \
290+ }
291+
292+#define DEFINE_COMPARISON_OPERATOR(op) \
293+ auto operator op (const any& lhs_, const any& rhs_) -> bool { \
294+ const any& lhs = any::unthunkVariant(lhs_); \
295+ const any& rhs = any::unthunkVariant(rhs_); \
296+ switch (lhs.type) { \
297+ case any::Type::Integer: assert(lhs.type == any::Type::Integer); return lhs.i op rhs.i; \
298+ case any::Type::Double: assert(lhs.type == any::Type::Double); return lhs.d op rhs.d; \
299+ case any::Type::Character: assert(lhs.type == any::Type::Character); return lhs.c op rhs.c; \
300+ case any::Type::Boolean: assert(lhs.type == any::Type::Boolean); return lhs.b op rhs.b; \
301+ case any::Type::StringLiteral: \
302+ assert(lhs.type == any::Type::StringLiteral || lhs.type == any::Type::String); \
303+ assert(rhs.type == any::Type::StringLiteral || rhs.type == any::Type::String); \
304+ return strcmp(lhs.r, rhs.type == any::Type::StringLiteral ? rhs.r : rhs.s->c_str()) op 0; \
305+ case any::Type::String: \
306+ assert(lhs.type == any::Type::StringLiteral || lhs.type == any::Type::String); \
307+ assert(rhs.type == any::Type::StringLiteral || rhs.type == any::Type::String); \
308+ return strcmp(lhs.s->c_str(), rhs.type == any::Type::StringLiteral ? rhs.r : rhs.s->c_str()) op 0; \
309+ case any::Type::Pointer: return lhs.p op rhs.p; \
310+ default: assert(false && "Unsupported type for operator " #op); \
311+ } \
312+ return false; \
313+ } \
314+ DEFINE_OPERATOR(op, long, bool) \
315+ DEFINE_OPERATOR(op, double, bool) \
316+ DEFINE_OPERATOR(op, char, bool) \
317+ DEFINE_OPERATOR(op, bool, bool) \
318+
319+//-----------------------------------------------------------------------------
320+// Operator definitions
321+//-----------------------------------------------------------------------------
322+
323+DEFINE_COMPARISON_OPERATOR(==)
324+DEFINE_COMPARISON_OPERATOR(!=)
325+DEFINE_COMPARISON_OPERATOR(<)
326+DEFINE_COMPARISON_OPERATOR(<=)
327+DEFINE_COMPARISON_OPERATOR(>)
328+DEFINE_COMPARISON_OPERATOR(>=)
329+
330+DEFINE_CSTR_EQUALS_OPERATOR()
331+DEFINE_CSTR_COMPARISON_OPERATOR(!=)
332+DEFINE_CSTR_COMPARISON_OPERATOR(<)
333+DEFINE_CSTR_COMPARISON_OPERATOR(<=)
334+DEFINE_CSTR_COMPARISON_OPERATOR(>)
335+DEFINE_CSTR_COMPARISON_OPERATOR(>=)
336+
378−auto any::operator+(const any& rhs_) const -> any {
337+auto operator+(const any& lhs_, const any& rhs_) -> any {
379− const any& lhs = extract_value(*this);
338+ const any& lhs = any::unthunkVariant(lhs_);
380− const any& rhs = extract_value(rhs_);
339+ const any& rhs = any::unthunkVariant(rhs_);
381− assert(lhs.type == rhs.type);
382 switch (lhs.type) {
340 switch (lhs.type) {
383− case Type::Integer: return lhs.i + rhs.i;
341+ case any::Type::Integer: assert(lhs.type == any::Type::Integer); return lhs.i + rhs.i;
384− case Type::Double: return lhs.d + rhs.d;
342+ case any::Type::Double: assert(lhs.type == any::Type::Double); return lhs.d + rhs.d;
385− case Type::Character: return any(char(lhs.c + rhs.c));
343+ case any::Type::Character: assert(lhs.type == any::Type::Character); return any(char(lhs.c + rhs.c));
386− case Type::String: return (*lhs.s) + (*rhs.s);
344+ case any::Type::StringLiteral:
345+ assert(lhs.type == any::Type::StringLiteral || lhs.type == any::Type::String);
346+ assert(rhs.type == any::Type::StringLiteral || rhs.type == any::Type::String);
347+ return rhs.type == any::Type::StringLiteral ? std::string(lhs.r) + rhs.r : lhs.r + *rhs.s;
348+ case any::Type::String:
349+ assert(lhs.type == any::Type::StringLiteral || lhs.type == any::Type::String);
350+ assert(rhs.type == any::Type::StringLiteral || rhs.type == any::Type::String);
351+ return rhs.type == any::Type::StringLiteral ? *lhs.s + rhs.r : *lhs.s + *rhs.s;
387 default: assert(false && "Unsupported type for '+' operator");
352 default: assert(false && "Unsupported type for '+' operator");
388 }
353 }
389 return nullptr;
354 return nullptr;
390}
355}
391
356
392−DEFINE_OPERATOR_RHS(Integer, long, +, i, long,)
357+DEFINE_OPERATOR(+, long, long)
393−DEFINE_OPERATOR_RHS(Double, double, +, d, double,)
358+DEFINE_OPERATOR(+, double, double)
394−DEFINE_OPERATOR_RHS(Character, char, +, c, char,)
359+DEFINE_OPERATOR(+, char, char)
395−DEFINE_OPERATOR_RHS(String, string&, +, s, string, *)
360+
396−DEFINE_OPERATOR_RHS(String, char* const, +, s, string, *)
361+auto operator+(const any& lhs_, const char * rhs) -> std::string {
362+ const any& lhs = any::unthunkVariant(lhs_);
363+ assert(lhs.type == any::Type::StringLiteral || lhs.type == any::Type::String);
364+ return lhs.type == any::Type::StringLiteral ? std::string(lhs.r) + rhs : *lhs.s + rhs;
365+}
366+
367+auto operator+(const char * lhs, const any& rhs_) -> std::string {
368+ const any& rhs = any::unthunkVariant(rhs_);
369+ assert(rhs.type == any::Type::StringLiteral || rhs.type == any::Type::String);
370+ return rhs.type == any::Type::StringLiteral ? lhs + std::string(rhs.r) : lhs + *rhs.s;
371+}
397
372
398−auto any::operator-(const any& rhs_) const -> any {
373+auto operator-(const any& lhs_, const any& rhs_) -> any {
399− const any& lhs = extract_value(*this);
374+ const any& lhs = any::unthunkVariant(lhs_);
400− const any& rhs = extract_value(rhs_);
375+ const any& rhs = any::unthunkVariant(rhs_);
401 assert(lhs.type == rhs.type);
376 assert(lhs.type == rhs.type);
402 switch (lhs.type) {
377 switch (lhs.type) {
403− case Type::Integer: return lhs.i - rhs.i;
378+ case any::Type::Integer: return lhs.i - rhs.i;
404− case Type::Double: return lhs.d - rhs.d;
379+ case any::Type::Double: return lhs.d - rhs.d;
405− case Type::Character: return any(char(lhs.c - rhs.c));
380+ case any::Type::Character: return any(char(lhs.c - rhs.c));
406− default: assert(false && "Unsupported type for '-' binary operator");
381+ default: assert(false && "Unsupported type for '-' operator");
407 }
382 }
408 return nullptr;
383 return nullptr;
409}
384}
410
385
411−DEFINE_OPERATOR_RHS(Integer, long, -, i, long,)
386+DEFINE_OPERATOR(-, long, long)
412−DEFINE_OPERATOR_RHS(Double, double, -, d, double,)
387+DEFINE_OPERATOR(-, double, double)
413−DEFINE_OPERATOR_RHS(Character, char, -, c, char,)
388+DEFINE_OPERATOR(-, char, char)
414
389
415−auto any::operator*(const any& rhs_) const -> any {
390+auto operator*(const any& lhs_, const any& rhs_) -> any {
416− const any& lhs = extract_value(*this);
391+ const any& lhs = any::unthunkVariant(lhs_);
417− const any& rhs = extract_value(rhs_);
392+ const any& rhs = any::unthunkVariant(rhs_);
418 assert(lhs.type == rhs.type);
393 assert(lhs.type == rhs.type);
419 switch (lhs.type) {
394 switch (lhs.type) {
420− case Type::Integer: return lhs.i * rhs.i;
395+ case any::Type::Integer: return lhs.i * rhs.i;
421− case Type::Double: return lhs.d * rhs.d;
396+ case any::Type::Double: return lhs.d * rhs.d;
397+ case any::Type::Character: return any(char(lhs.c * rhs.c));
422 default: assert(false && "Unsupported type for '*' operator");
398 default: assert(false && "Unsupported type for '*' operator");
423 }
399 }
424 return nullptr;
400 return nullptr;
425}
401}
426
402
427−DEFINE_OPERATOR_RHS(Integer, long, *, i, long,)
403+DEFINE_OPERATOR(*, long, long)
428−DEFINE_OPERATOR_RHS(Double, double, *, d, double,)
404+DEFINE_OPERATOR(*, double, double)
405+DEFINE_OPERATOR(*, char, char)
429
406
430−auto any::operator/(const any& rhs_) const -> any {
407+auto operator/(const any& lhs_, const any& rhs_) -> any {
431− const any& lhs = extract_value(*this);
408+ const any& lhs = any::unthunkVariant(lhs_);
432− const any& rhs = extract_value(rhs_);
409+ const any& rhs = any::unthunkVariant(rhs_);
433 assert(lhs.type == rhs.type);
410 assert(lhs.type == rhs.type);
434 switch (lhs.type) {
411 switch (lhs.type) {
435− case Type::Integer: return lhs.i / rhs.i;
412+ case any::Type::Integer: return lhs.i / rhs.i;
436− case Type::Double: return lhs.d / rhs.d;
413+ case any::Type::Double: return lhs.d / rhs.d;
414+ case any::Type::Character: return any(char(lhs.c / rhs.c));
437 default: assert(false && "Unsupported type for '/' operator");
415 default: assert(false && "Unsupported type for '/' operator");
438 }
416 }
439 return nullptr;
417 return nullptr;
440}
418}
441
419
442−DEFINE_OPERATOR_RHS(Integer, long, /, i, long,)
420+DEFINE_OPERATOR(/, long, long)
443−DEFINE_OPERATOR_RHS(Double, double, /, d, double,)
421+DEFINE_OPERATOR(/, double, double)
422+DEFINE_OPERATOR(/, char, char)
444
423
445−auto any::operator%(const any& rhs_) const -> any {
424+auto operator%(const any& lhs_, const any& rhs_) -> any {
446− const any& lhs = extract_value(*this);
425+ const any& lhs = any::unthunkVariant(lhs_);
447− const any& rhs = extract_value(rhs_);
426+ const any& rhs = any::unthunkVariant(rhs_);
448 assert(lhs.type == rhs.type);
427 assert(lhs.type == rhs.type);
449 switch (lhs.type) {
428 switch (lhs.type) {
450− case Type::Integer: return lhs.i % rhs.i;
429+ case any::Type::Integer: return lhs.i % rhs.i;
430+ case any::Type::Character: return any(char(lhs.c % rhs.c));
451 default: assert(false && "Unsupported type for '%' operator");
431 default: assert(false && "Unsupported type for '%' operator");
452 }
432 }
453 return nullptr;
433 return nullptr;
454}
434}
455
435
456−DEFINE_OPERATOR_RHS(Integer, long, %, i, long,)
436+DEFINE_OPERATOR(%, long, long)
437+DEFINE_OPERATOR(%, char, char)
457
438
439+// unary negate
458−auto any::operator-() const -> any {
440+auto operator-(const any& rhs_) -> any {
459− const any& lhs = any::extract_value(*this);
441+ const any& rhs = any::unthunkVariant(rhs_);
460− switch (lhs.type) {
442+ switch (rhs.type) {
461− case Type::Integer: return (- lhs.i);
443+ case any::Type::Integer: return (- rhs.i);
462− case Type::Double: return (- lhs.d);
444+ case any::Type::Double: return (- rhs.d);
463 default: assert(false && "Unsupported type for unary '-' operator");
445 default: assert(false && "Unsupported type for unary '-' operator");
464 }
446 }
465 return nullptr;
447 return nullptr;
466}
448}
467
449
468−DEFINE_OPERATOR_LHS(Integer, long, ==, i, bool,)
469−DEFINE_OPERATOR_LHS(Integer, long, !=, i, bool,)
470−DEFINE_OPERATOR_LHS(Integer, long, <, i, bool,)
471−DEFINE_OPERATOR_LHS(Integer, long, <=, i, bool,)
472−DEFINE_OPERATOR_LHS(Integer, long, >, i, bool,)
473−DEFINE_OPERATOR_LHS(Integer, long, >=, i, bool,)
474−
475−DEFINE_OPERATOR_LHS(Double, double, ==, d, bool,)
476−DEFINE_OPERATOR_LHS(Double, double, !=, d, bool,)
477−DEFINE_OPERATOR_LHS(Double, double, <, d, bool,)
478−DEFINE_OPERATOR_LHS(Double, double, <=, d, bool,)
479−DEFINE_OPERATOR_LHS(Double, double, >, d, bool,)
480−DEFINE_OPERATOR_LHS(Double, double, >=, d, bool,)
481−
482−DEFINE_OPERATOR_LHS(Character, char, ==, c, bool,)
483−DEFINE_OPERATOR_LHS(Character, char, !=, c, bool,)
484−DEFINE_OPERATOR_LHS(Character, char, <, c, bool,)
485−DEFINE_OPERATOR_LHS(Character, char, <=, c, bool,)
486−DEFINE_OPERATOR_LHS(Character, char, >, c, bool,)
487−DEFINE_OPERATOR_LHS(Character, char, >=, c, bool,)
488−
489−DEFINE_OPERATOR_LHS(Boolean, bool, ==, b, bool,)
490−DEFINE_OPERATOR_LHS(Boolean, bool, !=, b, bool,)
491−DEFINE_OPERATOR_LHS(Boolean, bool, <, b, bool,)
492−DEFINE_OPERATOR_LHS(Boolean, bool, <=, b, bool,)
493−DEFINE_OPERATOR_LHS(Boolean, bool, >, b, bool,)
494−DEFINE_OPERATOR_LHS(Boolean, bool, >=, b, bool,)
495−
496−DEFINE_OPERATOR_LHS(String, string&, ==, s, bool, *)
497−DEFINE_OPERATOR_LHS(String, string&, !=, s, bool, *)
498−DEFINE_OPERATOR_LHS(String, string&, <, s, bool, *)
499−DEFINE_OPERATOR_LHS(String, string&, <=, s, bool, *)
500−DEFINE_OPERATOR_LHS(String, string&, >, s, bool, *)
501−DEFINE_OPERATOR_LHS(String, string&, >=, s, bool, *)
502−
503−DEFINE_OPERATOR_LHS(String, char* const, ==, s, bool, *)
504−DEFINE_OPERATOR_LHS(String, char* const, !=, s, bool, *)
505−DEFINE_OPERATOR_LHS(String, char* const, <, s, bool, *)
506−DEFINE_OPERATOR_LHS(String, char* const, <=, s, bool, *)
507−DEFINE_OPERATOR_LHS(String, char* const, >, s, bool, *)
508−DEFINE_OPERATOR_LHS(String, char* const, >=, s, bool, *)
509−
510−DEFINE_OPERATOR_LHS(Integer, long, +, i, long,)
511−DEFINE_OPERATOR_LHS(Integer, long, -, i, long,)
512−DEFINE_OPERATOR_LHS(Integer, long, *, i, long,)
513−DEFINE_OPERATOR_LHS(Integer, long, /, i, long,)
514−DEFINE_OPERATOR_LHS(Integer, long, %, i, long,)
515−
516−DEFINE_OPERATOR_LHS(Double, double, +, d, double,)
517−DEFINE_OPERATOR_LHS(Double, double, -, d, double,)
518−DEFINE_OPERATOR_LHS(Double, double, *, d, double,)
519−DEFINE_OPERATOR_LHS(Double, double, /, d, double,)
520−
521−DEFINE_OPERATOR_LHS(Character, char, +, i, char,)
522−DEFINE_OPERATOR_LHS(Character, char, -, i, char,)
523−
524−DEFINE_OPERATOR_LHS(String, string&, +, s, string, *)
525−DEFINE_OPERATOR_LHS(String, char* const, +, s, string, *)
526−
527−
528} // namespace PureScript
450} // namespace PureScript
pcc/include/purescript.hh+122−235
@@ -29,16 +29,32 @@
29#include <functional>
29#include <functional>
30#include <string>
30#include <string>
31#include <vector>
31#include <vector>
32−#include <unordered_map>
32+#include <utility>
33#include <stdexcept>
33#include <stdexcept>
34−#include "map_key.hh"
34+
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;
38+
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)
45+
35
46
36namespace PureScript {
47namespace PureScript {
37
48
38−using string = std::string;
49+using string = const char *;
39−using runtime_error = std::runtime_error;
40using nullptr_t = std::nullptr_t;
50using nullptr_t = std::nullptr_t;
41
51
52+// Workaround for missing C++11 version in gcc
53+class runtime_error : public std::runtime_error {
54+public:
55+ runtime_error(const char message[]) : std::runtime_error(std::string(message)) {}
56+};
57+
42const bool undefined = false;
58const bool undefined = false;
43
59
44// A variant data class designed to provide some features of dynamic typing.
60// A variant data class designed to provide some features of dynamic typing.
@@ -46,16 +62,18 @@ const bool undefined = false;
46class any {
62class any {
47
63
48 public:
64 public:
49− enum class Type : std::int8_t {
65+ enum class Type : int8_t {
50 Unknown,
66 Unknown,
51 Integer,
67 Integer,
52 Double,
68 Double,
53 Character,
69 Character,
54 Boolean,
70 Boolean,
71+ StringLiteral,
55 String,
72 String,
56 Map,
73 Map,
57 Vector,
74 Vector,
58 Function,
75 Function,
76+ Closure,
59 EffFunction,
77 EffFunction,
60 Thunk,
78 Thunk,
61 Pointer
79 Pointer
@@ -67,43 +85,36 @@ class any {
67 };
85 };
68 static constexpr as_thunk unthunk = as_thunk{};
86 static constexpr as_thunk unthunk = as_thunk{};
69
87
70− using map = std::unordered_map<map_key_t, const any, map_key_t::hasher, map_key_t::equal>;
88+ using map = std::vector<std::pair<const char * const, const any>>;
71− using vector = std::vector<any>;
89+ using vector = std::vector<any>;
90+ using fn = auto (*)(const any&) -> any;
72− using fn = std::function<any(const any&)>;
91+ using closure = std::function<any(const any&)>;
73− using eff_fn = std::function<any()>;
92+ using eff_fn = std::function<any()>;
74− using thunk = std::function<const any& (const as_thunk)>;
93+ using thunk = auto (*)(const as_thunk) -> const any&;
75
94
76 template <typename T>
95 template <typename T>
77 using shared = std::shared_ptr<T>;
96 using shared = std::shared_ptr<T>;
78
97
79− template <typename T>
98+ template <typename T, typename... Args>
80− static constexpr auto make_shared(const T& arg) -> shared<T> {
99+ inline static auto make_shared(Args&&... args) -> decltype(std::make_shared<T>(std::forward<Args>(args)...)) {
81− return std::make_shared<T>(arg);
100+ return std::make_shared<T>(std::forward<Args>(args)...);
82− }
83−
84− template <typename T>
85− static constexpr auto make_shared(T&& arg) -> shared<T> {
86− return std::make_shared<T>(std::move(arg));
87− }
88−
89− template <typename T, typename U>
90− static constexpr auto static_cast_shared(U arg) -> T* {
91− return static_cast<T*>(arg.get());
92 }
101 }
93
102
94 private:
103 private:
95 union {
104 union {
96− mutable long i;
105+ mutable long i;
97− mutable double d;
106+ mutable double d;
98− mutable char c;
107+ mutable char c;
99− mutable bool b;
108+ mutable bool b;
109+ mutable string r;
100− mutable shared<string> s;
110+ mutable shared<std::string> s;
101− mutable shared<map> m;
111+ mutable shared<map> m;
102− mutable shared<vector> v;
112+ mutable shared<vector> v;
103− mutable shared<fn> f;
113+ mutable fn f;
114+ mutable shared<closure> l;
104− mutable shared<eff_fn> e;
115+ mutable shared<eff_fn> e;
105− mutable shared<thunk> t;
116+ mutable thunk t;
106− mutable shared<void> p;
117+ mutable shared<void> p;
107 };
118 };
108
119
109 public:
120 public:
@@ -111,81 +122,61 @@ class any {
111 any(const long val) : type(Type::Integer), i(val) {}
122 any(const long val) : type(Type::Integer), i(val) {}
112 any(const int val) : type(Type::Integer), i(val) {}
123 any(const int val) : type(Type::Integer), i(val) {}
113 any(const unsigned int val) : type(Type::Integer), i(val) {}
124 any(const unsigned int val) : type(Type::Integer), i(val) {}
114−
115 any(const double val) : type(Type::Double), d(val) {}
125 any(const double val) : type(Type::Double), d(val) {}
116−
117 any(const char val) : type(Type::Character), c(val) {}
126 any(const char val) : type(Type::Character), c(val) {}
118
127
128+ template <typename T, typename = typename std::enable_if<std::is_same<bool,T>::value>::type>
119− any(const bool val) : type(Type::Boolean), b(val) {}
129+ any(const T val) : type(Type::Boolean), b(val) {}
120
130
131+ template <size_t N>
121− any(const string& val) : type(Type::String), s(make_shared<string>(val)) {}
132+ any(const char (&val)[N]) : type(Type::StringLiteral), r(val) {}
122− any(string&& val) : type(Type::String), s(make_shared<string>(std::move(val))) {}
133+ any(char * val) : type(Type::String), s(make_shared<std::string>(val)) {}
123
134
124− any(const char val[]) : type(Type::String), s(make_shared<string>(val)) {}
135+ any(const std::string& val) : type(Type::String), s(make_shared<std::string>(val)) {}
136+ any(std::string&& val) : type(Type::String), s(make_shared<std::string>(std::move(val))) {}
125
137
126− any(const shared<string>& val) : type(Type::String), s(val) {}
138+ any(const shared<std::string>& val) : type(Type::String), s(val) {}
127− any(shared<string>&& val) : type(Type::String), s(std::move(val)) {}
139+ any(shared<std::string>&& val) noexcept : type(Type::String), s(std::move(val)) {}
128
140
129 any(const map& val) : type(Type::Map), m(make_shared<map>(val)) {}
141 any(const map& val) : type(Type::Map), m(make_shared<map>(val)) {}
130− any(map&& val) : type(Type::Map), m(make_shared<map>(std::move(val))) {}
142+ any(map&& val) noexcept : type(Type::Map), m(make_shared<map>(std::move(val))) {}
131−
132− any(const shared<map>& val) : type(Type::Map), m(val) {}
133− any(shared<map>&& val) : type(Type::Map), m(std::move(val)) {}
134
143
135 any(const vector& val) : type(Type::Vector), v(make_shared<vector>(val)) {}
144 any(const vector& val) : type(Type::Vector), v(make_shared<vector>(val)) {}
136− any(vector&& val) : type(Type::Vector), v(make_shared<vector>(std::move(val))) {}
145+ any(vector&& val) noexcept : type(Type::Vector), v(make_shared<vector>(std::move(val))) {}
137−
138− any(const shared<vector>& val) : type(Type::Vector), v(val) {}
139− any(shared<vector>&& val) : type(Type::Vector), v(std::move(val)) {}
140−
141− any(const shared<fn>& val) : type(Type::Function), f(val) {}
142− any(shared<fn>&& val) : type(Type::Function), f(std::move(val)) {}
143−
144− template <typename T,
145− typename = typename std::enable_if<!std::is_same<any,T>::value>::type>
146− any(const T& val, typename std::enable_if<std::is_assignable<fn,T>::value>::type* = 0)
147− : type(Type::Function), f(make_shared<fn>(val)) {}
148
146
149− // template <typename T>
147+ template <typename T>
150− // any(T&& val, typename std::enable_if<std::is_assignable<fn,T>::value>::type* = 0)
148+ any(const T& val, typename std::enable_if<std::is_convertible<T,fn>::value>::type* = 0)
151− // : type(Type::Function), f(std::move(val)) {}
149+ : type(Type::Function), f(val) {}
152
150
153− any(const shared<eff_fn>& val) : type(Type::EffFunction), e(val) {}
151+ template <typename T, typename = typename std::enable_if<!std::is_same<any,T>::value &&
154− any(shared<eff_fn>&& val) : type(Type::EffFunction), e(std::move(val)) {}
152+ !std::is_convertible<T,fn>::value>::type>
153+ any(const T& val, typename std::enable_if<std::is_assignable<closure,T>::value>::type* = 0)
154+ : type(Type::Closure), l(make_shared<closure>(val)) {}
155
155
156 template <typename T>
156 template <typename T>
157 any(const T& val, typename std::enable_if<std::is_assignable<eff_fn,T>::value>::type* = 0)
157 any(const T& val, typename std::enable_if<std::is_assignable<eff_fn,T>::value>::type* = 0)
158 : type(Type::EffFunction), e(make_shared<eff_fn>(val)) {}
158 : type(Type::EffFunction), e(make_shared<eff_fn>(val)) {}
159
159
160− any(const shared<thunk>& val) : type(Type::Thunk), t(val) {}
161− any(shared<thunk>&& val) : type(Type::Thunk), t(std::move(val)) {}
162−
163 template <typename T>
160 template <typename T>
164− any(const T& val, typename std::enable_if<std::is_assignable<thunk,T>::value>::type* = 0)
161+ any(const T& val, typename std::enable_if<std::is_convertible<T,thunk>::value>::type* = 0)
165− : type(Type::Thunk), t(make_shared<thunk>(val)) {}
162+ : type(Type::Thunk), t(val) {}
166
163
167 template <typename T>
164 template <typename T>
168 any(const T& val, typename std::enable_if<std::is_assignable<shared<void>,T>::value>::type* = 0)
165 any(const T& val, typename std::enable_if<std::is_assignable<shared<void>,T>::value>::type* = 0)
169 : type(Type::Pointer), p(val) {}
166 : type(Type::Pointer), p(val) {}
170
167
171− any(std::nullptr_t) : type(Type::Pointer), p(nullptr) {}
172−
173 template <typename T>
168 template <typename T>
174− any(T&& val, typename std::enable_if<std::is_assignable<shared<void>,T>::value>::type* = 0)
169+ any(T&& val, typename std::enable_if<std::is_assignable<shared<void>,T>::value>::type* = 0) noexcept
175 : type(Type::Pointer), p(std::move(val)) {}
170 : type(Type::Pointer), p(std::move(val)) {}
176
171
177− any(const any&);
172+ any(std::nullptr_t) : type(Type::Pointer), p(nullptr) {}
178−
179− void swap(any&&) const;
180
173
181− any(any&& val) {
174+ any(const any&);
182− swap(std::move(val));
175+ any(any&&) noexcept;
183− }
184
176
185− auto operator=(any val) -> any& {
177+ auto operator=(const any&) -> any&;
186− swap(std::move(val));
178+ auto operator=(any&) noexcept -> any&;
187− return *this;
179+ auto operator=(any&&) noexcept -> any&;
188− }
189
180
190 any() = delete;
181 any() = delete;
191 ~any();
182 ~any();
@@ -203,10 +194,7 @@ class any {
203 auto cast() const -> typename std::enable_if<std::is_same<T, bool>::value, T>::type;
194 auto cast() const -> typename std::enable_if<std::is_same<T, bool>::value, T>::type;
204
195
205 template <typename T>
196 template <typename T>
206− auto cast() const -> typename std::enable_if<std::is_same<T, string>::value, const T&>::type;
197+ auto cast() const -> typename std::enable_if<std::is_same<T, string>::value, T>::type;
207−
208− template <typename T>
209− auto cast() const -> typename std::enable_if<std::is_same<T, const char*>::value, const T>::type;
210
198
211 template <typename T>
199 template <typename T>
212 auto cast() const -> typename std::enable_if<std::is_same<T, map>::value, const T&>::type;
200 auto cast() const -> typename std::enable_if<std::is_same<T, map>::value, const T&>::type;
@@ -216,19 +204,7 @@ class any {
216
204
217 template <typename T>
205 template <typename T>
218 auto cast() const -> typename std::enable_if<std::is_assignable<shared<void>,T>::value, typename T::element_type*>::type {
206 auto cast() const -> typename std::enable_if<std::is_assignable<shared<void>,T>::value, typename T::element_type*>::type {
219− if (type == Type::Pointer) {
220− return static_cast_shared<typename T::element_type>(p);
207+ return static_cast<typename T::element_type*>(extractPointer());
221− }
222− const any* valuePtr = this;
223− do {
224− assert(valuePtr->type == Type::Thunk);
225− const any& value = (*valuePtr->t)(unthunk);
226− if (value.type == Type::Pointer) {
227− return static_cast_shared<typename T::element_type>(value.p);
228− }
229− valuePtr = &value;
230− } while (valuePtr->type != Type::Unknown);
231− return nullptr;
232 }
208 }
233
209
234 auto operator()(const any&) const -> any;
210 auto operator()(const any&) const -> any;
@@ -241,152 +217,63 @@ class any {
241 operator double() const;
217 operator double() const;
242 operator bool() const;
218 operator bool() const;
243
219
244− operator const string&() const;
220+ operator string() const;
245 operator const map&() const;
221 operator const map&() const;
246 operator const vector&() const;
222 operator const vector&() const;
247
223
248− auto operator[](const map_key_t&) const -> const any&;
224+ auto operator[](const char[]) const -> const any&;
249 auto operator[](const vector::size_type) const -> const any&;
225 auto operator[](const vector::size_type) const -> const any&;
250 auto operator[](const any&) const -> const any&;
226 auto operator[](const any&) const -> const any&;
251
227
228+ auto contains(const char[]) const -> bool;
229+
252− auto extractPointer() const -> const void*;
230+ auto extractPointer() const -> void*;
253−
231+
254− static auto extract_value(const any&) -> const any&;
232+ static auto unthunkVariant(const any&) -> const any&;
255−
233+
256− auto operator==(const any&) const -> bool;
234+ DECLARE_COMPARISON_OPERATOR(==)
257− auto operator==(const long) const -> bool;
235+ DECLARE_COMPARISON_OPERATOR(!=)
258− auto operator==(const double) const -> bool;
236+ DECLARE_COMPARISON_OPERATOR(<)
259− auto operator==(const char) const -> bool;
237+ DECLARE_COMPARISON_OPERATOR(<=)
260− auto operator==(const bool) const -> bool;
238+ DECLARE_COMPARISON_OPERATOR(>)
261− auto operator==(const string&) const -> bool;
239+ DECLARE_COMPARISON_OPERATOR(>=)
262− auto operator==(const char * const) const -> bool;
240+
263−
264− auto operator!=(const any&) const -> bool;
265− auto operator!=(const long) const -> bool;
266− auto operator!=(const double) const -> bool;
267− auto operator!=(const char) const -> bool;
268− auto operator!=(const bool) const -> bool;
269− auto operator!=(const string&) const -> bool;
270− auto operator!=(const char * const) const -> bool;
271−
272− auto operator<(const any&) const -> bool;
273− auto operator<(const long) const -> bool;
274− auto operator<(const double) const -> bool;
275− auto operator<(const char) const -> bool;
276− auto operator<(const bool) const -> bool;
277− auto operator<(const string&) const -> bool;
278− auto operator<(const char * const) const -> bool;
279−
280− auto operator<=(const any&) const -> bool;
281− auto operator<=(const long) const -> bool;
282− auto operator<=(const double) const -> bool;
283− auto operator<=(const char) const -> bool;
284− auto operator<=(const bool) const -> bool;
285− auto operator<=(const string&) const -> bool;
286− auto operator<=(const char * const) const -> bool;
287−
288− auto operator>(const any&) const -> bool;
289− auto operator>(const long) const -> bool;
290− auto operator>(const double) const -> bool;
291− auto operator>(const char) const -> bool;
292− auto operator>(const bool) const -> bool;
293− auto operator>(const string&) const -> bool;
294− auto operator>(const char * const) const -> bool;
295−
296− auto operator>=(const any&) const -> bool;
297− auto operator>=(const long) const -> bool;
298− auto operator>=(const double) const -> bool;
299− auto operator>=(const char) const -> bool;
300− auto operator>=(const bool) const -> bool;
301− auto operator>=(const string&) const -> bool;
302− auto operator>=(const char * const) const -> bool;
303−
304− auto operator+(const any&) const -> any;
305− auto operator+(const long) const -> long;
306− auto operator+(const double) const -> double;
307− auto operator+(const char) const -> char;
308− auto operator+(const string&) const -> string;
309− auto operator+(const char * const) const -> string;
310−
311− auto operator-(const any&) const -> any;
312− auto operator-(const long) const -> long;
313− auto operator-(const double) const -> double;
314− auto operator-(const char) const -> char;
315−
316− auto operator*(const any&) const -> any;
317− auto operator*(const long) const -> long;
318− auto operator*(const double) const -> double;
319−
320− auto operator/(const any&) const -> any;
321− auto operator/(const long) const -> long;
322− auto operator/(const double) const -> double;
323−
324− auto operator%(const any&) const -> any;
325− auto operator%(const long) const -> long;
326−
327− auto operator-() const -> any; // unary negate
328−
329− friend auto operator==(const long, const any&) -> bool;
330− friend auto operator!=(const long, const any&) -> bool;
331− friend auto operator< (const long, const any&) -> bool;
332− friend auto operator<=(const long, const any&) -> bool;
333− friend auto operator> (const long, const any&) -> bool;
334− friend auto operator>=(const long, const any&) -> bool;
335−
336− friend auto operator==(const double, const any&) -> bool;
337− friend auto operator!=(const double, const any&) -> bool;
338− friend auto operator< (const double, const any&) -> bool;
339− friend auto operator<=(const double, const any&) -> bool;
340− friend auto operator> (const double, const any&) -> bool;
341− friend auto operator>=(const double, const any&) -> bool;
342−
343− friend auto operator==(const char, const any&) -> bool;
344− friend auto operator!=(const char, const any&) -> bool;
345− friend auto operator< (const char, const any&) -> bool;
346− friend auto operator<=(const char, const any&) -> bool;
347− friend auto operator> (const char, const any&) -> bool;
348− friend auto operator>=(const char, const any&) -> bool;
349−
350− friend auto operator==(const bool, const any&) -> bool;
351− friend auto operator!=(const bool, const any&) -> bool;
352− friend auto operator< (const bool, const any&) -> bool;
353− friend auto operator<=(const bool, const any&) -> bool;
354− friend auto operator> (const bool, const any&) -> bool;
355− friend auto operator>=(const bool, const any&) -> bool;
356−
357− friend auto operator==(const string&, const any&) -> bool;
358− friend auto operator!=(const string&, const any&) -> bool;
359− friend auto operator< (const string&, const any&) -> bool;
360− friend auto operator<=(const string&, const any&) -> bool;
361− friend auto operator> (const string&, const any&) -> bool;
362− friend auto operator>=(const string&, const any&) -> bool;
363−
364− friend auto operator==(const char* const, const any&) -> bool;
365− friend auto operator!=(const char* const, const any&) -> bool;
366− friend auto operator< (const char* const, const any&) -> bool;
367− friend auto operator<=(const char* const, const any&) -> bool;
368− friend auto operator> (const char* const, const any&) -> bool;
369− friend auto operator>=(const char* const, const any&) -> bool;
370−
371− friend auto operator+(const long, const any&) -> long;
372− friend auto operator-(const long, const any&) -> long;
373− friend auto operator*(const long, const any&) -> long;
374− friend auto operator/(const long, const any&) -> long;
375− friend auto operator%(const long, const any&) -> long;
376−
377− friend auto operator+(const double, const any&) -> double;
378− friend auto operator-(const double, const any&) -> double;
379− friend auto operator*(const double, const any&) -> double;
380− friend auto operator/(const double, const any&) -> double;
381−
382− friend auto operator+(const char, const any&) -> char;
241+ friend auto operator+(const any&, const any&) -> any;
383− friend auto operator-(const char, const any&) -> char;
384−
385− friend auto operator+(const string&, const any&) -> string;
386− friend auto operator+(const char* const, const any&) -> string;
387
242
243+ DECLARE_OPERATOR(+, long, long)
244+ DECLARE_OPERATOR(+, double, double)
245+ DECLARE_OPERATOR(+, char, char)
246+ DECLARE_OPERATOR(+, const char *, std::string)
247+
248+ friend auto operator-(const any&, const any&) -> any;
249+
250+ DECLARE_OPERATOR(-, long, long)
251+ DECLARE_OPERATOR(-, double, double)
252+ DECLARE_OPERATOR(-, char, char)
253+
254+ friend auto operator*(const any&, const any&) -> any;
255+
256+ DECLARE_OPERATOR(*, long, long)
257+ DECLARE_OPERATOR(*, double, double)
258+ DECLARE_OPERATOR(*, char, char)
259+
260+ friend auto operator/(const any&, const any&) -> any;
261+
262+ DECLARE_OPERATOR(/, long, long)
263+ DECLARE_OPERATOR(/, double, double)
264+ DECLARE_OPERATOR(/, char, char)
265+
266+ friend auto operator%(const any&, const any&) -> any;
267+
268+ DECLARE_OPERATOR(%, long, long)
269+ DECLARE_OPERATOR(%, char, char)
270+
271+ friend auto operator-(const any&) -> any; // unary negate
388};
272};
389
273
390} // namespace PureScript
274} // namespace PureScript
391
275
276+#undef DECLARE_OPERATOR
277+#undef DECLARE_COMPARISON_OPERATOR
278+
392#endif // PureScript_HH
279#endif // PureScript_HH
src/Language/PureScript/CodeGen/Cpp.hs+14−12
@@ -145,7 +145,8 @@ moduleToCpp env (Module _ mn imps _ foreigns decls) = do
145 | otherwise = ([], [])
145 | otherwise = ([], [])
146 farg = \x -> (x, Just $ CppAny [CppConst, CppRef])
146 farg = \x -> (x, Just $ CppAny [CppConst, CppRef])
147 fieldLambdas flds
147 fieldLambdas flds
148+ | (f' : fs') <- flds = [CppReturn . maybeRemCaps $
148− | (f' : fs') <- flds = [CppReturn $ CppLambda [CppCaptureAll] (farg <$> [f'])
149+ CppLambda [CppCaptureAll] (farg <$> [f'])
149 (Just $ CppAny [])
150 (Just $ CppAny [])
150 (CppBlock $ fieldLambdas fs')]
151 (CppBlock $ fieldLambdas fs')]
151 | otherwise = [CppReturn (CppObjectLiteral ((ctorKey, CppStringLiteral name) : zip fields' (CppVar <$> fields')))]
152 | otherwise = [CppReturn (CppObjectLiteral ((ctorKey, CppStringLiteral name) : zip fields' (CppVar <$> fields')))]
@@ -155,17 +156,17 @@ moduleToCpp env (Module _ mn imps _ foreigns decls) = do
155 return $ CppVariableIntroduction (identToCpp ident, Just $ CppAny [CppConst]) [] (Just val')
156 return $ CppVariableIntroduction (identToCpp ident, Just $ CppAny [CppConst]) [] (Just val')
156
157
157 -------------------------------------------------------------------------------------------------
158 -------------------------------------------------------------------------------------------------
158− toLambda :: [CppCaptureType] -> Cpp -> Cpp
159+ fnToLambda :: Cpp -> Cpp
159 -------------------------------------------------------------------------------------------------
160 -------------------------------------------------------------------------------------------------
160− toLambda cs (CppFunction name args _ qs body) =
161+ fnToLambda (CppFunction name args _ qs body) =
161 CppVariableIntroduction (name, Just $ CppAny [CppConst])
162 CppVariableIntroduction (name, Just $ CppAny [CppConst])
162 (filter (==CppStatic) qs)
163 (filter (==CppStatic) qs)
163− (Just (CppLambda cs' args (Just $ CppAny []) body))
164+ (Just (CppLambda cs args (Just $ CppAny []) body))
164 where
165 where
165− cs' | (not . null) (qs `intersect` [CppInline, CppStatic]) = []
166+ cs | (not . null) (qs `intersect` [CppInline, CppStatic]) = []
166− | otherwise = cs
167+ | otherwise = [CppCaptureAll]
167− toLambda cs (CppComment com cpp) = CppComment com (toLambda cs cpp)
168+ fnToLambda (CppComment com cpp) = CppComment com (fnToLambda cpp)
168− toLambda _ _ = error "Not a function!"
169+ fnToLambda _ = error "Not a function!"
169
170
170 -------------------------------------------------------------------------------------------------
171 -------------------------------------------------------------------------------------------------
171 asReturnBlock :: Cpp -> Cpp
172 asReturnBlock :: Cpp -> Cpp
@@ -178,8 +179,8 @@ moduleToCpp env (Module _ mn imps _ foreigns decls) = do
178 convertNestedLambdas = everywhereOnCpp go
179 convertNestedLambdas = everywhereOnCpp go
179 where
180 where
180 go :: Cpp -> Cpp
181 go :: Cpp -> Cpp
181− go f@(CppFunction {}) = toLambda [CppCaptureAll] f
182+ go f@(CppFunction {}) = maybeRemCaps $ fnToLambda f
182− go (CppLambda [] args rtyp body) = CppLambda [CppCaptureAll] args rtyp body
183+ go (CppLambda _ args rtyp body) = maybeRemCaps $ CppLambda [CppCaptureAll] args rtyp body
183 go cpp = cpp
184 go cpp = cpp
184
185
185 -------------------------------------------------------------------------------------------------
186 -------------------------------------------------------------------------------------------------
@@ -211,11 +212,12 @@ moduleToCpp env (Module _ mn imps _ foreigns decls) = do
211
212
212 toelem :: Cpp -> (String, Cpp)
213 toelem :: Cpp -> (String, Cpp)
213 toelem (CppFunction name args rtyp _ (CppBlock body)) =
214 toelem (CppFunction name args rtyp _ (CppBlock body)) =
215+ (name, withdict . maybeRemCaps $ CppLambda [CppCaptureAll]
214− (name, withdict $ CppLambda [CppCaptureAll] args rtyp (CppBlock $ (accessor localdict <$> fns) ++ body))
216+ args rtyp (CppBlock $ (accessor localdict <$> fns) ++ body))
215 toelem _ = error "not a function"
217 toelem _ = error "not a function"
216
218
217 withdict :: Cpp -> Cpp
219 withdict :: Cpp -> Cpp
218− withdict cpp' =
220+ withdict cpp' = maybeRemCaps $
219 CppLambda [CppCaptureAll] [(localdict, Just $ CppAny [CppConst, CppRef])]
221 CppLambda [CppCaptureAll] [(localdict, Just $ CppAny [CppConst, CppRef])]
220 (Just $ CppAny [])
222 (Just $ CppAny [])
221 (CppBlock [CppReturn cpp'])
223 (CppBlock [CppReturn cpp'])
src/Language/PureScript/CodeGen/Cpp/File.hs+24−3
@@ -20,7 +20,6 @@ module Language.PureScript.CodeGen.Cpp.File where
20import Data.Maybe
20import Data.Maybe
21
21
22import Language.PureScript.CodeGen.Cpp.AST
22import Language.PureScript.CodeGen.Cpp.AST
23−-- import Language.PureScript.CodeGen.Cpp.Templates
24import Language.PureScript.CodeGen.Cpp.Types
23import Language.PureScript.CodeGen.Cpp.Types
25import Language.PureScript.Names
24import Language.PureScript.Names
26
25
@@ -119,14 +118,36 @@ toBody = catMaybes . map go
119 block = CppBlock [val, CppReturn (CppVar "_value_")]
118 block = CppBlock [val, CppReturn (CppVar "_value_")]
120 lambda = CppLambda [] [("", Just $ thunkMarkerType)] (Just $ CppAny [CppConst, CppRef]) block
119 lambda = CppLambda [] [("", Just $ thunkMarkerType)] (Just $ CppAny [CppConst, CppRef]) block
121 addCaptures :: Cpp -> Cpp
120 addCaptures :: Cpp -> Cpp
121+ addCaptures (CppObjectLiteral objs) = CppObjectLiteral (objlam <$> objs)
122+ where
123+ objlam :: (String, Cpp) -> (String, Cpp)
124+ objlam (name, (CppLambda _ args rty body)) = (name , CppLambda [] args rty $ addCaptures body)
125+ objlam obj = obj
122− addCaptures = everywhereOnCpp addCapture
126+ addCaptures cpps' = everywhereOnCpp addCapture cpps'
123 where
127 where
124 addCapture :: Cpp -> Cpp
128 addCapture :: Cpp -> Cpp
125− addCapture (CppLambda [] args rty body) = CppLambda [CppCaptureAll] args rty body
129+ addCapture (CppLambda _ args rty body) = maybeRemCaps $ CppLambda [CppCaptureAll] args rty body
126 addCapture cpp' = cpp'
130 addCapture cpp' = cpp'
127 go (CppComment comms cpp') | Just commented <- go cpp' = Just (CppComment comms commented)
131 go (CppComment comms cpp') | Just commented <- go cpp' = Just (CppComment comms commented)
128 go _ = Nothing
132 go _ = Nothing
129
133
134+-------------------------------------------------------------------------------------------------
135+maybeRemCaps :: Cpp -> Cpp
136+-------------------------------------------------------------------------------------------------
137+maybeRemCaps (CppLambda [CppCaptureAll] args rtyp body@(CppBlock [CppReturn CppNumericLiteral{}]))
138+ = CppLambda [] args rtyp body
139+maybeRemCaps (CppLambda [CppCaptureAll] args rtyp body@(CppBlock [CppReturn CppStringLiteral{}]))
140+ = CppLambda [] args rtyp body
141+maybeRemCaps (CppLambda [CppCaptureAll] args rtyp body@(CppBlock [CppReturn CppCharLiteral{}]))
142+ = CppLambda [] args rtyp body
143+maybeRemCaps (CppLambda [CppCaptureAll] args rtyp body@(CppBlock [CppReturn CppBooleanLiteral{}]))
144+ = CppLambda [] args rtyp body
145+maybeRemCaps (CppLambda [CppCaptureAll] args rtyp body@(CppBlock [CppReturn CppAccessor{}]))
146+ = CppLambda [] args rtyp body
147+maybeRemCaps (CppLambda [CppCaptureAll] args rtyp body@(CppBlock [CppReturn (CppVar "unit")])) -- TODO: not really safe
148+ = CppLambda [] args rtyp body
149+maybeRemCaps cpp = cpp
150+
130---------------------------------------------------------------------------------------------------
151---------------------------------------------------------------------------------------------------
131
152
132fileBegin :: ModuleName -> String -> [Cpp]
153fileBegin :: ModuleName -> String -> [Cpp]
src/Language/PureScript/Pretty/Cpp.hs+11−4
@@ -75,9 +75,9 @@ literals = mkPattern' match
75 [ return $ runType mapType ++ "{\n"
75 [ return $ runType mapType ++ "{\n"
76 , withIndent $ do
76 , withIndent $ do
77 cpps <- forM ps $ \(key, value) -> do
77 cpps <- forM ps $ \(key, value) -> do
78− val <- prettyPrintCpp' value
78+ value' <- prettyPrintCpp' value
79− k <- prettyPrintCpp' (CppStringLiteral key)
79+ key' <- prettyPrintCpp' (CppStringLiteral key)
80− return $ "{ " ++ "KEY" ++ parens k ++ ", " ++ val ++ " }"
80+ return $ "{ " ++ key' ++ ", " ++ value' ++ " }"
81 indentString <- currentIndent
81 indentString <- currentIndent
82 return $ intercalate ", \n" $ map (indentString ++) cpps
82 return $ intercalate ", \n" $ map (indentString ++) cpps
83 , return "\n"
83 , return "\n"
@@ -214,6 +214,13 @@ literals = mkPattern' match
214 , return $ if null cpps then "" else "\n"
214 , return $ if null cpps then "" else "\n"
215 , prettyStatements cpps
215 , prettyStatements cpps
216 ]
216 ]
217+ match (CppReturn value@(CppStringLiteral _)) = fmap concat $ sequence
218+ [ return "return "
219+ , return . runType $ CppAny []
220+ , return "("
221+ , prettyPrintCpp' value
222+ , return ")"
223+ ]
217 match (CppReturn value) = fmap concat $ sequence
224 match (CppReturn value) = fmap concat $ sequence
218 [ return "return "
225 [ return "return "
219 , prettyPrintCpp' value
226 , prettyPrintCpp' value
@@ -299,7 +306,7 @@ indexer = mkPattern' match
299 match (CppIndexer (CppNumericLiteral (Left index)) val) = return (show index ++ "UL", val)
306 match (CppIndexer (CppNumericLiteral (Left index)) val) = return (show index ++ "UL", val)
300 match (CppIndexer index val) = do
307 match (CppIndexer index val) = do
301 index' <- prettyPrintCpp' index
308 index' <- prettyPrintCpp' index
302− return ("KEY" ++ parens index', val)
309+ return (index', val)
303 match _ = mzero
310 match _ = mzero
304
311
305lam :: Pattern PrinterState Cpp ((String, [(String, Maybe CppType)], Maybe CppType), Cpp)
312lam :: Pattern PrinterState Cpp ((String, [(String, Maybe CppType)], Maybe CppType), Cpp)