git.iko.soy/rowtype-yoga/purescript-native
on golang help sign in
Merge remote-tracking branch 'pure11/pure11' into native
commitca19d06607738c78b192d9edea69d4eeb46746e5 authorAndy Arvanitis <andyarvanitis@gmail.com> dateMon 31 Oct 2016, 20:59 (10 years ago) parentefc0a45aba280f
9 files changed+313−240
pcc/include/purescript.cc+103−122 pcc/include/purescript.hh+114−81 src/Language/PureScript/CodeGen/Cpp.hs+60−19 src/Language/PureScript/CodeGen/Cpp/AST.hs+11−6 src/Language/PureScript/CodeGen/Cpp/Common.hs+2 src/Language/PureScript/CodeGen/Cpp/File.hs+1−1 src/Language/PureScript/CodeGen/Cpp/Optimizer/MagicDo.hs+1−1 src/Language/PureScript/CodeGen/Cpp/Types.hs+14−4 src/Language/PureScript/Pretty/Cpp.hs+7−6
pcc/include/purescript.cc+103−122
@@ -17,128 +17,109 @@
1717
1818namespace PureScript {
1919
20−#define RETURN_VALUE(TYPE, ACCESSOR, INDIRECTION) \
20+#define RETURN_VALUE(TAG, ACCESSOR, INDIRECTION) \
2121 const any& variant = unthunkVariant(*this); \
22− assert(variant.type == TYPE); \
22+ assert(variant.tag == TAG); \
2323 return INDIRECTION(variant.ACCESSOR); \
2424
2525auto any::operator()(const any& arg) const -> any {
2626 const any& variant = unthunkVariant(*this);
27− if (variant.type == Type::Closure) {
27+ if (variant.tag == tag_t::Closure) {
2828 return (*variant.l)(arg);
2929 }
30− assert(variant.type == Type::Function);
30+ assert(variant.tag == tag_t::Function);
3131 return (*variant.f)(arg);
3232}
3333
3434auto any::operator()(const as_thunk) const -> const any& {
35− assert(type == Type::Thunk);
35+ assert(tag == tag_t::Thunk);
3636 return (*t)(unthunk);
3737}
3838
3939auto any::operator()() const -> any {
4040 const any& variant = unthunkVariant(*this);
41− if (variant.type == Type::EffClosure) {
41+ if (variant.tag == tag_t::EffClosure) {
4242 return (*variant.k)();
4343 }
44− assert(variant.type == Type::EffFunction);
44+ assert(variant.tag == tag_t::EffFunction);
4545 return (*variant.e)();
4646}
4747
4848any::operator int() const {
49− RETURN_VALUE(Type::Integer, i,)
49+ RETURN_VALUE(tag_t::Integer, i,)
5050}
5151
5252any::operator double() const {
53− RETURN_VALUE(Type::Double, d,)
53+ RETURN_VALUE(tag_t::Double, d,)
5454}
5555
5656any::operator bool() const {
57− RETURN_VALUE(Type::Boolean, b,)
57+ RETURN_VALUE(tag_t::Boolean, b,)
5858}
5959
6060any::operator char() const {
61− RETURN_VALUE(Type::Character, c,)
61+ RETURN_VALUE(tag_t::Character, c,)
6262}
6363
6464any::operator cstring() const {
6565 const any& variant = unthunkVariant(*this);
66− if (variant.type == Type::StringLiteral) {
66+ if (variant.tag == tag_t::StringLiteral) {
6767 return variant.r;
6868 }
69− assert(variant.type == Type::String);
69+ assert(variant.tag == tag_t::String);
7070 return variant.s->c_str();
7171}
7272
73−any::operator const map&() const {
74− RETURN_VALUE(Type::Map, m, *)
75−}
76−
77−any::operator const data&() const {
78− RETURN_VALUE(Type::Data, v, *)
79−}
80−
8173any::operator const array&() const {
82− RETURN_VALUE(Type::Array, a, *)
74+ RETURN_VALUE(tag_t::Array, a, *)
8375}
8476
85−auto any::extractPointer() const -> void* {
86− RETURN_VALUE(Type::Pointer, POINTER_FROM_MEMBER(p),)
77+auto any::extractPointer(IF_DEBUG(const any::tag_t t)) const -> void* {
78+ RETURN_VALUE(t, POINTER_FROM_MEMBER(p),)
8779}
8880
8981auto any::unthunkVariant(const any& a) -> const any& {
9082 const any * variant = &a;
91− while (variant->type == Type::Thunk) {
83+ while (variant->tag == tag_t::Thunk) {
9284 variant = &((*variant->t)(unthunk));
9385 }
9486 return *variant;
9587}
9688
97−auto any::operator[](const char rhs[]) const -> const any& {
98− const any& variant = unthunkVariant(*this);
99− assert(variant.type == Type::Map);
100− const auto begin = variant.m->cbegin();
101− const auto end = variant.m->cend();
102− for (auto it = begin; it != end; ++it) {
103− if (it->first == rhs) {
104− return it->second;
105− }
106− }
107− for (auto it = begin; it != end; ++it) {
108− if (strcmp(it->first, rhs) == 0) {
109− return it->second;
89+static const any invalid_key(nullptr);
90+
91+auto any::operator[](const symbol_t key) const -> const any& {
92+ // TODO: assumes at least one element -- safe assumption?
93+ const auto& m = cast<map<unknown_size>>(*this);
94+ std::remove_reference<decltype(m)>::type::size_type i = 0;
95+ do {
96+ if (m[i].first == key) {
97+ return m[i].second;
11098 }
111− }
112− throw runtime_error("map key not found");
99+ } while (m[++i].first != nullptr);
100+ assert(false && "map key not found");
101+ return invalid_key;
113102}
114103
115104auto any::operator[](const size_t rhs) const -> const any& {
116− const any& variant = unthunkVariant(*this);
117− assert(variant.type == Type::Array);
118− return (*variant.a)[rhs];
105+ const auto& xs = cast<array>(*this);
106+ return xs[rhs];
119107}
120108
121109auto any::operator[](const any& rhs) const -> const any& {
122− const any& variant = unthunkVariant(*this);
123− assert(variant.type == Type::Array);
124− return (*variant.a)[cast<int>(rhs)];
110+ const auto& xs = cast<array>(*this);
111+ return xs[cast<int>(rhs)];
125112}
126113
127−auto any::contains(const char key[]) const -> bool {
128− const any& variant = unthunkVariant(*this);
129− assert(variant.type == Type::Map);
130− const auto begin = variant.m->cbegin();
131− const auto end = variant.m->cend();
132− for (auto it = begin; it != end; ++it) {
133− if (it->first == key) {
114+auto any::contains(const symbol_t key) const -> bool {
115+ // TODO: assumes at least one element -- safe assumption?
116+ const auto& m = cast<map<unknown_size>>(*this);
117+ std::remove_reference<decltype(m)>::type::size_type i = 0;
118+ do {
119+ if (m[i].first == key) {
134120 return true;
135121 }
136− }
137− for (auto it = begin; it != end; ++it) {
138− if (strcmp(it->first, key) == 0) {
139− return true;
140− }
141− }
122+ } while (m[++i].first != nullptr);
142123 return false;
143124}
144125
@@ -149,16 +130,16 @@ auto any::contains(const char key[]) const -> bool {
149130#define DEFINE_CSTR_EQUALS_OPERATOR() \
150131 auto operator==(const any& lhs_, const char * rhs) -> bool { \
151132 const any& lhs = any::unthunkVariant(lhs_); \
152− assert(lhs.type == any::Type::StringLiteral || lhs.type == any::Type::String); \
153− if (lhs.type == any::Type::StringLiteral) { \
133+ assert(lhs.tag == any::tag_t::StringLiteral || lhs.tag == any::tag_t::String); \
134+ if (lhs.tag == any::tag_t::StringLiteral) { \
154135 return (lhs.r == rhs) || (strcmp(lhs.r, rhs) == 0); \
155136 } \
156137 return strcmp(lhs.s->c_str(), rhs) == 0; \
157138 } \
158139 auto operator==(const char * lhs, const any& rhs_) -> bool { \
159140 const any& rhs = any::unthunkVariant(rhs_); \
160− assert(rhs.type == any::Type::StringLiteral || rhs.type == any::Type::String); \
161− if (rhs.type == any::Type::StringLiteral) { \
141+ assert(rhs.tag == any::tag_t::StringLiteral || rhs.tag == any::tag_t::String); \
142+ if (rhs.tag == any::tag_t::StringLiteral) { \
162143 return (lhs == rhs.r) || (strcmp(lhs, rhs) == 0); \
163144 } \
164145 return strcmp(lhs, rhs.s->c_str()) == 0; \
@@ -176,21 +157,21 @@ auto any::contains(const char key[]) const -> bool {
176157 auto operator op (const any& lhs_, const any& rhs_) -> bool { \
177158 const any& lhs = any::unthunkVariant(lhs_); \
178159 const any& rhs = any::unthunkVariant(rhs_); \
179− switch (lhs.type) { \
180− case any::Type::Integer: assert(lhs.type == any::Type::Integer); return lhs.i op rhs.i; \
181− case any::Type::Double: assert(lhs.type == any::Type::Double); return lhs.d op rhs.d; \
182− case any::Type::Character: assert(lhs.type == any::Type::Character); return lhs.c op rhs.c; \
183− case any::Type::Boolean: assert(lhs.type == any::Type::Boolean); return lhs.b op rhs.b; \
184− case any::Type::StringLiteral: \
185− assert(lhs.type == any::Type::StringLiteral || lhs.type == any::Type::String); \
186− assert(rhs.type == any::Type::StringLiteral || rhs.type == any::Type::String); \
187− return strcmp(lhs.r, rhs.type == any::Type::StringLiteral ? rhs.r : rhs.s->c_str()) op 0; \
188− case any::Type::String: \
189− assert(lhs.type == any::Type::StringLiteral || lhs.type == any::Type::String); \
190− assert(rhs.type == any::Type::StringLiteral || rhs.type == any::Type::String); \
191− return strcmp(lhs.s->c_str(), rhs.type == any::Type::StringLiteral ? rhs.r : rhs.s->c_str()) op 0; \
192− case any::Type::Pointer: return lhs.p op rhs.p; \
193− default: assert(false && "Unsupported type for operator " #op); \
160+ switch (lhs.tag) { \
161+ case any::tag_t::Integer: assert(lhs.tag == any::tag_t::Integer); return lhs.i op rhs.i; \
162+ case any::tag_t::Double: assert(lhs.tag == any::tag_t::Double); return lhs.d op rhs.d; \
163+ case any::tag_t::Character: assert(lhs.tag == any::tag_t::Character); return lhs.c op rhs.c; \
164+ case any::tag_t::Boolean: assert(lhs.tag == any::tag_t::Boolean); return lhs.b op rhs.b; \
165+ case any::tag_t::StringLiteral: \
166+ assert(lhs.tag == any::tag_t::StringLiteral || lhs.tag == any::tag_t::String); \
167+ assert(rhs.tag == any::tag_t::StringLiteral || rhs.tag == any::tag_t::String); \
168+ return strcmp(lhs.r, rhs.tag == any::tag_t::StringLiteral ? rhs.r : rhs.s->c_str()) op 0; \
169+ case any::tag_t::String: \
170+ assert(lhs.tag == any::tag_t::StringLiteral || lhs.tag == any::tag_t::String); \
171+ assert(rhs.tag == any::tag_t::StringLiteral || rhs.tag == any::tag_t::String); \
172+ return strcmp(lhs.s->c_str(), rhs.tag == any::tag_t::StringLiteral ? rhs.r : rhs.s->c_str()) op 0; \
173+ case any::tag_t::Pointer: return lhs.p op rhs.p; \
174+ default: assert(false && "Unsupported tag for operator " #op); \
194175 } \
195176 return false; \
196177 }
@@ -216,44 +197,44 @@ DEFINE_CSTR_COMPARISON_OPERATOR(>=)
216197auto operator+(const any& lhs_, const any& rhs_) -> any {
217198 const any& lhs = any::unthunkVariant(lhs_);
218199 const any& rhs = any::unthunkVariant(rhs_);
219− switch (lhs.type) {
220− case any::Type::Integer: assert(lhs.type == any::Type::Integer); return lhs.i + rhs.i;
221− case any::Type::Double: assert(lhs.type == any::Type::Double); return lhs.d + rhs.d;
222− case any::Type::Character: assert(lhs.type == any::Type::Character); return any(char(lhs.c + rhs.c));
223− case any::Type::StringLiteral:
224− assert(lhs.type == any::Type::StringLiteral || lhs.type == any::Type::String);
225− assert(rhs.type == any::Type::StringLiteral || rhs.type == any::Type::String);
226− return rhs.type == any::Type::StringLiteral ? std::string(lhs.r) + rhs.r : lhs.r + *rhs.s;
227− case any::Type::String:
228− assert(lhs.type == any::Type::StringLiteral || lhs.type == any::Type::String);
229− assert(rhs.type == any::Type::StringLiteral || rhs.type == any::Type::String);
230− return rhs.type == any::Type::StringLiteral ? *lhs.s + rhs.r : *lhs.s + *rhs.s;
231− default: assert(false && "Unsupported type for '+' operator");
200+ switch (lhs.tag) {
201+ case any::tag_t::Integer: assert(lhs.tag == any::tag_t::Integer); return lhs.i + rhs.i;
202+ case any::tag_t::Double: assert(lhs.tag == any::tag_t::Double); return lhs.d + rhs.d;
203+ case any::tag_t::Character: assert(lhs.tag == any::tag_t::Character); return any(char(lhs.c + rhs.c));
204+ case any::tag_t::StringLiteral:
205+ assert(lhs.tag == any::tag_t::StringLiteral || lhs.tag == any::tag_t::String);
206+ assert(rhs.tag == any::tag_t::StringLiteral || rhs.tag == any::tag_t::String);
207+ return rhs.tag == any::tag_t::StringLiteral ? std::string(lhs.r) + rhs.r : lhs.r + *rhs.s;
208+ case any::tag_t::String:
209+ assert(lhs.tag == any::tag_t::StringLiteral || lhs.tag == any::tag_t::String);
210+ assert(rhs.tag == any::tag_t::StringLiteral || rhs.tag == any::tag_t::String);
211+ return rhs.tag == any::tag_t::StringLiteral ? *lhs.s + rhs.r : *lhs.s + *rhs.s;
212+ default: assert(false && "Unsupported tag for '+' operator");
232213 }
233214 return nullptr;
234215}
235216
236217auto operator+(const any& lhs_, const char * rhs) -> std::string {
237218 const any& lhs = any::unthunkVariant(lhs_);
238− assert(lhs.type == any::Type::StringLiteral || lhs.type == any::Type::String);
239− return lhs.type == any::Type::StringLiteral ? std::string(lhs.r) + rhs : *lhs.s + rhs;
219+ assert(lhs.tag == any::tag_t::StringLiteral || lhs.tag == any::tag_t::String);
220+ return lhs.tag == any::tag_t::StringLiteral ? std::string(lhs.r) + rhs : *lhs.s + rhs;
240221}
241222
242223auto operator+(const char * lhs, const any& rhs_) -> std::string {
243224 const any& rhs = any::unthunkVariant(rhs_);
244− assert(rhs.type == any::Type::StringLiteral || rhs.type == any::Type::String);
245− return rhs.type == any::Type::StringLiteral ? lhs + std::string(rhs.r) : lhs + *rhs.s;
225+ assert(rhs.tag == any::tag_t::StringLiteral || rhs.tag == any::tag_t::String);
226+ return rhs.tag == any::tag_t::StringLiteral ? lhs + std::string(rhs.r) : lhs + *rhs.s;
246227}
247228
248229auto operator-(const any& lhs_, const any& rhs_) -> any {
249230 const any& lhs = any::unthunkVariant(lhs_);
250231 const any& rhs = any::unthunkVariant(rhs_);
251− assert(lhs.type == rhs.type);
252− switch (lhs.type) {
253− case any::Type::Integer: return lhs.i - rhs.i;
254− case any::Type::Double: return lhs.d - rhs.d;
255− case any::Type::Character: return any(char(lhs.c - rhs.c));
256− default: assert(false && "Unsupported type for '-' operator");
232+ assert(lhs.tag == rhs.tag);
233+ switch (lhs.tag) {
234+ case any::tag_t::Integer: return lhs.i - rhs.i;
235+ case any::tag_t::Double: return lhs.d - rhs.d;
236+ case any::tag_t::Character: return any(char(lhs.c - rhs.c));
237+ default: assert(false && "Unsupported tag for '-' operator");
257238 }
258239 return nullptr;
259240}
@@ -261,12 +242,12 @@ auto operator-(const any& lhs_, const any& rhs_) -> any {
261242auto operator*(const any& lhs_, const any& rhs_) -> any {
262243 const any& lhs = any::unthunkVariant(lhs_);
263244 const any& rhs = any::unthunkVariant(rhs_);
264− assert(lhs.type == rhs.type);
265− switch (lhs.type) {
266− case any::Type::Integer: return lhs.i * rhs.i;
267− case any::Type::Double: return lhs.d * rhs.d;
268− case any::Type::Character: return any(char(lhs.c * rhs.c));
269− default: assert(false && "Unsupported type for '*' operator");
245+ assert(lhs.tag == rhs.tag);
246+ switch (lhs.tag) {
247+ case any::tag_t::Integer: return lhs.i * rhs.i;
248+ case any::tag_t::Double: return lhs.d * rhs.d;
249+ case any::tag_t::Character: return any(char(lhs.c * rhs.c));
250+ default: assert(false && "Unsupported tag for '*' operator");
270251 }
271252 return nullptr;
272253}
@@ -274,12 +255,12 @@ auto operator*(const any& lhs_, const any& rhs_) -> any {
274255auto operator/(const any& lhs_, const any& rhs_) -> any {
275256 const any& lhs = any::unthunkVariant(lhs_);
276257 const any& rhs = any::unthunkVariant(rhs_);
277− assert(lhs.type == rhs.type);
278− switch (lhs.type) {
279− case any::Type::Integer: return lhs.i / rhs.i;
280− case any::Type::Double: return lhs.d / rhs.d;
281− case any::Type::Character: return any(char(lhs.c / rhs.c));
282− default: assert(false && "Unsupported type for '/' operator");
258+ assert(lhs.tag == rhs.tag);
259+ switch (lhs.tag) {
260+ case any::tag_t::Integer: return lhs.i / rhs.i;
261+ case any::tag_t::Double: return lhs.d / rhs.d;
262+ case any::tag_t::Character: return any(char(lhs.c / rhs.c));
263+ default: assert(false && "Unsupported tag for '/' operator");
283264 }
284265 return nullptr;
285266}
@@ -287,11 +268,11 @@ auto operator/(const any& lhs_, const any& rhs_) -> any {
287268auto operator%(const any& lhs_, const any& rhs_) -> any {
288269 const any& lhs = any::unthunkVariant(lhs_);
289270 const any& rhs = any::unthunkVariant(rhs_);
290− assert(lhs.type == rhs.type);
291− switch (lhs.type) {
292− case any::Type::Integer: return lhs.i % rhs.i;
293− case any::Type::Character: return any(char(lhs.c % rhs.c));
294− default: assert(false && "Unsupported type for '%' operator");
271+ assert(lhs.tag == rhs.tag);
272+ switch (lhs.tag) {
273+ case any::tag_t::Integer: return lhs.i % rhs.i;
274+ case any::tag_t::Character: return any(char(lhs.c % rhs.c));
275+ default: assert(false && "Unsupported tag for '%' operator");
295276 }
296277 return nullptr;
297278}
@@ -299,10 +280,10 @@ auto operator%(const any& lhs_, const any& rhs_) -> any {
299280// unary negate
300281auto operator-(const any& rhs_) -> any {
301282 const any& rhs = any::unthunkVariant(rhs_);
302− switch (rhs.type) {
303− case any::Type::Integer: return (- rhs.i);
304− case any::Type::Double: return (- rhs.d);
305− default: assert(false && "Unsupported type for unary '-' operator");
283+ switch (rhs.tag) {
284+ case any::tag_t::Integer: return (- rhs.i);
285+ case any::tag_t::Double: return (- rhs.d);
286+ default: assert(false && "Unsupported tag for unary '-' operator");
306287 }
307288 return nullptr;
308289}
pcc/include/purescript.hh+114−81
@@ -20,15 +20,17 @@
2020#if defined(DEBUG)
2121 #include <cassert>
2222 #include <climits>
23+ #define IF_DEBUG(x) x
2324#else
2425 #define NDEBUG
2526 #undef assert
2627 #define assert(x)
28+ #define IF_DEBUG(_)
2729#endif
2830
2931#include <functional>
3032#include <string>
31−#include <vector>
33+#include <array>
3234#include <deque>
3335#include <utility>
3436#include <stdexcept>
@@ -40,21 +42,36 @@ namespace PureScript {
4042using cstring = const char *;
4143using std::nullptr_t;
4244
45+struct symbol_generator_anchor {};
46+using symbol_t = const symbol_generator_anchor *;
47+
48+template <typename T>
49+struct symbol_generator {
50+ constexpr static symbol_generator_anchor anchor = symbol_generator_anchor{};
51+};
52+template <typename T>
53+constexpr symbol_generator_anchor symbol_generator<T>::anchor;
54+
55+#define SYMBOL(S) &symbol_generator<symbol::S>::anchor
56+
4357// Workaround for missing C++11 version in gcc
4458class runtime_error : public std::runtime_error {
4559public:
4660 runtime_error(const char message[]) : std::runtime_error(std::string(message)) {}
4761};
4862
49−const bool undefined = false;
50−const size_t constructor = 0;
63+constexpr bool undefined = false;
64+constexpr size_t constructor = 0;
65+
66+// Not a real limit, just used for simpler accessors
67+static constexpr size_t unknown_size = 64;
5168
5269// A variant data class designed to provide some features of dynamic typing.
5370//
5471class any {
5572
5673 public:
57− enum class Type {
74+ enum class tag_t {
5875 Thunk = 0x10,
5976 Integer,
6077 Double,
@@ -74,16 +91,21 @@ class any {
7491 };
7592
7693 private:
77− mutable Type type;
94+ mutable tag_t tag;
7895
7996 public:
8097 struct as_thunk {
8198 };
8299 static constexpr as_thunk unthunk = as_thunk{};
83100
84− using map_pair = std::pair<const char * const, const any>;
85− using map = std::vector<map_pair WITH_ALLOCATOR(map_pair)>;
86− using data = std::vector<any WITH_ALLOCATOR(any)>;
101+ using map_pair = std::pair<const symbol_t, const any>;
102+
103+ template <size_t N>
104+ using map = std::array<const map_pair, N>;
105+
106+ template <size_t N>
107+ using data = std::array<const any, N>;
108+
87109 using array = std::deque<any WITH_ALLOCATOR(any)>;
88110 using fn = auto (*)(const any&) -> any;
89111 using eff_fn = auto (*)() -> any;
@@ -134,8 +156,6 @@ class any {
134156 mutable eff_fn e;
135157 mutable void * u;
136158 mutable managed<std::string> s;
137− mutable managed<map> m;
138− mutable managed<data> v;
139159 mutable managed<array> a;
140160 mutable managed<closure> l;
141161 mutable managed<eff_closure> k;
@@ -144,74 +164,74 @@ class any {
144164
145165 public:
146166
147− any(const int val) noexcept : type(Type::Integer), i(val) {}
148− any(const long int_value) noexcept : type(Type::Integer), i(int_value) {
167+ any(const int val) noexcept : tag(tag_t::Integer), i(val) {}
168+ any(const long int_value) noexcept : tag(tag_t::Integer), i(int_value) {
149169 assert(int_value >= INT_MIN && int_value <= INT_MAX);
150170 }
151171
152− any(const double val) noexcept : type(Type::Double), d(val) {}
153− any(const char val) noexcept : type(Type::Character), c(val) {}
172+ any(const double val) noexcept : tag(tag_t::Double), d(val) {}
173+ any(const char val) noexcept : tag(tag_t::Character), c(val) {}
154174
155175 template <typename T, typename = typename std::enable_if<std::is_same<bool,T>::value>::type>
156− any(const T val) noexcept : type(Type::Boolean), b(val) {}
176+ any(const T val) noexcept : tag(tag_t::Boolean), b(val) {}
157177
158178 template <size_t N>
159− any(const char (&val)[N]) noexcept : type(Type::StringLiteral), r(val) {}
160− any(char * val) : type(Type::String), s(make_managed<std::string>(val)) {}
179+ any(const char (&val)[N]) noexcept : tag(tag_t::StringLiteral), r(val) {}
180+ any(char * val) : tag(tag_t::String), s(make_managed<std::string>(val)) {}
161181
162− any(const std::string& val) : type(Type::String), s(make_managed<std::string>(val)) {}
163− any(std::string&& val) noexcept : type(Type::String), s(make_managed<std::string>(std::move(val))) {}
182+ any(const std::string& val) : tag(tag_t::String), s(make_managed<std::string>(val)) {}
183+ any(std::string&& val) noexcept : tag(tag_t::String), s(make_managed<std::string>(std::move(val))) {}
164184
165− any(const managed<std::string>& val) noexcept : type(Type::String), s(val) {}
166− any(managed<std::string>&& val) noexcept : type(Type::String), s(std::move(val)) {}
185+ any(const managed<std::string>& val) noexcept : tag(tag_t::String), s(val) {}
186+ any(managed<std::string>&& val) noexcept : tag(tag_t::String), s(std::move(val)) {}
167187
168− any(const map& val) : type(Type::Map), m(make_managed<map>(val)) {}
169− any(map&& val) noexcept : type(Type::Map), m(make_managed<map>(std::move(val))) {}
188+ template <size_t N>
189+ any(map<N>&& val) noexcept : tag(tag_t::Map), p(make_managed<map<N>>(std::move(val))) {}
170190
171− any(const data& val) : type(Type::Data), v(make_managed<data>(val)) {}
172− any(data&& val) noexcept : type(Type::Data), v(make_managed<data>(std::move(val))) {}
191+ template <size_t N>
192+ any(data<N>&& val) noexcept : tag(tag_t::Data), p(make_managed<data<N>>(std::move(val))) {}
173193
174− any(const array& val) : type(Type::Array), a(make_managed<array>(val)) {}
175− any(array&& val) noexcept : type(Type::Array), a(make_managed<array>(std::move(val))) {}
194+ any(const array& val) : tag(tag_t::Array), a(make_managed<array>(val)) {}
195+ any(array&& val) noexcept : tag(tag_t::Array), a(make_managed<array>(std::move(val))) {}
176196
177197 template <typename T>
178198 any(const T& val, typename std::enable_if<std::is_convertible<T,fn>::value>::type* = 0) noexcept
179− : type(Type::Function), f(val) {}
199+ : tag(tag_t::Function), f(val) {}
180200
181201 template <typename T, typename = typename std::enable_if<!std::is_same<any,T>::value &&
182202 !std::is_convertible<T,fn>::value>::type>
183203 any(const T& val, typename std::enable_if<std::is_assignable<std::function<any(const any&)>,T>::value>::type* = 0)
184− : type(Type::Closure), l(make_managed<_closure<T>>(val)) {}
204+ : tag(tag_t::Closure), l(make_managed<_closure<T>>(val)) {}
185205
186206 template <typename T>
187207 any(const T& val, typename std::enable_if<std::is_convertible<T,eff_fn>::value>::type* = 0) noexcept
188− : type(Type::EffFunction), e(val) {}
208+ : tag(tag_t::EffFunction), e(val) {}
189209
190210 template <typename T,
191211 typename = typename std::enable_if<!std::is_same<any,T>::value &&
192212 !std::is_convertible<T,eff_fn>::value>::type>
193213 any(const T& val, typename std::enable_if<std::is_assignable<std::function<any()>,T>::value>::type* = 0)
194− : type(Type::EffClosure), k(make_managed<_eff_closure<T>>(val)) {}
214+ : tag(tag_t::EffClosure), k(make_managed<_eff_closure<T>>(val)) {}
195215
196216 template <typename T>
197217 any(const T& val, typename std::enable_if<std::is_convertible<T,thunk>::value>::type* = 0) noexcept
198− : type(Type::Thunk), t(val) {}
218+ : tag(tag_t::Thunk), t(val) {}
199219
200220 template <typename T,
201221 typename = typename std::enable_if<std::is_class<typename std::remove_pointer<T>::type>::value>::type>
202222 any(const T& val, typename std::enable_if<IS_POINTER_TYPE(T)::value>::type* = 0) noexcept
203− : type(Type::Pointer), p(val) {}
223+ : tag(tag_t::Pointer), p(val) {}
204224
205225 template <typename T>
206226 any(T&& val, typename std::enable_if<std::is_assignable<managed<void>,T>::value>::type* = 0) noexcept
207− : type(Type::Pointer), p(std::move(val)) {}
227+ : tag(tag_t::Pointer), p(std::move(val)) {}
208228
209229 // Explicit void* to raw pointer value
210230 template <typename T>
211231 any(const T& val, typename std::enable_if<std::is_same<T,void*>::value>::type* = 0) noexcept
212− : type(Type::RawPointer), u(val) {}
232+ : tag(tag_t::RawPointer), u(val) {}
213233
214− any(std::nullptr_t) noexcept : type(Type::Pointer), p(nullptr) {}
234+ any(nullptr_t) noexcept : tag(tag_t::RawPointer), u(nullptr) {}
215235
216236
217237#if !defined(USE_GC)
@@ -232,62 +252,62 @@ class any {
232252
233253 template <typename T>
234254 auto assign(T&& other) const noexcept -> void {
235− switch (other.type) {
236− case Type::Thunk: t = other.t; break;
237− case Type::Integer: i = other.i; break;
238− case Type::Double: d = other.d; break;
239− case Type::Character: c = other.c; break;
240− case Type::Boolean: b = other.b; break;
241− case Type::StringLiteral: r = other.r; break;
242− case Type::Function: f = other.f; break;
243− case Type::EffFunction: e = other.e; break;
244− case Type::RawPointer: u = other.u; break;
245−
246− case Type::String: new (&s) managed<std::string>(move_if_rvalue<T>(other.s)); break;
247− case Type::Map: new (&m) managed<map>(move_if_rvalue<T>(other.m)); break;
248− case Type::Data: new (&v) managed<data>(move_if_rvalue<T>(other.v)); break;
249− case Type::Array: new (&a) managed<array>(move_if_rvalue<T>(other.a)); break;
250− case Type::Closure: new (&l) managed<closure>(move_if_rvalue<T>(other.l)); break;
251− case Type::EffClosure: new (&k) managed<eff_closure>(move_if_rvalue<T>(other.k)); break;
252− case Type::Pointer: new (&p) managed<void>(move_if_rvalue<T>(other.p)); break;
253−
254− default: assert(false && "Bad 'any' type"); break;
255+ switch (other.tag) {
256+ case tag_t::Thunk: t = other.t; break;
257+ case tag_t::Integer: i = other.i; break;
258+ case tag_t::Double: d = other.d; break;
259+ case tag_t::Character: c = other.c; break;
260+ case tag_t::Boolean: b = other.b; break;
261+ case tag_t::StringLiteral: r = other.r; break;
262+ case tag_t::Function: f = other.f; break;
263+ case tag_t::EffFunction: e = other.e; break;
264+ case tag_t::RawPointer: u = other.u; break;
265+
266+ case tag_t::String: new (&s) managed<std::string>(move_if_rvalue<T>(other.s)); break;
267+ case tag_t::Array: new (&a) managed<array>(move_if_rvalue<T>(other.a)); break;
268+ case tag_t::Closure: new (&l) managed<closure>(move_if_rvalue<T>(other.l)); break;
269+ case tag_t::EffClosure: new (&k) managed<eff_closure>(move_if_rvalue<T>(other.k)); break;
270+ case tag_t::Map:
271+ case tag_t::Data:
272+ case tag_t::Pointer: new (&p) managed<void>(move_if_rvalue<T>(other.p)); break;
273+
274+ default: assert(false && "Bad 'any' tag"); break;
255275 }
256276 }
257277
258278 auto destruct() -> void {
259− switch (type) {
260− case Type::String: s.~managed<std::string>(); break;
261− case Type::Map: m.~managed<map>(); break;
262− case Type::Data: v.~managed<data>(); break;
263− case Type::Array: a.~managed<array>(); break;
264− case Type::Closure: l.~managed<closure>(); break;
265− case Type::EffClosure: k.~managed<eff_closure>(); break;
266− case Type::Pointer: p.~managed<void>(); break;
279+ switch (tag) {
280+ case tag_t::String: s.~managed<std::string>(); break;
281+ case tag_t::Array: a.~managed<array>(); break;
282+ case tag_t::Closure: l.~managed<closure>(); break;
283+ case tag_t::EffClosure: k.~managed<eff_closure>(); break;
284+ case tag_t::Map:
285+ case tag_t::Data:
286+ case tag_t::Pointer: p.~managed<void>(); break;
267287
268288 default: break;
269289 }
270290 }
271291
272292 public:
273− any(const any& other) noexcept : type(other.type) {
293+ any(const any& other) noexcept : tag(other.tag) {
274294 assign(other);
275295 }
276296
277− any(any&& other) noexcept : type(other.type) {
297+ any(any&& other) noexcept : tag(other.tag) {
278298 assign(std::move(other));
279299 }
280300
281301 auto operator=(const any& rhs) noexcept -> any& {
282302 destruct();
283− type = rhs.type;
303+ tag = rhs.tag;
284304 assign(rhs);
285305 return *this;
286306 }
287307
288308 auto operator=(any&& rhs) noexcept -> any& {
289309 destruct();
290− type = rhs.type;
310+ tag = rhs.tag;
291311 assign(std::move(rhs));
292312 return *this;
293313 }
@@ -309,21 +329,19 @@ class any {
309329 operator bool() const;
310330 operator char() const;
311331 operator cstring() const;
312− operator const map&() const;
313− operator const data&() const;
314332 operator const array&() const;
315333
316− auto operator[](const char[]) const -> const any&;
334+ auto operator[](const symbol_t) const -> const any&;
317335 auto operator[](const size_t) const -> const any&;
318336 auto operator[](const any&) const -> const any&;
319337
320− auto contains(const char[]) const -> bool;
338+ auto contains(const symbol_t) const -> bool;
321339
322− auto extractPointer() const -> void*;
340+ auto extractPointer(IF_DEBUG(const tag_t)) const -> void*;
323341
324342 auto rawPointer() const -> void* {
325343 const any& variant = unthunkVariant(*this);
326− assert(type == Type::RawPointer);
344+ assert(tag == tag_t::RawPointer);
327345 return variant.u;
328346 }
329347
@@ -385,6 +403,25 @@ class any {
385403 DEFINE_OPERATOR(%, char, char)
386404
387405 friend auto operator-(const any&) -> any; // unary negate
406+
407+}; // class any
408+
409+template <typename T, typename U=void>
410+struct tag_helper {};
411+
412+template <size_t N>
413+struct tag_helper<any::map<N>> {
414+ static constexpr any::tag_t tag = any::tag_t::Map;
415+};
416+
417+template <size_t N>
418+struct tag_helper<any::data<N>> {
419+ static constexpr any::tag_t tag = any::tag_t::Data;
420+};
421+
422+template <typename T>
423+struct tag_helper<T> {
424+ static constexpr any::tag_t tag = any::tag_t::Pointer;
388425};
389426
390427template <typename T>
@@ -396,18 +433,14 @@ inline auto cast(const any& a) ->
396433
397434template <typename T>
398435inline auto cast(const any& a) ->
399− typename std::enable_if<std::is_same<T, any::map>::value ||
400− std::is_same<T, any::data>::value ||
401− std::is_same<T, any::array>::value, const T&>::type {
436+ typename std::enable_if<std::is_same<T, any::array>::value, const T&>::type {
402437 return a;
403438}
404439
405440template <typename T, typename = typename std::enable_if<std::is_class<T>::value>::type>
406441inline auto cast(const any& a) ->
407− typename std::enable_if<!std::is_same<T, any::map>::value &&
408− !std::is_same<T, any::data>::value &&
409− !std::is_same<T, any::array>::value, T&>::type {
410− return *static_cast<T*>(a.extractPointer());
442+ typename std::enable_if<!std::is_same<T, any::array>::value, T&>::type {
443+ return *static_cast<T*>(a.extractPointer(IF_DEBUG(tag_helper<T>::tag)));
411444}
412445
413446template <typename T>
src/Language/PureScript/CodeGen/Cpp.hs+60−19
@@ -71,16 +71,17 @@ moduleToCpp env (Module _ mn imps _ foreigns decls) = do
7171 (snd <$> imps)
7272 let cppImports' = "PureScript" : cppImports
7373 cppDecls <- concat <$> mapM (bindToCpp [CppTopLevel]) decls
74− let namesmap = M.toList .
74+ let cpps = filterInlineFuncs <$> cppDecls
75+ namesmap = M.toList .
7576 M.mapKeysMonotonic (qualifiedToCpp id) . M.map (\(t, _, _) -> arity t) $
7677 E.names env
7778 datamap = M.toList .
7879 M.mapKeysMonotonic (qualifiedToCpp (Ident . runProperName)) .
7980 M.map (\(_, _, _, fields) -> length fields) $
8081 E.dataConstructors env
81− cppDecls' <- traverse (optimize $ namesmap ++ datamap) cppDecls
82+ cpps' <- traverse (optimize $ namesmap ++ datamap) cpps
8283 foreignWrappers <- curriedForeigns
83− let optimized = cppDecls' ++ foreignWrappers
84+ let optimized = cpps' ++ foreignWrappers
8485 let moduleHeader =
8586 fileBegin mn "HH" ++
8687 P.linebreak ++
@@ -99,9 +100,10 @@ moduleToCpp env (Module _ mn imps _ foreigns decls) = do
99100 P.linebreak ++
100101 fileEnd mn "HH"
101102 let bodyCpps = toBodyDecl optimized ++ toBody optimized
103+ symbols = allSymbols bodyCpps
102104 moduleBody =
103105 CppInclude (runModuleName mn) (runModuleName mn) :
104− P.linebreak ++
106+ symbolDefs symbols :
105107 (if null bodyCpps
106108 then []
107109 else [ CppNamespace (runModuleName mn) $
@@ -189,7 +191,7 @@ moduleToCpp env (Module _ mn imps _ foreigns decls) = do
189191 isAccessor Accessor{} = True
190192 isAccessor _ = False
191193 isIndexer :: Cpp -> Bool
192− isIndexer (CppIndexer (CppStringLiteral _) (CppVar _)) = True
194+ isIndexer (CppIndexer (CppSymbol _) (CppVar _)) = True
193195 isIndexer _ = False
194196 classes = qualifiedToCpp (Ident . runProperName) . T.constraintClass <$>
195197 maybe [] extractConstraints ty'
@@ -368,7 +370,7 @@ moduleToCpp env (Module _ mn imps _ foreigns decls) = do
368370 [dict'])
369371 where
370372 dict' = CppVar dictname
371− dict'' = CppCast dataType dict'
373+ dict'' = CppCast (dataType 1) dict'
372374
373375 accessor :: String -> (String, Cpp) -> Cpp
374376 accessor dictname (name, _) =
@@ -440,18 +442,20 @@ moduleToCpp env (Module _ mn imps _ foreigns decls) = do
440442 CppArrayLiteral <$> mapM valueToCpp xs
441443
442444 valueToCpp (Literal _ (ObjectLiteral ps)) =
443− CppObjectLiteral CppRecord <$> sortBy (compare `on` fst) <$> mapM (sndM valueToCpp) ps
445+ CppObjectLiteral CppRecord <$>
446+ mapM (sndM valueToCpp) ((\(k,v) -> (CppSymbol k, v)) <$> sortBy (compare `on` fst) ps)
444447
445448 valueToCpp (Accessor _ prop val) =
446− CppIndexer <$> pure (CppStringLiteral prop) <*> valueToCpp val
449+ CppIndexer <$> pure (CppSymbol prop) <*> valueToCpp val
447450
448451 -- TODO: use a more efficient way of copying/updating the map?
449452 valueToCpp (ObjectUpdate (_, _, Just ty, _) obj ps) = do
450453 obj' <- valueToCpp obj
451454 updatedFields <- mapM (sndM valueToCpp) ps
452455 let origKeys = (allKeys ty) \\ (fst <$> updatedFields)
453− origFields = (\key -> (key, CppIndexer (CppStringLiteral key) obj')) <$> origKeys
454− return $ CppObjectLiteral CppRecord . sortBy (compare `on` fst) $ origFields ++ updatedFields
456+ origFields = (\key -> (key, CppIndexer (CppSymbol key) obj')) <$> origKeys
457+ return $ CppObjectLiteral CppRecord $
458+ (\(k,v) -> (CppSymbol k, v)) <$> sortBy (compare `on` fst) (origFields ++ updatedFields)
455459 where
456460 allKeys :: T.Type -> [String]
457461 allKeys (T.TypeApp (T.TypeConstructor _) r@(T.RCons {})) = fst <$> (fst $ T.rowToList r)
@@ -485,7 +489,7 @@ moduleToCpp env (Module _ mn imps _ foreigns decls) = do
485489 let Just (_, constraints, fns) = findClass (Qualified mn' (ProperName classname)) in
486490 return . CppObjectLiteral CppInstance $
487491 zip
488− ((sort $ superClassDictionaryNames constraints) ++ (fst <$> fns))
492+ (CppSymbol <$> (sort $ superClassDictionaryNames constraints) ++ (fst <$> fns))
489493 args'
490494 Var _ (Qualified (Just _) _) -> applied f args' curriedName'
491495 _ -> applied f args' id
@@ -625,7 +629,7 @@ moduleToCpp env (Module _ mn imps _ foreigns decls) = do
625629 EqualTo
626630 (CppIndexer
627631 (CppVar ctorKey)
628− (CppCast dataType $ CppVar varName))
632+ (CppCast (dataType 1) $ CppVar varName))
629633 ctorCpp)
630634 (CppBlock cpps)
631635 Nothing]
@@ -641,11 +645,13 @@ moduleToCpp env (Module _ mn imps _ foreigns decls) = do
641645 (argVar, Nothing)
642646 []
643647 (Just $ CppIndexer
644− (fieldToIndex field)
645− (CppCast dataType $ CppVar varName))
648+ (fieldToIndex' field)
649+ (CppCast (dataType $ fieldToIndex field + 1) $ CppVar varName))
646650 : cpps
647− fieldToIndex :: Ident -> Cpp
648− fieldToIndex = CppNumericLiteral . Left . (+1) . read . dropWhile isLetter . runIdent
651+ fieldToIndex :: Ident -> Int
652+ fieldToIndex = (+1) . read . dropWhile isLetter . runIdent
653+ fieldToIndex' :: Ident -> Cpp
654+ fieldToIndex' = CppNumericLiteral . Left . toInteger . fieldToIndex
649655 ctor' :: Cpp
650656 ctor' = CppAccessor (CppVar . identToCpp $ Ident ctor) (CppVar "data")
651657 ctorCpp :: Cpp
@@ -712,7 +718,7 @@ moduleToCpp env (Module _ mn imps _ foreigns decls) = do
712718 (propVar, Nothing)
713719 []
714720 (Just $ CppIndexer
715− (CppStringLiteral prop)
721+ (CppSymbol prop)
716722 (CppVar varName))
717723 : cpp
718724
@@ -868,12 +874,12 @@ extractConstraints = go []
868874---------------------------------------------------------------------------------------------------
869875dictIndexerToEnum :: [(Cpp,Cpp)] -> Cpp -> Cpp
870876---------------------------------------------------------------------------------------------------
871−dictIndexerToEnum repls (CppIndexer (CppStringLiteral prop) dict)
877+dictIndexerToEnum repls (CppIndexer (CppSymbol prop) dict)
872878 | Just cls <- lookup dict repls =
873879 CppBinary Dot
874880 (CppIndexer
875881 (CppAccessor (CppVar . identToCpp $ Ident prop) cls)
876− (CppCast mapType dict))
882+ (CppCast (mapType 0) dict))
877883 (CppVar "second")
878884dictIndexerToEnum _ cpp = cpp
879885
@@ -914,3 +920,38 @@ convertIfPrimFn (Just ty) (CppFunction name params _ qs body)
914920 | (tys', Just rty') <- primFn ty =
915921 CppFunction name (zipWith (\(p, _) t -> (p, Just t)) params tys') (Just rty') qs body
916922convertIfPrimFn _ cpp = cpp
923+
924+---------------------------------------------------------------------------------------------------
925+allSymbols :: [Cpp] -> [String]
926+---------------------------------------------------------------------------------------------------
927+allSymbols cpps = nub $ concatMap (everythingOnCpp (++) symbols) cpps
928+ where
929+ symbols :: Cpp -> [String]
930+ symbols (CppSymbol s) = [symbolname s]
931+ symbols _ = []
932+
933+---------------------------------------------------------------------------------------------------
934+symbolDefs :: [String] -> Cpp
935+---------------------------------------------------------------------------------------------------
936+symbolDefs [] = CppNoOp
937+symbolDefs syms = CppNamespace "PureScript" [CppNamespace "symbol" (asFunc <$> syms)]
938+ where
939+ asFunc :: String -> Cpp
940+ asFunc s = CppStruct s []
941+
942+---------------------------------------------------------------------------------------------------
943+filterInlineFuncs :: Cpp -> Cpp
944+---------------------------------------------------------------------------------------------------
945+filterInlineFuncs = everywhereOnCpp convert
946+ where
947+ convert :: Cpp -> Cpp
948+ convert (CppBlock []) = CppBlock []
949+ convert (CppFunction n ps r qs cpp)
950+ | CppInline `elem` qs,
951+ everythingOnCpp (||) shouldRemove cpp = CppFunction n ps r (delete CppInline qs) cpp
952+ where
953+ shouldRemove :: Cpp -> Bool
954+ shouldRemove CppSymbol{} = True
955+ shouldRemove CppLambda{} = True
956+ shouldRemove _ = False
957+ convert cpp = cpp
src/Language/PureScript/CodeGen/Cpp/AST.hs+11−6
@@ -185,7 +185,7 @@ data Cpp
185185 -- |
186186 -- An object literal
187187 --
188− | CppObjectLiteral CppObjectType [(String, Cpp)]
188+ | CppObjectLiteral CppObjectType [(Cpp, Cpp)]
189189 -- |
190190 -- An general property accessor expression (property, expr)
191191 --
@@ -211,6 +211,11 @@ data Cpp
211211 --
212212 | CppVar String
213213 -- |
214+ -- Unique system-wide name/constant
215+ --
216+ | CppSymbol String
217+ -- |
218+ -- |
214219 -- A block of expressions in braces
215220 --
216221 | CppBlock [Cpp]
@@ -297,7 +302,7 @@ everywhereOnCpp f = go
297302 go (CppArrayLiteral cpp) = f (CppArrayLiteral (map go cpp))
298303 go (CppDataLiteral cpp) = f (CppDataLiteral (map go cpp))
299304 go (CppIndexer j1 j2) = f (CppIndexer (go j1) (go j2))
300− go (CppObjectLiteral t cpp) = f (CppObjectLiteral t (map (fmap go) cpp))
305+ go (CppObjectLiteral t cpps) = f (CppObjectLiteral t (map (fmap go) cpps))
301306 go (CppAccessor prop j) = f (CppAccessor (go prop) (go j))
302307 go (CppFunction name args rty qs j) = f (CppFunction name args rty qs (go j))
303308 go (CppLambda cps args rty j) = f (CppLambda cps args rty (go j))
@@ -328,7 +333,7 @@ everywhereOnCppTopDownM f = f >=> go
328333 go (CppArrayLiteral cpp) = CppArrayLiteral <$> traverse f' cpp
329334 go (CppDataLiteral cpp) = CppDataLiteral <$> traverse f' cpp
330335 go (CppIndexer j1 j2) = CppIndexer <$> f' j1 <*> f' j2
331− go (CppObjectLiteral t cpp) = CppObjectLiteral t <$> traverse (sndM f') cpp
336+ go (CppObjectLiteral t cpps) = CppObjectLiteral t <$> traverse (pairM f' f') cpps
332337 go (CppAccessor prop j) = CppAccessor prop <$> f' j
333338 go (CppFunction name args rty qs j) = CppFunction name args rty qs <$> f' j
334339 go (CppLambda cps args rty j) = CppLambda cps args rty <$> f' j
@@ -341,7 +346,7 @@ everywhereOnCppTopDownM f = f >=> go
341346 go (CppAssignment j1 j2) = CppAssignment <$> f' j1 <*> f' j2
342347 go (CppWhile j1 j2) = CppWhile <$> f' j1 <*> f' j2
343348 go (CppIfElse j1 j2 j3) = CppIfElse <$> f' j1 <*> f' j2 <*> traverse f' j3
344− go (CppSwitch cpp cpps) = CppSwitch <$> f' cpp <*> traverse (sndM f') cpps
349+ go (CppSwitch cpp cpps) = CppSwitch <$> f' cpp <*> traverse (pairM f' f') cpps
345350 go (CppReturn j) = CppReturn <$> f' j
346351 go (CppThrow j) = CppThrow <$> f' j
347352 go (CppComment com j) = CppComment com <$> f' j
@@ -355,7 +360,7 @@ everythingOnCpp (<>) f = go
355360 go j@(CppArrayLiteral cpp) = foldl (<>) (f j) (map go cpp)
356361 go j@(CppDataLiteral cpp) = foldl (<>) (f j) (map go cpp)
357362 go j@(CppIndexer j1 j2) = f j <> go j1 <> go j2
358− go j@(CppObjectLiteral _ cpp) = foldl (<>) (f j) (map (go . snd) cpp)
363+ go j@(CppObjectLiteral _ cpps) = foldl (<>) (f j) ((map (go . fst) cpps) ++ (map (go . snd) cpps))
359364 go j@(CppAccessor j1 j2) = f j <> go j1 <> go j2
360365 go j@(CppFunction _ _ _ _ j1) = f j <> go j1
361366 go j@(CppLambda _ _ _ j1) = f j <> go j1
@@ -369,7 +374,7 @@ everythingOnCpp (<>) f = go
369374 go j@(CppWhile j1 j2) = f j <> go j1 <> go j2
370375 go j@(CppIfElse j1 j2 Nothing) = f j <> go j1 <> go j2
371376 go j@(CppIfElse j1 j2 (Just j3)) = f j <> go j1 <> go j2 <> go j3
372− go j@(CppSwitch cpp cpps) = foldl (<>) (f j <> go cpp) (map (go . snd) cpps)
377+ go j@(CppSwitch cpp cpps) = foldl (<>) (f j <> go cpp) ((map (go . fst) cpps) ++ (map (go . snd) cpps))
373378 go j@(CppReturn j1) = f j <> go j1
374379 go j@(CppThrow j1) = f j <> go j1
375380 go j@(CppComment _ j1) = f j <> go j1
src/Language/PureScript/CodeGen/Cpp/Common.hs+2
@@ -167,6 +167,7 @@ nameIsCppReserved name =
167167 , "string"
168168 , "struct"
169169 , "switch"
170+ , "symbol"
170171 , "template"
171172 , "this"
172173 , "thread_local"
@@ -178,6 +179,7 @@ nameIsCppReserved name =
178179 , "typename"
179180 , "typeof"
180181 , "union"
182+ , "unknown_size"
181183 , "unsigned"
182184 , "using"
183185 , "virtual"
src/Language/PureScript/CodeGen/Cpp/File.hs+1−1
@@ -141,7 +141,7 @@ toBody = catMaybes . map go
141141 addCaptures :: Cpp -> Cpp
142142 addCaptures (CppObjectLiteral t objs) = CppObjectLiteral t (objlam <$> objs)
143143 where
144− objlam :: (String, Cpp) -> (String, Cpp)
144+ objlam :: (Cpp, Cpp) -> (Cpp, Cpp)
145145 objlam (name', (CppLambda _ args rty body)) = (name' , CppLambda [] args rty $ addCaptures body)
146146 objlam obj = obj
147147 addCaptures (CppApp (CppLambda _ [] rty body) []) = CppApp (CppLambda [] [] rty (addCaptures body)) []
src/Language/PureScript/CodeGen/Cpp/Optimizer/MagicDo.hs+1−1
@@ -128,7 +128,7 @@ inlineST = everywhereOnCpp convertBlock
128128 -- or in a more aggressive way, turning wrappers into local variables depending on the
129129 -- agg(ressive) parameter.
130130 convert agg (CppApp f [arg]) | isSTFunc C.newSTRef f =
131− CppLambda [CppCaptureAll] [] Nothing (CppBlock [CppReturn $ if agg then arg else CppObjectLiteral CppRecord [(C.stRefValue, arg)]])
131+ CppLambda [CppCaptureAll] [] Nothing (CppBlock [CppReturn $ if agg then arg else CppObjectLiteral CppRecord [(CppSymbol C.stRefValue, arg)]])
132132 convert agg (CppApp (CppApp f [ref]) []) | isSTFunc C.readSTRef f =
133133 if agg then ref else CppAccessor (CppVar C.stRefValue) ref
134134 convert agg (CppApp (CppApp (CppApp f [ref]) [arg]) []) | isSTFunc C.writeSTRef f =
src/Language/PureScript/CodeGen/Cpp/Types.hs+14−4
@@ -124,11 +124,18 @@ stringType = CppPrimitive "string"
124124charType :: CppType
125125charType = CppPrimitive "char"
126126
127−mapType :: CppType
128−mapType = CppPrimitive "any::map"
127+voidType :: CppType
128+voidType = CppPrimitive "void"
129129
130−dataType :: CppType
131−dataType = CppPrimitive "any::data"
130+mapType :: Int -> CppType
131+mapType = maptype
132+ where
133+ maptype 0 = mapprim "unknown_size"
134+ maptype n = mapprim $ show n
135+ mapprim s = CppPrimitive $ "any::map<" ++ s ++ ">"
136+
137+dataType :: Int -> CppType
138+dataType n = CppPrimitive $ "any::data<" ++ show n ++ ">"
132139
133140arrayType :: CppType
134141arrayType = CppPrimitive "any::array"
@@ -141,3 +148,6 @@ ctorKey = "constructor"
141148
142149constAnyRef :: Maybe CppType
143150constAnyRef = Just $ CppAny [CppConst, CppRef]
151+
152+symbolname :: String -> String
153+symbolname = identToCpp . Ident
src/Language/PureScript/Pretty/Cpp.hs+7−6
@@ -40,7 +40,6 @@ import qualified Control.Arrow as A
4040import Language.PureScript.CodeGen.Cpp.AST
4141import Language.PureScript.CodeGen.Cpp.Types
4242import Language.PureScript.Comments
43−-- import Language.PureScript.Pretty.Common
4443import qualified Language.PureScript.Constants as C
4544import Numeric
4645-- import Debug.Trace
@@ -104,7 +103,7 @@ literals = mkPattern' match
104103 , return " }"
105104 ]
106105 match (CppDataLiteral xs) = fmap concat $ sequence
107− [ return $ runType dataType
106+ [ return $ runType (dataType $ length xs)
108107 , return "{ "
109108 , fmap (intercalate ", ") $ forM xs prettyPrintCpp'
110109 , return " }"
@@ -118,17 +117,17 @@ literals = mkPattern' match
118117 , return " }"
119118 ]
120119 match (CppObjectLiteral _ ps) = fmap concat $ sequence
121− [ return $ runType mapType ++ "{\n"
120+ [ return $ runType (mapType $ length ps + 1) ++ "{{\n"
122121 , withIndent $ do
123122 cpps <- forM ps $ \(key, value) -> do
124123 value' <- prettyPrintCpp' value
125− key' <- prettyPrintCpp' (CppStringLiteral key)
124+ key' <- prettyPrintCpp' key
126125 return $ "{ " ++ key' ++ ", " ++ value' ++ " }"
127126 indentString <- currentIndent
128− return $ intercalate ", \n" $ map (indentString ++) cpps
127+ return $ intercalate ", \n" $ map (indentString ++) (cpps ++ ["{ nullptr, nullptr }"])
129128 , return "\n"
130129 , currentIndent
131− , return "}"
130+ , return "}}"
132131 ]
133132
134133 match (CppFunction name args rty qs ret) =
@@ -196,6 +195,7 @@ literals = mkPattern' match
196195 isUseNamespace :: Cpp -> Bool
197196 isUseNamespace (CppUseNamespace{}) = True
198197 isUseNamespace _ = False
198+ match (CppStruct (name) []) = return $ "struct " ++ name ++ " {}"
199199 match (CppStruct (name) mems) = fmap concat $ sequence $
200200 [ return "\n"
201201 , currentIndent
@@ -240,6 +240,7 @@ literals = mkPattern' match
240240
241241 match (CppVar ident) | ident == C.__unused = match (CppVar $ '$':ident)
242242 match (CppVar ident) = return ident
243+ match (CppSymbol ident) = return $ "SYMBOL" ++ parens (symbolname ident)
243244 match (CppApp v [CppNoOp]) = return (prettyPrintCpp1 v)
244245 match (CppVariableIntroduction (ident, typ) qs value)
245246 | ident == C.__unused = match (CppVariableIntroduction ('$':ident, typ) qs value)