@@ -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}