git.iko.soy/rowtype-yoga/purescript-native
on golang help sign in
Merge branch 'pure11' of github.com:pure11/purescript into pure11
commitf94dba1f7c50fb2ad54a85a0927f37aad0dcc492 authorAndy Arvanitis <andyarvanitis@gmail.com> dateSun 31 Jan 2016, 16:32 (11 years ago) parent07eacbd2bd16c2
7 files changed+559−696
pcc/include/purescript.cc+338−416 pcc/include/purescript.hh+151−246 src/Language/PureScript/CodeGen/Cpp.hs+28−21 src/Language/PureScript/CodeGen/Cpp/Common.hs+1−4 src/Language/PureScript/CodeGen/Cpp/File.hs+25−3 src/Language/PureScript/CodeGen/Cpp/Types.hs+1−1 src/Language/PureScript/Pretty/Cpp.hs+15−5
pcc/include/purescript.cc+338−416
@@ -12,517 +12,439 @@
1212//
1313///////////////////////////////////////////////////////////////////////////////
1414//
15+#include <cstring>
1516#include "PureScript.hh"
1617
1718namespace PureScript {
1819
19−any::any(const any& val) : type(val.type) {
20− switch (type) {
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_ptr (val.p); break;
32−
33− default: assert(false && "Unsupported type in copy ctor");
34− }
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+
58+any::any(const any& other) : type(other.type) {
59+ COPY_DATA(other);
3560}
3661
37−void any::swap(any&& val) {
38− type = val.type;
39− switch (type) {
40− case Type::Integer: i = val.i; break;
41− case Type::Double: d = val.d; break;
42− case Type::Character: c = val.c; break;
43− case Type::Boolean: b = val.b; break;
44− case Type::String: new (&s) shared_string (std::move(val.s)); break;
45− case Type::Map: new (&m) shared_map (std::move(val.m)); break;
46− case Type::Vector: new (&v) shared_vector (std::move(val.v)); break;
47− case Type::Function: new (&f) shared_fn (std::move(val.f)); break;
48− case Type::EffFunction: new (&e) shared_eff_fn (std::move(val.e)); break;
49− case Type::Thunk: new (&t) shared_thunk (std::move(val.t)); break;
50− case Type::Pointer: new (&p) shared_void_ptr (std::move(val.p)); break;
51−
52− default: assert(false && "Unsupported type in move ctor");
53− }
62+any::any(any&& other) noexcept : type(other.type) {
63+ MOVE_DATA(other);
64+}
65+
66+auto any::operator=(const any& rhs) -> any& {
67+ type = rhs.type;
68+ COPY_DATA(rhs);
69+ return *this;
70+}
71+
72+// Takes ownership -- might need to reconsider this
73+auto any::operator=(any& rhs) noexcept -> any& {
74+ type = rhs.type;
75+ MOVE_DATA(rhs);
76+ return *this;
77+}
78+
79+auto any::operator=(any&& rhs) noexcept -> any& {
80+ type = rhs.type;
81+ MOVE_DATA(rhs);
82+ return *this;
5483}
5584
5685any::~any() {
57− // std::cout << "destroy" << std::endl;
5886 switch (type) {
59− case Type::Integer: ; break;
60− case Type::Double: ; break;
61− case Type::Character: ; break;
62− case Type::Boolean: ; break;
63− case Type::String: s.~shared_string(); break;
64− case Type::Map: m.~shared_map(); break;
65− case Type::Vector: v.~shared_vector(); break;
66− case Type::Function: f.~shared_fn(); break;
67− case Type::EffFunction: e.~shared_eff_fn(); break;
68− case Type::Thunk: t.~shared_thunk(); break;
69− case Type::Pointer: p.~shared_void_ptr(); break;
87+ case Type::Integer: ; break;
88+ case Type::Double: ; break;
89+ case Type::Character: ; break;
90+ case Type::Boolean: ; break;
91+ case Type::StringLiteral: ; break;
92+ case Type::String: s.~shared<std::string>(); break;
93+ case Type::Map: m.~shared<map>(); break;
94+ case Type::Vector: v.~shared<vector>(); break;
95+ case Type::Function: ; break;
96+ case Type::Closure: l.~shared<closure>(); break;
97+ case Type::EffFunction: e.~shared<eff_fn>(); break;
98+ case Type::Thunk: ; break;
99+ case Type::Pointer: p.~shared<void>(); break;
70100
71101 default: assert(false && "Unsupported type in destructor");
72102 }
73103};
74104
75− #define RETURN_VALUE(TYPE, VAL, FN) \
76− if (type == TYPE) { \
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) { \
84− return FN(value.VAL); \
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− }
105+#define RETURN_VALUE(TYPE, ACCESSOR, INDIRECTION) \
106+ const any& variant = unthunkVariant(*this); \
107+ assert(variant.type == TYPE); \
108+ return INDIRECTION(variant.ACCESSOR); \
154109
155− auto any::operator()(const as_thunk) const -> const any& {
156− assert(type == Type::Thunk);
157− return (*t)(unthunk);
158− }
110+template <typename T>
111+auto any::cast() const -> typename std::enable_if<std::is_same<T, long>::value, T>::type {
112+ RETURN_VALUE(Type::Integer, i,)
113+}
114+template auto any::cast<long>() const -> long;
159115
160− auto any::operator()() const -> any {
161− if (type == Type::EffFunction) {
162− return (*e)();
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− }
171− valuePtr = &value;
172− } while (valuePtr->type != Type::Unknown);
173− return nullptr;
174− }
116+template <typename T>
117+auto any::cast() const -> typename std::enable_if<std::is_same<T, double>::value, T>::type {
118+ RETURN_VALUE(Type::Double, d,)
119+}
120+template auto any::cast<double>() const -> double;
175121
176− any::operator long() const {
177− RETURN_VALUE(Type::Integer, i,)
178− }
122+template <typename T>
123+auto any::cast() const -> typename std::enable_if<std::is_same<T, char>::value, T>::type {
124+ RETURN_VALUE(Type::Character, c,)
125+}
126+template auto any::cast<char>() const -> char;
179127
180− any::operator double() const {
181− RETURN_VALUE(Type::Double, d,)
182− }
128+template <typename T>
129+auto any::cast() const -> typename std::enable_if<std::is_same<T, bool>::value, T>::type {
130+ RETURN_VALUE(Type::Boolean, b,)
131+}
132+template auto any::cast<bool>() const -> bool;
183133
184− any::operator bool() const {
185− RETURN_VALUE(Type::Boolean, b,)
134+template <typename T>
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;
186139 }
140+ assert(variant.type == Type::String);
141+ return variant.s->c_str();
142+}
143+template auto any::cast<string>() const -> string;
187144
188− any::operator const string&() const {
189− RETURN_VALUE(Type::String, s, *)
190− }
145+template <typename T>
146+auto any::cast() const -> typename std::enable_if<std::is_same<T, map>::value, const T&>::type {
147+ RETURN_VALUE(Type::Map, m, *)
148+}
149+template auto any::cast<any::map>() const -> const map&;
191150
192− any::operator const map&() const {
193− RETURN_VALUE(Type::Map, m, *)
194− }
151+template <typename T>
152+auto any::cast() const -> typename std::enable_if<std::is_same<T, vector>::value, const T&>::type {
153+ RETURN_VALUE(Type::Vector, v, *)
154+}
155+template auto any::cast<any::vector>() const -> const vector&;
195156
196− any::operator const vector&() const {
197− RETURN_VALUE(Type::Vector, v, *)
157+auto any::operator()(const any& arg) const -> any {
158+ const any& variant = unthunkVariant(*this);
159+ if (variant.type == Type::Closure) {
160+ return (*variant.l)(arg);
198161 }
162+ assert(variant.type == Type::Function);
163+ return (*variant.f)(arg);
164+}
199165
200− auto any::extractPointer() const -> const void* {
201− RETURN_VALUE(Type::Pointer, p.get(),)
202− }
166+auto any::operator()(const as_thunk) const -> const any& {
167+ assert(type == Type::Thunk);
168+ return (*t)(unthunk);
169+}
203170
204− auto any::extract_value(const any& a) -> const any& {
205− if (a.type != Type::Thunk) {
206− return a;
207− }
208− const any* valuePtr = &a;
209− do {
210− const any& value = (*valuePtr->t)(unthunk);
211− if (value.type != Type::Thunk) {
212− return value;
213− }
214− valuePtr = &value;
215− } while (true);
216− }
171+auto any::operator()() const -> any {
172+ const any& variant = unthunkVariant(*this);
173+ assert(variant.type == Type::EffFunction);
174+ return (*variant.e)();
175+}
217176
218− auto any::operator[](const char rhs[]) const -> const any& {
219− RETURN_VALUE(Type::Map, m->at(rhs),)
220− }
177+any::operator long() const {
178+ return cast<long>();
179+}
221180
222− auto any::operator[](const vector::size_type rhs) const -> const any& {
223− RETURN_VALUE(Type::Vector, v->at(rhs),)
224− }
181+any::operator double() const {
182+ return cast<double>();
183+}
225184
226− auto any::operator[](const any& rhs) const -> const any& {
227− RETURN_VALUE(Type::Vector, v->at(rhs.cast<long>()),)
228− }
185+any::operator bool() const {
186+ return cast<bool>();
187+}
229188
230−#define DEFINE_OPERATOR_LHS(K, T, OP, V, R, P) \
231−auto operator OP(const T lhs, const any& rhs_) -> R { \
232− auto& rhs = any::extract_value(rhs_); \
233− assert(rhs.type == any::Type::K); \
234− return lhs OP P(rhs.V); \
189+any::operator string() const {
190+ return cast<string>();
235191}
236192
237−#define DEFINE_OPERATOR_RHS(K, T, OP, V, R, P) \
238−auto any::operator OP(const T rhs) const -> R { \
239− auto& lhs = any::extract_value(*this); \
240− assert(lhs.type == Type::K); \
241− return P(lhs.V) OP rhs; \
193+any::operator const map&() const {
194+ return cast<map>();
242195}
243196
244−auto any::operator==(const any& rhs_) const -> bool {
245− auto& lhs = extract_value(*this);
246− auto& 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;
197+any::operator const vector&() const {
198+ return cast<vector>();
258199}
259200
260−DEFINE_OPERATOR_RHS(Integer, long, ==, i, bool,)
261−DEFINE_OPERATOR_RHS(Double, double, ==, d, bool,)
262−DEFINE_OPERATOR_RHS(Character, char, ==, c, bool,)
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, *)
201+auto any::extractPointer() const -> void* {
202+ RETURN_VALUE(Type::Pointer, p.get(),)
203+}
266204
267−auto any::operator!=(const any& rhs_) const -> bool {
268− auto& lhs = extract_value(*this);
269− auto& rhs = extract_value(rhs_);
270− assert(lhs.type == rhs.type);
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");
205+auto any::unthunkVariant(const any& a) -> const any& {
206+ const any * variant = &a;
207+ while (variant->type == Type::Thunk) {
208+ variant = &((*variant->t)(unthunk));
279209 }
280− return false;
210+ return *variant;
281211}
282212
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 {
291− auto& lhs = extract_value(*this);
292− auto& rhs = extract_value(rhs_);
293− assert(lhs.type == rhs.type);
294− switch (lhs.type) {
295− case Type::Integer: return lhs.i < rhs.i;
296− case Type::Double: return lhs.d < rhs.d;
297− case Type::Character: return lhs.c < rhs.c;
298− case Type::Boolean: return lhs.b < rhs.b;
299− case Type::String: return (*lhs.s) < (*rhs.s);
300− default: assert(false && "Unsupported type for '<' operator");
213+auto any::operator[](const char rhs[]) const -> const any& {
214+ const any& variant = unthunkVariant(*this);
215+ assert(variant.type == Type::Map);
216+ const any::map::const_iterator begin = variant.m->begin();
217+ const any::map::const_iterator end = variant.m->end();
218+ for (any::map::const_iterator it = begin; it != end; ++it) {
219+ if (it->first == rhs) {
220+ return it->second;
221+ }
301222 }
302− return false;
223+ for (any::map::const_iterator it = begin; it != end; ++it) {
224+ if (strcmp(it->first, rhs) == 0) {
225+ return it->second;
226+ }
227+ }
228+ throw runtime_error("map key not found");
303229}
304230
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 {
313− auto& lhs = extract_value(*this);
314− auto& rhs = extract_value(rhs_);
315− assert(lhs.type == rhs.type);
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);
322− default: assert(false && "Unsupported type for '<' operator");
323− }
324− return false;
231+auto any::operator[](const vector::size_type rhs) const -> const any& {
232+ const any& variant = unthunkVariant(*this);
233+ assert(variant.type == Type::Vector);
234+ return (*variant.v)[rhs];
325235}
326236
327−DEFINE_OPERATOR_RHS(Integer, long, <=, i, bool,)
328−DEFINE_OPERATOR_RHS(Double, double, <=, d, bool,)
329−DEFINE_OPERATOR_RHS(Character, char, <=, c, bool,)
330−DEFINE_OPERATOR_RHS(Boolean, bool, <=, b, bool,)
331−DEFINE_OPERATOR_RHS(String, string&, <=, s, bool, *)
332−DEFINE_OPERATOR_RHS(String, char* const, <=, s, bool, *)
237+auto any::operator[](const any& rhs) const -> const any& {
238+ const any& variant = unthunkVariant(*this);
239+ assert(variant.type == Type::Vector);
240+ return (*variant.v)[rhs.cast<long>()];
241+}
333242
334−auto any::operator>(const any& rhs_) const -> bool {
335− auto& lhs = extract_value(*this);
336− auto& rhs = extract_value(rhs_);
337− assert(lhs.type == rhs.type);
338− switch (lhs.type) {
339− case Type::Integer: return lhs.i > rhs.i;
340− case Type::Double: return lhs.d > rhs.d;
341− case Type::Character: return lhs.c > rhs.c;
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");
243+auto any::contains(const char key[]) const -> bool {
244+ const any& variant = unthunkVariant(*this);
245+ assert(variant.type == Type::Map);
246+ for (any::map::const_iterator it = variant.m->begin(), end = variant.m->end(); it != end; ++it) {
247+ if (it->first == key || strcmp(it->first, key) == 0) {
248+ return true;
249+ }
345250 }
346251 return false;
347252}
348253
349−DEFINE_OPERATOR_RHS(Integer, long, >, i, bool,)
350−DEFINE_OPERATOR_RHS(Double, double, >, d, bool,)
351−DEFINE_OPERATOR_RHS(Character, char, >, c, bool,)
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, *)
254+//-----------------------------------------------------------------------------
255+// Operator helper macros
256+//-----------------------------------------------------------------------------
355257
356−auto any::operator>=(const any& rhs_) const -> bool {
357− auto& lhs = extract_value(*this);
358− auto& rhs = extract_value(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− }
368− return false;
258+#define DEFINE_OPERATOR(op, ty, rty) \
259+auto operator op (const any& lhs, ty rhs) -> rty { \
260+ return lhs.cast<typename std::remove_const<std::remove_reference<ty>::type>::type>() op rhs; \
261+} \
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>(); \
369264}
370265
371−DEFINE_OPERATOR_RHS(Integer, long, >=, i, bool,)
372−DEFINE_OPERATOR_RHS(Double, double, >=, d, bool,)
373−DEFINE_OPERATOR_RHS(Character, char, >=, c, bool,)
374−DEFINE_OPERATOR_RHS(Boolean, bool, >=, b, bool,)
375−DEFINE_OPERATOR_RHS(String, string&, >=, s, bool, *)
376−DEFINE_OPERATOR_RHS(String, char* const, >=, s, bool, *)
377−
378−auto any::operator+(const any& rhs_) const -> any {
379− auto& lhs = extract_value(*this);
380− auto& rhs = extract_value(rhs_);
381− assert(lhs.type == rhs.type);
266+#define DEFINE_CSTR_EQUALS_OPERATOR() \
267+ auto operator==(const any& lhs_, const char * rhs) -> bool { \
268+ const any& lhs = any::unthunkVariant(lhs_); \
269+ assert(lhs.type == any::Type::StringLiteral || lhs.type == any::Type::String); \
270+ if (lhs.type == any::Type::StringLiteral) { \
271+ return (lhs.r == rhs) || (strcmp(lhs.r, rhs) == 0); \
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+
337+auto operator+(const any& lhs_, const any& rhs_) -> any {
338+ const any& lhs = any::unthunkVariant(lhs_);
339+ const any& rhs = any::unthunkVariant(rhs_);
382340 switch (lhs.type) {
383− case Type::Integer: return lhs.i + rhs.i;
384− case Type::Double: return lhs.d + rhs.d;
385− case Type::Character: return any(char(lhs.c + rhs.c));
386− case Type::String: return (*lhs.s) + (*rhs.s);
341+ case any::Type::Integer: assert(lhs.type == any::Type::Integer); return lhs.i + rhs.i;
342+ case any::Type::Double: assert(lhs.type == any::Type::Double); return lhs.d + rhs.d;
343+ case any::Type::Character: assert(lhs.type == any::Type::Character); return any(char(lhs.c + rhs.c));
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;
387352 default: assert(false && "Unsupported type for '+' operator");
388353 }
389354 return nullptr;
390355}
391356
392−DEFINE_OPERATOR_RHS(Integer, long, +, i, long,)
393−DEFINE_OPERATOR_RHS(Double, double, +, d, double,)
394−DEFINE_OPERATOR_RHS(Character, char, +, c, char,)
395−DEFINE_OPERATOR_RHS(String, string&, +, s, string, *)
396−DEFINE_OPERATOR_RHS(String, char* const, +, s, string, *)
357+DEFINE_OPERATOR(+, long, long)
358+DEFINE_OPERATOR(+, double, double)
359+DEFINE_OPERATOR(+, char, char)
360+
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+}
397372
398−auto any::operator-(const any& rhs_) const -> any {
399− auto& lhs = extract_value(*this);
400− auto& rhs = extract_value(rhs_);
373+auto operator-(const any& lhs_, const any& rhs_) -> any {
374+ const any& lhs = any::unthunkVariant(lhs_);
375+ const any& rhs = any::unthunkVariant(rhs_);
401376 assert(lhs.type == rhs.type);
402377 switch (lhs.type) {
403− case Type::Integer: return lhs.i - rhs.i;
404− case Type::Double: return lhs.d - rhs.d;
405− case Type::Character: return any(char(lhs.c - rhs.c));
406− default: assert(false && "Unsupported type for '-' binary operator");
378+ case any::Type::Integer: return lhs.i - rhs.i;
379+ case any::Type::Double: return lhs.d - rhs.d;
380+ case any::Type::Character: return any(char(lhs.c - rhs.c));
381+ default: assert(false && "Unsupported type for '-' operator");
407382 }
408383 return nullptr;
409384}
410385
411−DEFINE_OPERATOR_RHS(Integer, long, -, i, long,)
412−DEFINE_OPERATOR_RHS(Double, double, -, d, double,)
413−DEFINE_OPERATOR_RHS(Character, char, -, c, char,)
386+DEFINE_OPERATOR(-, long, long)
387+DEFINE_OPERATOR(-, double, double)
388+DEFINE_OPERATOR(-, char, char)
414389
415−auto any::operator*(const any& rhs_) const -> any {
416− auto& lhs = extract_value(*this);
417− auto& rhs = extract_value(rhs_);
390+auto operator*(const any& lhs_, const any& rhs_) -> any {
391+ const any& lhs = any::unthunkVariant(lhs_);
392+ const any& rhs = any::unthunkVariant(rhs_);
418393 assert(lhs.type == rhs.type);
419394 switch (lhs.type) {
420− case Type::Integer: return lhs.i * rhs.i;
421− case Type::Double: return lhs.d * rhs.d;
395+ case any::Type::Integer: return lhs.i * rhs.i;
396+ case any::Type::Double: return lhs.d * rhs.d;
397+ case any::Type::Character: return any(char(lhs.c * rhs.c));
422398 default: assert(false && "Unsupported type for '*' operator");
423399 }
424400 return nullptr;
425401}
426402
427−DEFINE_OPERATOR_RHS(Integer, long, *, i, long,)
428−DEFINE_OPERATOR_RHS(Double, double, *, d, double,)
403+DEFINE_OPERATOR(*, long, long)
404+DEFINE_OPERATOR(*, double, double)
405+DEFINE_OPERATOR(*, char, char)
429406
430−auto any::operator/(const any& rhs_) const -> any {
431− auto& lhs = extract_value(*this);
432− auto& rhs = extract_value(rhs_);
407+auto operator/(const any& lhs_, const any& rhs_) -> any {
408+ const any& lhs = any::unthunkVariant(lhs_);
409+ const any& rhs = any::unthunkVariant(rhs_);
433410 assert(lhs.type == rhs.type);
434411 switch (lhs.type) {
435− case Type::Integer: return lhs.i / rhs.i;
436− case Type::Double: return lhs.d / rhs.d;
412+ case any::Type::Integer: return lhs.i / rhs.i;
413+ case any::Type::Double: return lhs.d / rhs.d;
414+ case any::Type::Character: return any(char(lhs.c / rhs.c));
437415 default: assert(false && "Unsupported type for '/' operator");
438416 }
439417 return nullptr;
440418}
441419
442−DEFINE_OPERATOR_RHS(Integer, long, /, i, long,)
443−DEFINE_OPERATOR_RHS(Double, double, /, d, double,)
420+DEFINE_OPERATOR(/, long, long)
421+DEFINE_OPERATOR(/, double, double)
422+DEFINE_OPERATOR(/, char, char)
444423
445−auto any::operator%(const any& rhs_) const -> any {
446− auto& lhs = extract_value(*this);
447− auto& rhs = extract_value(rhs_);
424+auto operator%(const any& lhs_, const any& rhs_) -> any {
425+ const any& lhs = any::unthunkVariant(lhs_);
426+ const any& rhs = any::unthunkVariant(rhs_);
448427 assert(lhs.type == rhs.type);
449428 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));
451431 default: assert(false && "Unsupported type for '%' operator");
452432 }
453433 return nullptr;
454434}
455435
456−DEFINE_OPERATOR_RHS(Integer, long, %, i, long,)
436+DEFINE_OPERATOR(%, long, long)
437+DEFINE_OPERATOR(%, char, char)
457438
458−auto any::operator-() const -> any {
459− auto& lhs = any::extract_value(*this);
460− switch (lhs.type) {
461− case Type::Integer: return (- lhs.i);
462− case Type::Double: return (- lhs.d);
439+// unary negate
440+auto operator-(const any& rhs_) -> any {
441+ const any& rhs = any::unthunkVariant(rhs_);
442+ switch (rhs.type) {
443+ case any::Type::Integer: return (- rhs.i);
444+ case any::Type::Double: return (- rhs.d);
463445 default: assert(false && "Unsupported type for unary '-' operator");
464446 }
465447 return nullptr;
466448}
467449
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−
528450} // namespace PureScript
pcc/include/purescript.hh+151−246
@@ -29,93 +29,121 @@
2929#include <functional>
3030#include <string>
3131#include <vector>
32−#include <unordered_map>
32+#include <utility>
3333#include <stdexcept>
3434
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+
46+
3547namespace PureScript {
3648
37−using string = std::string;
38−using runtime_error = std::runtime_error;
49+using string = const char *;
3950using nullptr_t = std::nullptr_t;
4051
41−const bool undefined = false;
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+};
4257
43−// TODO: deprecated -- remove
44−#define KEY(k) k
58+const bool undefined = false;
59+const std::vector<int>::size_type kDataCtor = 0;
4560
4661// A variant data class designed to provide some features of dynamic typing.
4762//
4863class any {
4964
5065 public:
51− enum class Type : std::int8_t {
66+ enum class Type : int8_t {
5267 Unknown,
5368 Integer,
5469 Double,
5570 Character,
5671 Boolean,
72+ StringLiteral,
5773 String,
5874 Map,
5975 Vector,
6076 Function,
77+ Closure,
6178 EffFunction,
6279 Thunk,
6380 Pointer
6481 };
6582
66− Type type = Type::Unknown;
83+ mutable Type type = Type::Unknown;
6784
6885 struct as_thunk {
6986 };
7087 static constexpr as_thunk unthunk = as_thunk{};
7188
72− using map = std::unordered_map<std::string, const any>;
73− using vector = std::vector<any>;
74− using fn = std::function<any(const any&)>;
75− using eff_fn = std::function<any()>;
76− using thunk = std::function<const any& (const as_thunk)>;
77−
78− using shared_string = std::shared_ptr<string>;
79− using shared_map = std::shared_ptr<map>;
80− using shared_vector = std::shared_ptr<vector>;
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&;
8193
82− using shared_fn = std::shared_ptr<fn>;
83− using shared_eff_fn = std::shared_ptr<eff_fn>;
84− using shared_thunk = std::shared_ptr<thunk>;
94+ class closure {
95+ public:
96+ virtual auto operator()(const any&) const -> any = 0;
97+ };
8598
8699 template <typename T>
87− using shared = std::shared_ptr<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+ };
88108
89− using shared_void_ptr = std::shared_ptr<void>;
109+ class eff_fn {
110+ public:
111+ virtual auto operator()() const -> any = 0;
112+ };
90113
91114 template <typename T>
92− static constexpr auto make_shared(const T& arg) -> shared<T> {
93− return std::make_shared<T>(arg);
94− }
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+ };
95123
96124 template <typename T>
97− static constexpr auto make_shared(T&& arg) -> shared<T> {
98− return std::make_shared<T>(std::move(arg));
99− }
125+ using shared = std::shared_ptr<T>;
100126
101− template <typename T, typename U>
102− static constexpr auto static_cast_shared(U arg) -> T* {
103− return static_cast<T*>(arg.get());
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)...);
104130 }
105131
106132 private:
107133 union {
108− long i;
109− double d;
110− char c;
111− bool b;
112− shared_string s;
113− shared_map m;
114− shared_vector v;
115− shared_fn f;
116− shared_eff_fn e;
117− shared_thunk t;
118− shared_void_ptr p;
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;
119147 };
120148
121149 public:
@@ -123,80 +151,61 @@ class any {
123151 any(const long val) : type(Type::Integer), i(val) {}
124152 any(const int val) : type(Type::Integer), i(val) {}
125153 any(const unsigned int val) : type(Type::Integer), i(val) {}
126−
127154 any(const double val) : type(Type::Double), d(val) {}
128−
129155 any(const char val) : type(Type::Character), c(val) {}
130156
131− any(const bool val) : type(Type::Boolean), b(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) {}
132159
133− any(const string& val) : type(Type::String), s(make_shared<string>(val)) {}
134− any(string&& val) : type(Type::String), s(make_shared<string>(std::move(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)) {}
135163
136− any(const char val[]) : type(Type::String), s(make_shared<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))) {}
137166
138− any(const shared_string& val) : type(Type::String), s(val) {}
139− any(shared_string&& val) : type(Type::String), s(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)) {}
140169
141170 any(const map& val) : type(Type::Map), m(make_shared<map>(val)) {}
142− any(map&& val) : type(Type::Map), m(make_shared<map>(std::move(val))) {}
143−
144− any(const shared_map& val) : type(Type::Map), m(val) {}
145− any(shared_map&& val) : type(Type::Map), m(std::move(val)) {}
171+ any(map&& val) noexcept : type(Type::Map), m(make_shared<map>(std::move(val))) {}
146172
147173 any(const vector& val) : type(Type::Vector), v(make_shared<vector>(val)) {}
148− any(vector&& val) : type(Type::Vector), v(make_shared<vector>(std::move(val))) {}
149−
150− any(const shared_vector& val) : type(Type::Vector), v(val) {}
151− any(shared_vector&& val) : type(Type::Vector), v(std::move(val)) {}
152−
153− any(const shared_fn& val) : type(Type::Function), f(val) {}
154− any(shared_fn&& val) : type(Type::Function), f(std::move(val)) {}
174+ any(vector&& val) noexcept : type(Type::Vector), v(make_shared<vector>(std::move(val))) {}
155175
156176 template <typename T>
157− any(const T& val, typename std::enable_if<std::is_assignable<fn,T>::value>::type* = 0)
158− : type(Type::Function), f(make_shared<fn>(val)) {}
159−
160− // template <typename T>
161− // any(T&& val, typename std::enable_if<std::is_assignable<fn,T>::value>::type* = 0)
162− // : type(Type::Function), f(std::move(val)) {}
177+ any(const T& val, typename std::enable_if<std::is_convertible<T,fn>::value>::type* = 0)
178+ : type(Type::Function), f(val) {}
163179
164− any(const shared_eff_fn& val) : type(Type::EffFunction), e(val) {}
165− any(shared_eff_fn&& val) : type(Type::EffFunction), e(std::move(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)) {}
166184
167185 template <typename T>
168− any(const T& val, typename std::enable_if<std::is_assignable<eff_fn,T>::value>::type* = 0)
169− : type(Type::EffFunction), e(make_shared<eff_fn>(val)) {}
170−
171− any(const shared_thunk& val) : type(Type::Thunk), t(val) {}
172− any(shared_thunk&& val) : type(Type::Thunk), t(std::move(val)) {}
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)) {}
173188
174189 template <typename T>
175− any(const T& val, typename std::enable_if<std::is_assignable<thunk,T>::value>::type* = 0)
176− : type(Type::Thunk), t(make_shared<thunk>(val)) {}
190+ any(const T& val, typename std::enable_if<std::is_convertible<T,thunk>::value>::type* = 0)
191+ : type(Type::Thunk), t(val) {}
177192
178193 template <typename T>
179− any(const T& val, typename std::enable_if<std::is_assignable<shared_void_ptr,T>::value>::type* = 0)
194+ any(const T& val, typename std::enable_if<std::is_assignable<shared<void>,T>::value>::type* = 0)
180195 : type(Type::Pointer), p(val) {}
181196
182− any(std::nullptr_t) : type(Type::Pointer), p(nullptr) {}
183−
184197 template <typename T>
185− any(T&& val, typename std::enable_if<std::is_assignable<shared_void_ptr,T>::value>::type* = 0)
198+ any(T&& val, typename std::enable_if<std::is_assignable<shared<void>,T>::value>::type* = 0) noexcept
186199 : type(Type::Pointer), p(std::move(val)) {}
187200
188− any(const any&);
201+ any(std::nullptr_t) : type(Type::Pointer), p(nullptr) {}
189202
190− void swap(any&&);
203+ any(const any&);
204+ any(any&&) noexcept;
191205
192− any(any&& val) {
193− swap(std::move(val));
194− }
195−
196− auto operator=(any val) -> any& {
197− swap(std::move(val));
198− return *this;
199− }
206+ auto operator=(const any&) -> any&;
207+ auto operator=(any&) noexcept -> any&;
208+ auto operator=(any&&) noexcept -> any&;
200209
201210 any() = delete;
202211 ~any();
@@ -214,10 +223,7 @@ class any {
214223 auto cast() const -> typename std::enable_if<std::is_same<T, bool>::value, T>::type;
215224
216225 template <typename T>
217− auto cast() const -> typename std::enable_if<std::is_same<T, string>::value, const T&>::type;
218−
219− template <typename T>
220− auto cast() const -> typename std::enable_if<std::is_same<T, const char*>::value, const T>::type;
226+ auto cast() const -> typename std::enable_if<std::is_same<T, string>::value, T>::type;
221227
222228 template <typename T>
223229 auto cast() const -> typename std::enable_if<std::is_same<T, map>::value, const T&>::type;
@@ -226,23 +232,11 @@ class any {
226232 auto cast() const -> typename std::enable_if<std::is_same<T, vector>::value, const T&>::type;
227233
228234 template <typename T>
229− auto cast() const -> typename std::enable_if<std::is_assignable<shared_void_ptr,T>::value, typename T::element_type*>::type {
230− if (type == Type::Pointer) {
231− return static_cast_shared<typename T::element_type>(p);
232− }
233− const any* valuePtr = this;
234− do {
235− assert(valuePtr->type == Type::Thunk);
236− const any& value = (*valuePtr->t)(unthunk);
237− if (value.type == Type::Pointer) {
238− return static_cast_shared<typename T::element_type>(value.p);
239− }
240− valuePtr = &value;
241− } while (valuePtr->type != Type::Unknown);
242− return nullptr;
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());
243237 }
244238
245− auto operator()(const any) const -> any;
239+ auto operator()(const any&) const -> any;
246240
247241 auto operator()(const as_thunk) const -> const any&;
248242
@@ -252,152 +246,63 @@ class any {
252246 operator double() const;
253247 operator bool() const;
254248
255− operator const string&() const;
249+ operator string() const;
256250 operator const map&() const;
257251 operator const vector&() const;
258252
259− auto operator[](const char []) const -> const any&;
253+ auto operator[](const char[]) const -> const any&;
260254 auto operator[](const vector::size_type) const -> const any&;
261255 auto operator[](const any&) const -> const any&;
262256
263− auto extractPointer() const -> const void*;
264−
265− static auto extract_value(const any&) -> const any&;
266−
267− auto operator==(const any&) const -> bool;
268− auto operator==(const long) const -> bool;
269− auto operator==(const double) const -> bool;
270− auto operator==(const char) const -> bool;
271− auto operator==(const bool) const -> bool;
272− auto operator==(const string&) const -> bool;
273− auto operator==(const char * const) const -> bool;
274−
275− auto operator!=(const any&) const -> bool;
276− auto operator!=(const long) const -> bool;
277− auto operator!=(const double) const -> bool;
278− auto operator!=(const char) const -> bool;
279− auto operator!=(const bool) const -> bool;
280− auto operator!=(const string&) const -> bool;
281− auto operator!=(const char * const) const -> bool;
282−
283− auto operator<(const any&) const -> bool;
284− auto operator<(const long) const -> bool;
285− auto operator<(const double) const -> bool;
286− auto operator<(const char) const -> bool;
287− auto operator<(const bool) const -> bool;
288− auto operator<(const string&) const -> bool;
289− auto operator<(const char * const) const -> bool;
290−
291− auto operator<=(const any&) const -> bool;
292− auto operator<=(const long) const -> bool;
293− auto operator<=(const double) const -> bool;
294− auto operator<=(const char) const -> bool;
295− auto operator<=(const bool) const -> bool;
296− auto operator<=(const string&) const -> bool;
297− auto operator<=(const char * const) const -> bool;
298−
299− auto operator>(const any&) const -> bool;
300− auto operator>(const long) const -> bool;
301− auto operator>(const double) const -> bool;
302− auto operator>(const char) const -> bool;
303− auto operator>(const bool) const -> bool;
304− auto operator>(const string&) const -> bool;
305− auto operator>(const char * const) const -> bool;
306−
307− auto operator>=(const any&) const -> bool;
308− auto operator>=(const long) const -> bool;
309− auto operator>=(const double) const -> bool;
310− auto operator>=(const char) const -> bool;
311− auto operator>=(const bool) const -> bool;
312− auto operator>=(const string&) const -> bool;
313− auto operator>=(const char * const) const -> bool;
314−
315− auto operator+(const any&) const -> any;
316− auto operator+(const long) const -> long;
317− auto operator+(const double) const -> double;
318− auto operator+(const char) const -> char;
319− auto operator+(const string&) const -> string;
320− auto operator+(const char * const) const -> string;
321−
322− auto operator-(const any&) const -> any;
323− auto operator-(const long) const -> long;
324− auto operator-(const double) const -> double;
325− auto operator-(const char) const -> char;
326−
327− auto operator*(const any&) const -> any;
328− auto operator*(const long) const -> long;
329− auto operator*(const double) const -> double;
330−
331− auto operator/(const any&) const -> any;
332− auto operator/(const long) const -> long;
333− auto operator/(const double) const -> double;
334−
335− auto operator%(const any&) const -> any;
336− auto operator%(const long) const -> long;
337−
338− auto operator-() const -> any; // unary negate
339−
340− friend auto operator==(const long, const any&) -> bool;
341− friend auto operator!=(const long, const any&) -> bool;
342− friend auto operator< (const long, const any&) -> bool;
343− friend auto operator<=(const long, const any&) -> bool;
344− friend auto operator> (const long, const any&) -> bool;
345− friend auto operator>=(const long, const any&) -> bool;
346−
347− friend auto operator==(const double, const any&) -> bool;
348− friend auto operator!=(const double, const any&) -> bool;
349− friend auto operator< (const double, const any&) -> bool;
350− friend auto operator<=(const double, const any&) -> bool;
351− friend auto operator> (const double, const any&) -> bool;
352− friend auto operator>=(const double, const any&) -> bool;
353−
354− friend auto operator==(const char, const any&) -> bool;
355− friend auto operator!=(const char, const any&) -> bool;
356− friend auto operator< (const char, const any&) -> bool;
357− friend auto operator<=(const char, const any&) -> bool;
358− friend auto operator> (const char, const any&) -> bool;
359− friend auto operator>=(const char, const any&) -> bool;
360−
361− friend auto operator==(const bool, const any&) -> bool;
362− friend auto operator!=(const bool, const any&) -> bool;
363− friend auto operator< (const bool, const any&) -> bool;
364− friend auto operator<=(const bool, const any&) -> bool;
365− friend auto operator> (const bool, const any&) -> bool;
366− friend auto operator>=(const bool, const any&) -> bool;
367−
368− friend auto operator==(const string&, const any&) -> bool;
369− friend auto operator!=(const string&, const any&) -> bool;
370− friend auto operator< (const string&, const any&) -> bool;
371− friend auto operator<=(const string&, const any&) -> bool;
372− friend auto operator> (const string&, const any&) -> bool;
373− friend auto operator>=(const string&, const any&) -> bool;
374−
375− friend auto operator==(const char* const, const any&) -> bool;
376− friend auto operator!=(const char* const, const any&) -> bool;
377− friend auto operator< (const char* const, const any&) -> bool;
378− friend auto operator<=(const char* const, const any&) -> bool;
379− friend auto operator> (const char* const, const any&) -> bool;
380− friend auto operator>=(const char* const, const any&) -> bool;
381−
382− friend auto operator+(const long, const any&) -> long;
383− friend auto operator-(const long, const any&) -> long;
384− friend auto operator*(const long, const any&) -> long;
385− friend auto operator/(const long, const any&) -> long;
386− friend auto operator%(const long, const any&) -> long;
387−
388− friend auto operator+(const double, const any&) -> double;
389− friend auto operator-(const double, const any&) -> double;
390− friend auto operator*(const double, const any&) -> double;
391− friend auto operator/(const double, const any&) -> double;
392−
393− friend auto operator+(const char, const any&) -> char;
394− friend auto operator-(const char, const any&) -> char;
395−
396− friend auto operator+(const string&, const any&) -> string;
397− friend auto operator+(const char* const, const any&) -> string;
257+ auto contains(const char[]) const -> bool;
258+
259+ auto extractPointer() const -> void*;
260+
261+ static auto unthunkVariant(const any&) -> const any&;
398262
263+ DECLARE_COMPARISON_OPERATOR(==)
264+ DECLARE_COMPARISON_OPERATOR(!=)
265+ DECLARE_COMPARISON_OPERATOR(<)
266+ DECLARE_COMPARISON_OPERATOR(<=)
267+ DECLARE_COMPARISON_OPERATOR(>)
268+ DECLARE_COMPARISON_OPERATOR(>=)
269+
270+ friend auto operator+(const any&, const any&) -> any;
271+
272+ DECLARE_OPERATOR(+, long, long)
273+ DECLARE_OPERATOR(+, double, double)
274+ DECLARE_OPERATOR(+, char, char)
275+ DECLARE_OPERATOR(+, const char *, std::string)
276+
277+ friend auto operator-(const any&, const any&) -> any;
278+
279+ DECLARE_OPERATOR(-, long, long)
280+ DECLARE_OPERATOR(-, double, double)
281+ DECLARE_OPERATOR(-, char, char)
282+
283+ friend auto operator*(const any&, const any&) -> any;
284+
285+ DECLARE_OPERATOR(*, long, long)
286+ DECLARE_OPERATOR(*, double, double)
287+ DECLARE_OPERATOR(*, char, char)
288+
289+ friend auto operator/(const any&, const any&) -> any;
290+
291+ DECLARE_OPERATOR(/, long, long)
292+ DECLARE_OPERATOR(/, double, double)
293+ DECLARE_OPERATOR(/, char, char)
294+
295+ friend auto operator%(const any&, const any&) -> any;
296+
297+ DECLARE_OPERATOR(%, long, long)
298+ DECLARE_OPERATOR(%, char, char)
299+
300+ friend auto operator-(const any&) -> any; // unary negate
399301};
400302
401303} // namespace PureScript
402304
305+#undef DECLARE_OPERATOR
306+#undef DECLARE_COMPARISON_OPERATOR
307+
403308#endif // PureScript_HH
src/Language/PureScript/CodeGen/Cpp.hs+28−21
@@ -26,6 +26,7 @@ module Language.PureScript.CodeGen.Cpp
2626 , P.prettyPrintCpp
2727 ) where
2828
29+import Data.Char (isLetter)
2930import Data.List
3031import Data.Function (on)
3132import qualified Data.Map as M
@@ -119,7 +120,7 @@ moduleToCpp env (Module _ mn imps _ foreigns decls) = do
119120 block <- asReturnBlock <$> valueToCpp body
120121 let fn' = CppFunction (identToCpp ident)
121122 [(identToCpp arg, Just $ CppAny [CppConst, CppRef])]
122− (Just $ CppAny [CppConst, CppRef])
123+ (Just $ CppAny [])
123124 []
124125 block
125126 return fn'
@@ -139,33 +140,34 @@ moduleToCpp env (Module _ mn imps _ foreigns decls) = do
139140 []
140141 (CppBlock (fieldLambdas fs))
141142 where
142− name = qualifiedToStr (ModuleName []) id (Qualified (Just mn) ident)
143+ name = identToCpp ident
143144 fields' = identToCpp <$> fields
144145 (f, fs) | (f' : fs') <- fields' = ([f'], fs')
145146 | otherwise = ([], [])
146147 farg = \x -> (x, Just $ CppAny [CppConst, CppRef])
147148 fieldLambdas flds
148− | (f' : fs') <- flds = [CppReturn $ CppLambda [CppCaptureAll] (farg <$> [f'])
149+ | (f' : fs') <- flds = [CppReturn . maybeRemCaps $
150+ CppLambda [CppCaptureAll] (farg <$> [f'])
149151 (Just $ CppAny [])
150152 (CppBlock $ fieldLambdas fs')]
151− | otherwise = [CppReturn (CppObjectLiteral ((ctorKey, CppStringLiteral name) : zip fields' (CppVar <$> fields')))]
153+ | otherwise = [CppReturn (CppArrayLiteral (CppStringLiteral name : (CppVar <$> fields')))]
152154
153155 declToCpp _ ident val = do
154156 val' <- valueToCpp val
155157 return $ CppVariableIntroduction (identToCpp ident, Just $ CppAny [CppConst]) [] (Just val')
156158
157159 -------------------------------------------------------------------------------------------------
158− toLambda :: [CppCaptureType] -> Cpp -> Cpp
160+ fnToLambda :: Cpp -> Cpp
159161 -------------------------------------------------------------------------------------------------
160− toLambda cs (CppFunction name args _ qs body) =
162+ fnToLambda (CppFunction name args _ qs body) =
161163 CppVariableIntroduction (name, Just $ CppAny [CppConst])
162164 (filter (==CppStatic) qs)
163− (Just (CppLambda cs' args (Just $ CppAny []) body))
165+ (Just (CppLambda cs args (Just $ CppAny []) body))
164166 where
165− cs' | (not . null) (qs `intersect` [CppInline, CppStatic]) = []
166− | otherwise = cs
167− toLambda cs (CppComment com cpp) = CppComment com (toLambda cs cpp)
168− toLambda _ _ = error "Not a function!"
167+ cs | (not . null) (qs `intersect` [CppInline, CppStatic]) = []
168+ | otherwise = [CppCaptureAll]
169+ fnToLambda (CppComment com cpp) = CppComment com (fnToLambda cpp)
170+ fnToLambda _ = error "Not a function!"
169171
170172 -------------------------------------------------------------------------------------------------
171173 asReturnBlock :: Cpp -> Cpp
@@ -178,8 +180,8 @@ moduleToCpp env (Module _ mn imps _ foreigns decls) = do
178180 convertNestedLambdas = everywhereOnCpp go
179181 where
180182 go :: Cpp -> Cpp
181− go f@(CppFunction {}) = toLambda [CppCaptureAll] f
182− go (CppLambda [] args rtyp body) = CppLambda [CppCaptureAll] args rtyp body
183+ go f@(CppFunction {}) = maybeRemCaps $ fnToLambda f
184+ go (CppLambda _ args rtyp body) = maybeRemCaps $ CppLambda [CppCaptureAll] args rtyp body
183185 go cpp = cpp
184186
185187 -------------------------------------------------------------------------------------------------
@@ -211,11 +213,12 @@ moduleToCpp env (Module _ mn imps _ foreigns decls) = do
211213
212214 toelem :: Cpp -> (String, Cpp)
213215 toelem (CppFunction name args rtyp _ (CppBlock body)) =
214− (name, withdict $ CppLambda [CppCaptureAll] args rtyp (CppBlock $ (accessor localdict <$> fns) ++ body))
216+ (name, withdict . maybeRemCaps $ CppLambda [CppCaptureAll]
217+ args rtyp (CppBlock $ (accessor localdict <$> fns) ++ body))
215218 toelem _ = error "not a function"
216219
217220 withdict :: Cpp -> Cpp
218− withdict cpp' =
221+ withdict cpp' = maybeRemCaps $
219222 CppLambda [CppCaptureAll] [(localdict, Just $ CppAny [CppConst, CppRef])]
220223 (Just $ CppAny [])
221224 (CppBlock [CppReturn cpp'])
@@ -399,14 +402,16 @@ moduleToCpp env (Module _ mn imps _ foreigns decls) = do
399402 binderToCpp varName done (ConstructorBinder (_, _, _, Just IsNewtype) _ _ [b]) =
400403 binderToCpp varName done b
401404
402− binderToCpp varName done (ConstructorBinder (_, _, _, Just (IsConstructor ctorType fields)) _ ctor bs) = do
405+ binderToCpp varName done (ConstructorBinder (_, _, _, Just (IsConstructor ctorType fields))
406+ _
407+ (Qualified _ (ProperName ctor))
408+ bs) = do
403409 cpps <- go (zip fields bs) done
404− let ctor' = qualifiedToStr (ModuleName []) (Ident . runProperName) ctor
405410 return $ case ctorType of
406411 ProductType -> cpps
407412 SumType ->
408− [ CppIfElse (CppBinary Equal (CppIndexer (CppStringLiteral ctorKey) (CppVar varName))
409− (CppStringLiteral ctor'))
413+ [ CppIfElse (CppBinary Equal (CppIndexer (CppVar ctorKey) (CppVar varName))
414+ (CppStringLiteral ctor))
410415 (CppBlock cpps)
411416 Nothing ]
412417 where
@@ -418,8 +423,10 @@ moduleToCpp env (Module _ mn imps _ foreigns decls) = do
418423 cpps <- binderToCpp argVar done'' binder
419424 return (CppVariableIntroduction (argVar, Nothing)
420425 []
421− (Just (CppIndexer (CppStringLiteral $ identToCpp field) (CppVar varName)))
426+ (Just (CppIndexer (fieldToIndex field) (CppVar varName)))
422427 : cpps)
428+ fieldToIndex :: Ident -> Cpp
429+ fieldToIndex = CppNumericLiteral . Left . (+1) . read . dropWhile isLetter . runIdent
423430
424431 binderToCpp _ _ b@(ConstructorBinder{}) =
425432 error $ "Invalid ConstructorBinder in binderToCpp: " ++ show b
@@ -441,7 +448,7 @@ moduleToCpp env (Module _ mn imps _ foreigns decls) = do
441448 Nothing]
442449
443450 literalToBinderCpp varName done (StringLiteral str) =
444− return [CppIfElse (CppBinary Equal (CppCast stringType $ CppVar varName)
451+ return [CppIfElse (CppBinary Equal (CppVar varName)
445452 (CppStringLiteral str))
446453 (CppBlock done)
447454 Nothing]
src/Language/PureScript/CodeGen/Cpp/Common.hs+1−4
@@ -106,7 +106,6 @@ nameIsCppReserved name =
106106 , "decltype"
107107 , "default"
108108 , "delete"
109− , "djb2"
110109 , "do"
111110 , "double"
112111 , "dynamic_cast"
@@ -121,15 +120,13 @@ nameIsCppReserved name =
121120 , "for"
122121 , "friend"
123122 , "goto"
124− , "HASH"
125123 , "if"
126124 , "import"
125+ , "kDataCtor"
127126 , "inline"
128127 , "int"
129− , "KEY"
130128 , "list"
131129 , "long"
132− , "map_key_t"
133130 , "mutable"
134131 , "namespace"
135132 , "new"
src/Language/PureScript/CodeGen/Cpp/File.hs+25−3
@@ -20,7 +20,6 @@ module Language.PureScript.CodeGen.Cpp.File where
2020import Data.Maybe
2121
2222import Language.PureScript.CodeGen.Cpp.AST
23−-- import Language.PureScript.CodeGen.Cpp.Templates
2423import Language.PureScript.CodeGen.Cpp.Types
2524import Language.PureScript.Names
2625
@@ -119,14 +118,37 @@ toBody = catMaybes . map go
119118 block = CppBlock [val, CppReturn (CppVar "_value_")]
120119 lambda = CppLambda [] [("", Just $ thunkMarkerType)] (Just $ CppAny [CppConst, CppRef]) block
121120 addCaptures :: Cpp -> Cpp
122− addCaptures = everywhereOnCpp addCapture
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
126+ addCaptures (CppApp (CppLambda _ [] rty body) []) = CppApp (CppLambda [] [] rty (addCaptures body)) []
127+ addCaptures cpps' = everywhereOnCpp addCapture cpps'
123128 where
124129 addCapture :: Cpp -> Cpp
125− addCapture (CppLambda [] args rty body) = CppLambda [CppCaptureAll] args rty body
130+ addCapture (CppLambda _ args rty body) = maybeRemCaps $ CppLambda [CppCaptureAll] args rty body
126131 addCapture cpp' = cpp'
127132 go (CppComment comms cpp') | Just commented <- go cpp' = Just (CppComment comms commented)
128133 go _ = Nothing
129134
135+-------------------------------------------------------------------------------------------------
136+maybeRemCaps :: Cpp -> Cpp
137+-------------------------------------------------------------------------------------------------
138+maybeRemCaps (CppLambda [CppCaptureAll] args rtyp body@(CppBlock [CppReturn CppNumericLiteral{}]))
139+ = CppLambda [] args rtyp body
140+maybeRemCaps (CppLambda [CppCaptureAll] args rtyp body@(CppBlock [CppReturn CppStringLiteral{}]))
141+ = CppLambda [] args rtyp body
142+maybeRemCaps (CppLambda [CppCaptureAll] args rtyp body@(CppBlock [CppReturn CppCharLiteral{}]))
143+ = CppLambda [] args rtyp body
144+maybeRemCaps (CppLambda [CppCaptureAll] args rtyp body@(CppBlock [CppReturn CppBooleanLiteral{}]))
145+ = CppLambda [] args rtyp body
146+maybeRemCaps (CppLambda [CppCaptureAll] args rtyp body@(CppBlock [CppReturn CppAccessor{}]))
147+ = CppLambda [] args rtyp body
148+maybeRemCaps (CppLambda [CppCaptureAll] args rtyp body@(CppBlock [CppReturn (CppVar "unit")])) -- TODO: not really safe
149+ = CppLambda [] args rtyp body
150+maybeRemCaps cpp = cpp
151+
130152---------------------------------------------------------------------------------------------------
131153
132154fileBegin :: ModuleName -> String -> [Cpp]
src/Language/PureScript/CodeGen/Cpp/Types.hs+1−1
@@ -119,4 +119,4 @@ unthunkMarkerValue :: String
119119unthunkMarkerValue = "any::unthunk"
120120
121121ctorKey :: String
122−ctorKey = "constructor"
122+ctorKey = "kDataCtor"
src/Language/PureScript/Pretty/Cpp.hs+15−5
@@ -75,9 +75,9 @@ literals = mkPattern' match
7575 [ return $ runType mapType ++ "{\n"
7676 , withIndent $ do
7777 cpps <- forM ps $ \(key, value) -> do
78− val <- prettyPrintCpp' value
79− k <- prettyPrintCpp' (CppStringLiteral key)
80− return $ "{ " ++ k ++ ", " ++ val ++ " }"
78+ value' <- prettyPrintCpp' value
79+ key' <- prettyPrintCpp' (CppStringLiteral key)
80+ return $ "{ " ++ key' ++ ", " ++ value' ++ " }"
8181 indentString <- currentIndent
8282 return $ intercalate ", \n" $ map (indentString ++) cpps
8383 , return "\n"
@@ -214,6 +214,13 @@ literals = mkPattern' match
214214 , return $ if null cpps then "" else "\n"
215215 , prettyStatements cpps
216216 ]
217+ match (CppReturn value@(CppStringLiteral _)) = fmap concat $ sequence
218+ [ return "return "
219+ , return . runType $ CppAny []
220+ , return "("
221+ , prettyPrintCpp' value
222+ , return ")"
223+ ]
217224 match (CppReturn value) = fmap concat $ sequence
218225 [ return "return "
219226 , prettyPrintCpp' value
@@ -296,8 +303,11 @@ accessor = mkPattern match
296303indexer :: Pattern PrinterState Cpp (String, Cpp)
297304indexer = mkPattern' match
298305 where
299− match (CppIndexer (CppNumericLiteral (Left index)) val) = return (show index ++ "UL", val)
300− match (CppIndexer index val) = (,) <$> prettyPrintCpp' index <*> pure val
306+ match (CppIndexer (CppNumericLiteral (Left 0)) val) = return ("0UL", val)
307+ match (CppIndexer (CppNumericLiteral (Left index)) val) = return (show index, val)
308+ match (CppIndexer index val) = do
309+ index' <- prettyPrintCpp' index
310+ return (index', val)
301311 match _ = mzero
302312
303313lam :: Pattern PrinterState Cpp ((String, [(String, Maybe CppType)], Maybe CppType), Cpp)