git.iko.soy/rowtype-yoga/purescript-native
on golang help sign in
C++: cleanup unthunking
c0ec8bfAndy Arvanitis
pcc/include/purescript.cc+57−101
@@ -102,21 +102,10 @@ any::~any() {
102 }
102 }
103};
103};
104
104
105−#define RETURN_VALUE(TYPE, VAL, FN) \
105+#define RETURN_VALUE(TYPE, ACCESSOR, INDIRECTION) \
106− if (type == TYPE) { \
107− return FN(VAL); \
108− } \
109− const any* valuePtr = this; \
106+ const any& variant = unthunkVariant(*this); \
110− do { \
111− assert(valuePtr->type == Type::Thunk); \
112− const any& value = (*valuePtr->t)(unthunk); \
113− if (value.type == TYPE) { \
107+ assert(variant.type == TYPE); \
114− return FN(value.VAL); \
108+ return INDIRECTION(variant.ACCESSOR); \
115− } \
116− valuePtr = &value; \
117− } while (valuePtr->type != Type::Unknown); \
118− assert(false && "Unknown value type"); \
119− return FN(VAL);
120
109
121template <typename T>
110template <typename T>
122auto any::cast() const -> typename std::enable_if<std::is_same<T, long>::value, T>::type {
111auto any::cast() const -> typename std::enable_if<std::is_same<T, long>::value, T>::type {
@@ -144,12 +133,12 @@ template auto any::cast<bool>() const -> bool;
144
133
145template <typename T>
134template <typename T>
146auto any::cast() const -> typename std::enable_if<std::is_same<T, string>::value, T>::type {
135auto any::cast() const -> typename std::enable_if<std::is_same<T, string>::value, T>::type {
147− const any& val = extractValue(*this);
136+ const any& variant = unthunkVariant(*this);
148− if (val.type == Type::StringLiteral) {
137+ if (variant.type == Type::StringLiteral) {
149− return val.r;
138+ return variant.r;
150 }
139 }
151− assert(val.type == Type::String);
140+ assert(variant.type == Type::String);
152− return val.s->c_str();
141+ return variant.s->c_str();
153}
142}
154template auto any::cast<string>() const -> string;
143template auto any::cast<string>() const -> string;
155
144
@@ -166,26 +155,12 @@ auto any::cast() const -> typename std::enable_if<std::is_same<T, vector>::value
166template auto any::cast<any::vector>() const -> const vector&;
155template auto any::cast<any::vector>() const -> const vector&;
167
156
168auto any::operator()(const any& arg) const -> any {
157auto any::operator()(const any& arg) const -> any {
158+ const any& variant = unthunkVariant(*this);
169− if (type == Type::Function) {
159+ if (variant.type == Type::Closure) {
170− return (*f)(arg);
160+ return (*variant.l)(arg);
171 }
161 }
172− if (type == Type::Closure) {
173− return (*l)(arg);
174− }
175− const any* valuePtr = this;
176− do {
177− assert(valuePtr->type == Type::Thunk);
178− const any& value = (*valuePtr->t)(unthunk);
179− if (value.type == Type::Function) {
162+ assert(variant.type == Type::Function);
180− return (*value.f)(arg);
163+ return (*variant.f)(arg);
181− }
182− if (value.type == Type::Closure) {
183− return (*value.l)(arg);
184− }
185− valuePtr = &value;
186− } while (valuePtr->type != Type::Unknown);
187− assert(false && "Unknown value type");
188− return nullptr;
189}
164}
190
165
191auto any::operator()(const as_thunk) const -> const any& {
166auto any::operator()(const as_thunk) const -> const any& {
@@ -194,32 +169,21 @@ auto any::operator()(const as_thunk) const -> const any& {
194}
169}
195
170
196auto any::operator()() const -> any {
171auto any::operator()() const -> any {
197− if (type == Type::EffFunction) {
198− return (*e)();
199− }
200− const any* valuePtr = this;
172+ const any& variant = unthunkVariant(*this);
201− do {
202− assert(valuePtr->type == Type::Thunk);
203− const any& value = (*valuePtr->t)(unthunk);
204− if (value.type == Type::EffFunction) {
173+ assert(variant.type == Type::EffFunction);
205− return (*value.e)();
174+ return (*variant.e)();
206− }
207− valuePtr = &value;
208− } while (valuePtr->type != Type::Unknown);
209− assert(false && "Unknown value type");
210− return nullptr;
211}
175}
212
176
213any::operator long() const {
177any::operator long() const {
214− RETURN_VALUE(Type::Integer, i,)
178+ return cast<long>();
215}
179}
216
180
217any::operator double() const {
181any::operator double() const {
218− RETURN_VALUE(Type::Double, d,)
182+ return cast<double>();
219}
183}
220
184
221any::operator bool() const {
185any::operator bool() const {
222− RETURN_VALUE(Type::Boolean, b,)
186+ return cast<bool>();
223}
187}
224
188
225any::operator string() const {
189any::operator string() const {
@@ -227,38 +191,30 @@ any::operator string() const {
227}
191}
228
192
229any::operator const map&() const {
193any::operator const map&() const {
230− RETURN_VALUE(Type::Map, m, *)
194+ return cast<map>();
231}
195}
232
196
233any::operator const vector&() const {
197any::operator const vector&() const {
234− RETURN_VALUE(Type::Vector, v, *)
198+ return cast<vector>();
235}
199}
236
200
237auto any::extractPointer() const -> void* {
201auto any::extractPointer() const -> void* {
238 RETURN_VALUE(Type::Pointer, p.get(),)
202 RETURN_VALUE(Type::Pointer, p.get(),)
239}
203}
240
204
241−auto any::extractValue(const any& a) -> const any& {
205+auto any::unthunkVariant(const any& a) -> const any& {
206+ const any * variant = &a;
242− if (a.type != Type::Thunk) {
207+ while (variant->type == Type::Thunk) {
243− return a;
208+ variant = &((*variant->t)(unthunk));
244 }
209 }
245− const any* valuePtr = &a;
246− do {
247− const any& value = (*valuePtr->t)(unthunk);
248− if (value.type != Type::Thunk) {
249− return value;
210+ return *variant;
250− }
251− valuePtr = &value;
252− } while (valuePtr->type != Type::Unknown);
253− assert(false && "Unknown value type");
254− return a;
255}
211}
256
212
257auto any::operator[](const char rhs[]) const -> const any& {
213auto any::operator[](const char rhs[]) const -> const any& {
258− const any& val = extractValue(*this);
214+ const any& variant = unthunkVariant(*this);
259− assert(val.type == Type::Map);
215+ assert(variant.type == Type::Map);
260− const any::map::const_iterator begin = val.m->begin();
216+ const any::map::const_iterator begin = variant.m->begin();
261− const any::map::const_iterator end = val.m->end();
217+ const any::map::const_iterator end = variant.m->end();
262 for (any::map::const_iterator it = begin; it != end; ++it) {
218 for (any::map::const_iterator it = begin; it != end; ++it) {
263 if (it->first == rhs) {
219 if (it->first == rhs) {
264 return it->second;
220 return it->second;
@@ -273,21 +229,21 @@ auto any::operator[](const char rhs[]) const -> const any& {
273}
229}
274
230
275auto any::operator[](const vector::size_type rhs) const -> const any& {
231auto any::operator[](const vector::size_type rhs) const -> const any& {
276− const any& val = extractValue(*this);
232+ const any& variant = unthunkVariant(*this);
277− assert(val.type == Type::Vector);
233+ assert(variant.type == Type::Vector);
278− return (*val.v)[rhs];
234+ return (*variant.v)[rhs];
279}
235}
280
236
281auto any::operator[](const any& rhs) const -> const any& {
237auto any::operator[](const any& rhs) const -> const any& {
282− const any& val = extractValue(*this);
238+ const any& variant = unthunkVariant(*this);
283− assert(val.type == Type::Vector);
239+ assert(variant.type == Type::Vector);
284− return (*val.v)[rhs.cast<long>()];
240+ return (*variant.v)[rhs.cast<long>()];
285}
241}
286
242
287auto any::contains(const char key[]) const -> bool {
243auto any::contains(const char key[]) const -> bool {
288− const any& val = extractValue(*this);
244+ const any& variant = unthunkVariant(*this);
289− assert(val.type == Type::Map);
245+ assert(variant.type == Type::Map);
290− for (any::map::const_iterator it = val.m->begin(), end = val.m->end(); it != end; ++it) {
246+ for (any::map::const_iterator it = variant.m->begin(), end = variant.m->end(); it != end; ++it) {
291 if (it->first == key || strcmp(it->first, key) == 0) {
247 if (it->first == key || strcmp(it->first, key) == 0) {
292 return true;
248 return true;
293 }
249 }
@@ -309,7 +265,7 @@ auto operator op (ty lhs, const any& rhs) -> rty { \
309
265
310#define DEFINE_CSTR_EQUALS_OPERATOR() \
266#define DEFINE_CSTR_EQUALS_OPERATOR() \
311 auto operator==(const any& lhs_, const char * rhs) -> bool { \
267 auto operator==(const any& lhs_, const char * rhs) -> bool { \
312− const any& lhs = any::extractValue(lhs_); \
268+ const any& lhs = any::unthunkVariant(lhs_); \
313 assert(lhs.type == any::Type::StringLiteral || lhs.type == any::Type::String); \
269 assert(lhs.type == any::Type::StringLiteral || lhs.type == any::Type::String); \
314 if (lhs.type == any::Type::StringLiteral) { \
270 if (lhs.type == any::Type::StringLiteral) { \
315 return (lhs.r == rhs) || (strcmp(lhs.r, rhs) == 0); \
271 return (lhs.r == rhs) || (strcmp(lhs.r, rhs) == 0); \
@@ -317,7 +273,7 @@ auto operator op (ty lhs, const any& rhs) -> rty { \
317 return strcmp(lhs.s->c_str(), rhs) == 0; \
273 return strcmp(lhs.s->c_str(), rhs) == 0; \
318 } \
274 } \
319 auto operator==(const char * lhs, const any& rhs_) -> bool { \
275 auto operator==(const char * lhs, const any& rhs_) -> bool { \
320− const any& rhs = any::extractValue(rhs_); \
276+ const any& rhs = any::unthunkVariant(rhs_); \
321 assert(rhs.type == any::Type::StringLiteral || rhs.type == any::Type::String); \
277 assert(rhs.type == any::Type::StringLiteral || rhs.type == any::Type::String); \
322 if (rhs.type == any::Type::StringLiteral) { \
278 if (rhs.type == any::Type::StringLiteral) { \
323 return (lhs == rhs.r) || (strcmp(lhs, rhs) == 0); \
279 return (lhs == rhs.r) || (strcmp(lhs, rhs) == 0); \
@@ -335,8 +291,8 @@ auto operator op (ty lhs, const any& rhs) -> rty { \
335
291
336#define DEFINE_COMPARISON_OPERATOR(op) \
292#define DEFINE_COMPARISON_OPERATOR(op) \
337 auto operator op (const any& lhs_, const any& rhs_) -> bool { \
293 auto operator op (const any& lhs_, const any& rhs_) -> bool { \
338− const any& lhs = any::extractValue(lhs_); \
294+ const any& lhs = any::unthunkVariant(lhs_); \
339− const any& rhs = any::extractValue(rhs_); \
295+ const any& rhs = any::unthunkVariant(rhs_); \
340 switch (lhs.type) { \
296 switch (lhs.type) { \
341 case any::Type::Integer: assert(lhs.type == any::Type::Integer); return lhs.i op rhs.i; \
297 case any::Type::Integer: assert(lhs.type == any::Type::Integer); return lhs.i op rhs.i; \
342 case any::Type::Double: assert(lhs.type == any::Type::Double); return lhs.d op rhs.d; \
298 case any::Type::Double: assert(lhs.type == any::Type::Double); return lhs.d op rhs.d; \
@@ -379,8 +335,8 @@ DEFINE_CSTR_COMPARISON_OPERATOR(>)
379DEFINE_CSTR_COMPARISON_OPERATOR(>=)
335DEFINE_CSTR_COMPARISON_OPERATOR(>=)
380
336
381auto operator+(const any& lhs_, const any& rhs_) -> any {
337auto operator+(const any& lhs_, const any& rhs_) -> any {
382− const any& lhs = any::extractValue(lhs_);
338+ const any& lhs = any::unthunkVariant(lhs_);
383− const any& rhs = any::extractValue(rhs_);
339+ const any& rhs = any::unthunkVariant(rhs_);
384 switch (lhs.type) {
340 switch (lhs.type) {
385 case any::Type::Integer: assert(lhs.type == any::Type::Integer); return lhs.i + rhs.i;
341 case any::Type::Integer: assert(lhs.type == any::Type::Integer); return lhs.i + rhs.i;
386 case any::Type::Double: assert(lhs.type == any::Type::Double); return lhs.d + rhs.d;
342 case any::Type::Double: assert(lhs.type == any::Type::Double); return lhs.d + rhs.d;
@@ -403,20 +359,20 @@ DEFINE_OPERATOR(+, double, double)
403DEFINE_OPERATOR(+, char, char)
359DEFINE_OPERATOR(+, char, char)
404
360
405auto operator+(const any& lhs_, const char * rhs) -> std::string {
361auto operator+(const any& lhs_, const char * rhs) -> std::string {
406− const any& lhs = any::extractValue(lhs_);
362+ const any& lhs = any::unthunkVariant(lhs_);
407 assert(lhs.type == any::Type::StringLiteral || lhs.type == any::Type::String);
363 assert(lhs.type == any::Type::StringLiteral || lhs.type == any::Type::String);
408 return lhs.type == any::Type::StringLiteral ? std::string(lhs.r) + rhs : *lhs.s + rhs;
364 return lhs.type == any::Type::StringLiteral ? std::string(lhs.r) + rhs : *lhs.s + rhs;
409}
365}
410
366
411auto operator+(const char * lhs, const any& rhs_) -> std::string {
367auto operator+(const char * lhs, const any& rhs_) -> std::string {
412− const any& rhs = any::extractValue(rhs_);
368+ const any& rhs = any::unthunkVariant(rhs_);
413 assert(rhs.type == any::Type::StringLiteral || rhs.type == any::Type::String);
369 assert(rhs.type == any::Type::StringLiteral || rhs.type == any::Type::String);
414 return rhs.type == any::Type::StringLiteral ? lhs + std::string(rhs.r) : lhs + *rhs.s;
370 return rhs.type == any::Type::StringLiteral ? lhs + std::string(rhs.r) : lhs + *rhs.s;
415}
371}
416
372
417auto operator-(const any& lhs_, const any& rhs_) -> any {
373auto operator-(const any& lhs_, const any& rhs_) -> any {
418− const any& lhs = any::extractValue(lhs_);
374+ const any& lhs = any::unthunkVariant(lhs_);
419− const any& rhs = any::extractValue(rhs_);
375+ const any& rhs = any::unthunkVariant(rhs_);
420 assert(lhs.type == rhs.type);
376 assert(lhs.type == rhs.type);
421 switch (lhs.type) {
377 switch (lhs.type) {
422 case any::Type::Integer: return lhs.i - rhs.i;
378 case any::Type::Integer: return lhs.i - rhs.i;
@@ -432,8 +388,8 @@ DEFINE_OPERATOR(-, double, double)
432DEFINE_OPERATOR(-, char, char)
388DEFINE_OPERATOR(-, char, char)
433
389
434auto operator*(const any& lhs_, const any& rhs_) -> any {
390auto operator*(const any& lhs_, const any& rhs_) -> any {
435− const any& lhs = any::extractValue(lhs_);
391+ const any& lhs = any::unthunkVariant(lhs_);
436− const any& rhs = any::extractValue(rhs_);
392+ const any& rhs = any::unthunkVariant(rhs_);
437 assert(lhs.type == rhs.type);
393 assert(lhs.type == rhs.type);
438 switch (lhs.type) {
394 switch (lhs.type) {
439 case any::Type::Integer: return lhs.i * rhs.i;
395 case any::Type::Integer: return lhs.i * rhs.i;
@@ -449,8 +405,8 @@ DEFINE_OPERATOR(*, double, double)
449DEFINE_OPERATOR(*, char, char)
405DEFINE_OPERATOR(*, char, char)
450
406
451auto operator/(const any& lhs_, const any& rhs_) -> any {
407auto operator/(const any& lhs_, const any& rhs_) -> any {
452− const any& lhs = any::extractValue(lhs_);
408+ const any& lhs = any::unthunkVariant(lhs_);
453− const any& rhs = any::extractValue(rhs_);
409+ const any& rhs = any::unthunkVariant(rhs_);
454 assert(lhs.type == rhs.type);
410 assert(lhs.type == rhs.type);
455 switch (lhs.type) {
411 switch (lhs.type) {
456 case any::Type::Integer: return lhs.i / rhs.i;
412 case any::Type::Integer: return lhs.i / rhs.i;
@@ -466,8 +422,8 @@ DEFINE_OPERATOR(/, double, double)
466DEFINE_OPERATOR(/, char, char)
422DEFINE_OPERATOR(/, char, char)
467
423
468auto operator%(const any& lhs_, const any& rhs_) -> any {
424auto operator%(const any& lhs_, const any& rhs_) -> any {
469− const any& lhs = any::extractValue(lhs_);
425+ const any& lhs = any::unthunkVariant(lhs_);
470− const any& rhs = any::extractValue(rhs_);
426+ const any& rhs = any::unthunkVariant(rhs_);
471 assert(lhs.type == rhs.type);
427 assert(lhs.type == rhs.type);
472 switch (lhs.type) {
428 switch (lhs.type) {
473 case any::Type::Integer: return lhs.i % rhs.i;
429 case any::Type::Integer: return lhs.i % rhs.i;
@@ -482,7 +438,7 @@ DEFINE_OPERATOR(%, char, char)
482
438
483// unary negate
439// unary negate
484auto operator-(const any& rhs_) -> any {
440auto operator-(const any& rhs_) -> any {
485− const any& rhs = any::extractValue(rhs_);
441+ const any& rhs = any::unthunkVariant(rhs_);
486 switch (rhs.type) {
442 switch (rhs.type) {
487 case any::Type::Integer: return (- rhs.i);
443 case any::Type::Integer: return (- rhs.i);
488 case any::Type::Double: return (- rhs.d);
444 case any::Type::Double: return (- rhs.d);
pcc/include/purescript.hh+1−1
@@ -229,7 +229,7 @@ class any {
229
229
230 auto extractPointer() const -> void*;
230 auto extractPointer() const -> void*;
231
231
232− static auto extractValue(const any&) -> const any&;
232+ static auto unthunkVariant(const any&) -> const any&;
233
233
234 DECLARE_COMPARISON_OPERATOR(==)
234 DECLARE_COMPARISON_OPERATOR(==)
235 DECLARE_COMPARISON_OPERATOR(!=)
235 DECLARE_COMPARISON_OPERATOR(!=)