git.iko.soy/rowtype-yoga/purescript-native
on golang help sign in
Revert "C++: consolidate logic for managed types"

This reverts commit 40a3fe248fb1a1714e214f8dd4a6001a8c43fe89.

commita2a4fd73da869005835c90365311c0ad90a989fa authorAndy Arvanitis <andyarvanitis@gmail.com> dateThu 2 Feb 2017, 08:39 (10 years ago) parent40a3fe2
2 files changed+102−75
pcc/runtime/purescript.cc+8−10 pcc/runtime/purescript.hh+94−65
pcc/runtime/purescript.cc+8−10
@@ -28,7 +28,7 @@ any::EffClosure::~EffClosure() {}
2828auto any::operator()(const any& arg) const -> any {
2929 const any& variant = unthunkVariant(*this);
3030 if (variant.tag == Tag::Closure) {
31− return (*static_cast<const Closure*>(POINTER_FROM_MEMBER(variant.p)))(arg);
31+ return (*variant.l)(arg);
3232 }
3333 assert(variant.tag == Tag::Function);
3434 return (*variant.f)(arg);
@@ -42,7 +42,7 @@ auto any::operator()(const as_thunk) const -> const any& {
4242auto any::operator()() const -> any {
4343 const any& variant = unthunkVariant(*this);
4444 if (variant.tag == Tag::EffClosure) {
45− return (*static_cast<const EffClosure*>(POINTER_FROM_MEMBER(variant.p)))();
45+ return (*variant.k)();
4646 }
4747 assert(variant.tag == Tag::EffFunction);
4848 return (*variant.e)();
@@ -77,19 +77,19 @@ any::operator size_t() const {
7777}
7878
7979any::operator const string&() const {
80− return *static_cast<const string*>(extractPointer(IF_DEBUG(Tag::String)));
80+ RETURN_VALUE(Tag::String, s, *)
8181}
8282
8383any::operator const char *() const {
84− return static_cast<const string*>(extractPointer(IF_DEBUG(Tag::String)))->c_str();
84+ RETURN_VALUE(Tag::String, s->c_str(),)
8585}
8686
8787any::operator const array&() const {
88− return *static_cast<const array*>(extractPointer(IF_DEBUG(Tag::Array)));
88+ RETURN_VALUE(Tag::Array, a, *)
8989}
9090
9191any::operator const record&() const {
92− return *static_cast<const record*>(extractPointer(IF_DEBUG(Tag::Record)));
92+ RETURN_VALUE(Tag::Record, r, *)
9393}
9494
9595auto any::extractPointer(IF_DEBUG(const any::Tag t)) const -> void* {
@@ -145,8 +145,7 @@ auto any::at(const std::string& key) const -> const any& {
145145 case any::Tag::Double: return lhs.d op static_cast<decltype(any::d)>(rhs); \
146146 case any::Tag::Character: return lhs.c op static_cast<decltype(any::c)>(rhs); \
147147 case any::Tag::Boolean: return lhs.b op static_cast<decltype(any::b)>(rhs); \
148− case any::Tag::String: return *static_cast<const string*>(POINTER_FROM_MEMBER(lhs.p)) \
149− op static_cast<const string&>(rhs); \
148+ case any::Tag::String: return *lhs.s op static_cast<const string&>(rhs); \
150149 case any::Tag::RawPointer: return lhs.v op cast<decltype(any::v)>(rhs); \
151150 case any::Tag::Pointer: return lhs.p op any::unthunkVariant(rhs).p; \
152151 default: assert(false && "Unsupported tag for operator " #op); \
@@ -171,8 +170,7 @@ auto operator+(const any& lhs_, const any& rhs) -> any {
171170 case any::Tag::Integer: return lhs.i + static_cast<decltype(any::i)>(rhs);
172171 case any::Tag::Double: return lhs.d + static_cast<decltype(any::d)>(rhs);
173172 case any::Tag::Character: return decltype(any::c){lhs.c + static_cast<decltype(any::c)>(rhs)};
174− case any::Tag::String: return *static_cast<const string*>(POINTER_FROM_MEMBER(lhs.p))
175− + static_cast<const string&>(rhs);
173+ case any::Tag::String: return *lhs.s + static_cast<const string&>(rhs);
176174 default: assert(false && "Unsupported tag for '+' operator");
177175 }
178176 return nullptr;
pcc/runtime/purescript.hh+94−65
@@ -80,13 +80,9 @@ static constexpr size_t unknown_size = 64;
8080//
8181class any {
8282
83− private:
84− static constexpr auto _managed_ = 0x10;
85−
8683 public:
8784 enum class Tag {
88− Unknown,
89− Thunk,
85+ Thunk = 0x10,
9086 Integer,
9187 Double,
9288 Character,
@@ -94,25 +90,19 @@ class any {
9490 Function,
9591 EffFunction,
9692 RawPointer,
97− String = _managed_,
98− Dictionary,
93+ String,
94+ Map,
9995 Data,
10096 Array,
10197 Record,
10298 Closure,
10399 EffClosure,
104− Pointer,
105− Invalid
100+ Pointer
106101 };
107102
108103 private:
109104 mutable Tag tag;
110105
111− inline static auto isManaged(const Tag tag) -> decltype(_managed_) {
112− return static_cast<decltype(_managed_)>(tag) & _managed_;
113− }
114− static_assert(static_cast<decltype(_managed_)>(Tag::Invalid) & _managed_, "outside of range");
115−
116106 public:
117107 struct as_thunk {
118108 };
@@ -168,16 +158,20 @@ class any {
168158
169159 private:
170160 union {
171− mutable thunk t;
172− mutable int i;
173− mutable double d;
174− mutable char32_t c;
175− mutable bool b;
176− mutable fn f;
177− mutable eff_fn e;
178− mutable void * v;
179− mutable uint64_t u;
180− mutable managed<void> p;
161+ mutable thunk t;
162+ mutable int i;
163+ mutable double d;
164+ mutable char32_t c;
165+ mutable bool b;
166+ mutable fn f;
167+ mutable eff_fn e;
168+ mutable void * v;
169+ mutable managed<string> s;
170+ mutable managed<array> a;
171+ mutable managed<record> r;
172+ mutable managed<Closure> l;
173+ mutable managed<EffClosure> k;
174+ mutable managed<void> p;
181175 };
182176
183177 public:
@@ -194,24 +188,24 @@ class any {
194188 template <typename T, typename = typename std::enable_if<std::is_same<bool,T>::value>::type>
195189 any(const T val) noexcept : tag(Tag::Boolean), b(val) {}
196190
197− any(const char * val) : tag(Tag::String), p(make_managed_and_finalized<string>(val)) {}
198− any(const string& val) : tag(Tag::String), p(make_managed_and_finalized<string>(val)) {}
199− any(string&& val) noexcept : tag(Tag::String), p(make_managed_and_finalized<string>(std::move(val))) {}
191+ any(const char * val) : tag(Tag::String), s(make_managed_and_finalized<string>(val)) {}
192+ any(const string& val) : tag(Tag::String), s(make_managed_and_finalized<string>(val)) {}
193+ any(string&& val) noexcept : tag(Tag::String), s(make_managed_and_finalized<string>(std::move(val))) {}
200194
201− any(const managed<string>& val) noexcept : tag(Tag::String), p(val) {}
202− any(managed<string>&& val) noexcept : tag(Tag::String), p(std::move(val)) {}
195+ any(const managed<string>& val) noexcept : tag(Tag::String), s(val) {}
196+ any(managed<string>&& val) noexcept : tag(Tag::String), s(std::move(val)) {}
203197
204198 template <size_t N>
205− any(dict<N>&& val) noexcept : tag(Tag::Dictionary), p(make_managed<dict<N>>(std::move(val))) {}
199+ any(dict<N>&& val) noexcept : tag(Tag::Map), p(make_managed<dict<N>>(std::move(val))) {}
206200
207201 template <size_t N>
208202 any(data<N>&& val) noexcept : tag(Tag::Data), p(make_managed<data<N>>(std::move(val))) {}
209203
210− any(const array& val) : tag(Tag::Array), p(make_managed<array>(val)) {}
211− any(array&& val) noexcept : tag(Tag::Array), p(make_managed<array>(std::move(val))) {}
204+ any(const array& val) : tag(Tag::Array), a(make_managed<array>(val)) {}
205+ any(array&& val) noexcept : tag(Tag::Array), a(make_managed<array>(std::move(val))) {}
212206
213− any(const record& val) : tag(Tag::Record), p(make_managed<record>(val)) {}
214− any(record&& val) noexcept : tag(Tag::Record), p(make_managed<record>(std::move(val))) {}
207+ any(const record& val) : tag(Tag::Record), r(make_managed<record>(val)) {}
208+ any(record&& val) noexcept : tag(Tag::Record), r(make_managed<record>(std::move(val))) {}
215209
216210 template <typename T>
217211 any(const T& val, typename std::enable_if<std::is_convertible<T,fn>::value>::type* = 0) noexcept
@@ -220,7 +214,7 @@ class any {
220214 template <typename T, typename = typename std::enable_if<!std::is_same<any,T>::value &&
221215 !std::is_convertible<T,fn>::value>::type>
222216 any(const T& val, typename std::enable_if<std::is_assignable<std::function<any(const any&)>,T>::value>::type* = 0)
223− : tag(Tag::Closure), p(make_managed<Closure_<T>>(val)) {}
217+ : tag(Tag::Closure), l(make_managed<Closure_<T>>(val)) {}
224218
225219 template <typename T>
226220 any(const T& val, typename std::enable_if<std::is_convertible<T,eff_fn>::value>::type* = 0) noexcept
@@ -230,7 +224,7 @@ class any {
230224 typename = typename std::enable_if<!std::is_same<any,T>::value &&
231225 !std::is_convertible<T,eff_fn>::value>::type>
232226 any(const T& val, typename std::enable_if<std::is_assignable<std::function<any()>,T>::value>::type* = 0)
233− : tag(Tag::EffClosure), p(make_managed<EffClosure_<T>>(val)) {}
227+ : tag(Tag::EffClosure), k(make_managed<EffClosure_<T>>(val)) {}
234228
235229 template <typename T>
236230 any(const T& val, typename std::enable_if<std::is_convertible<T,thunk>::value>::type* = 0) noexcept
@@ -255,56 +249,80 @@ class any {
255249
256250#if !defined(USE_GC)
257251 private:
258− auto destruct() const noexcept -> void {
259− if (isManaged(tag)) {
260− p.~managed<void>();
261− }
252+ template <typename T,
253+ typename U,
254+ typename = typename std::enable_if<!std::is_reference<T>::value>::type>
255+ static constexpr auto move_if_rvalue(U&& u) noexcept -> U&& {
256+ return static_cast<U&&>(u);
257+ }
258+
259+ template <typename T,
260+ typename U,
261+ typename = typename std::enable_if<std::is_reference<T>::value>::type>
262+ static constexpr auto move_if_rvalue(U& u) noexcept -> U& {
263+ return static_cast<U&>(u);
262264 }
263265
264− static_assert(sizeof(u) >= sizeof(t), "size assumption");
265− static_assert(sizeof(u) >= sizeof(i), "size assumption");
266− static_assert(sizeof(u) >= sizeof(d), "size assumption");
267− static_assert(sizeof(u) >= sizeof(c), "size assumption");
268− static_assert(sizeof(u) >= sizeof(b), "size assumption");
269− static_assert(sizeof(u) >= sizeof(f), "size assumption");
270− static_assert(sizeof(u) >= sizeof(e), "size assumption");
271− static_assert(sizeof(u) >= sizeof(v), "size assumption");
272−
273− auto copyAssign(const any& other) const noexcept -> void {
274− if (isManaged(other.tag)) {
275− new (&p) managed<void>(other.p);
276− } else {
277− u = other.u;
266+ template <typename T>
267+ auto assign(T&& other) const noexcept -> void {
268+ switch (other.tag) {
269+ case Tag::Thunk: t = other.t; break;
270+ case Tag::Integer: i = other.i; break;
271+ case Tag::Double: d = other.d; break;
272+ case Tag::Character: c = other.c; break;
273+ case Tag::Boolean: b = other.b; break;
274+ case Tag::Function: f = other.f; break;
275+ case Tag::EffFunction: e = other.e; break;
276+ case Tag::RawPointer: v = other.v; break;
277+
278+ case Tag::String: new (&s) managed<string>(move_if_rvalue<T>(other.s)); break;
279+ case Tag::Array: new (&a) managed<array>(move_if_rvalue<T>(other.a)); break;
280+ case Tag::Record: new (&r) managed<record>(move_if_rvalue<T>(other.r)); break;
281+ case Tag::Closure: new (&l) managed<Closure>(move_if_rvalue<T>(other.l)); break;
282+ case Tag::EffClosure: new (&k) managed<EffClosure>(move_if_rvalue<T>(other.k)); break;
283+ case Tag::Map:
284+ case Tag::Data:
285+ case Tag::Pointer: new (&p) managed<void>(move_if_rvalue<T>(other.p)); break;
286+
287+ default: assert(false && "Bad 'any' tag"); break;
278288 }
279289 }
280− auto moveAssign(any& other) const noexcept -> void {
281− if (isManaged(other.tag)) {
282− new (&p) managed<void>(std::move(other.p));
283− } else {
284− u = other.u;
290+
291+ auto destruct() -> void {
292+ switch (tag) {
293+ case Tag::String: s.~managed<string>(); break;
294+ case Tag::Array: a.~managed<array>(); break;
295+ case Tag::Record: r.~managed<record>(); break;
296+ case Tag::Closure: l.~managed<Closure>(); break;
297+ case Tag::EffClosure: k.~managed<EffClosure>(); break;
298+ case Tag::Map:
299+ case Tag::Data:
300+ case Tag::Pointer: p.~managed<void>(); break;
301+
302+ default: break;
285303 }
286304 }
287305
288306 public:
289307 any(const any& other) noexcept : tag(other.tag) {
290− copyAssign(other);
308+ assign(other);
291309 }
292310
293311 any(any&& other) noexcept : tag(other.tag) {
294− moveAssign(other);
312+ assign(std::move(other));
295313 }
296314
297315 auto operator=(const any& rhs) noexcept -> any& {
298316 destruct();
299317 tag = rhs.tag;
300− copyAssign(rhs);
318+ assign(rhs);
301319 return *this;
302320 }
303321
304322 auto operator=(any&& rhs) noexcept -> any& {
305323 destruct();
306324 tag = rhs.tag;
307− moveAssign(rhs);
325+ assign(std::move(rhs));
308326 return *this;
309327 }
310328
@@ -413,7 +431,7 @@ namespace Private {
413431
414432 template <size_t N>
415433 struct TagHelper<any::dict<N>> {
416− static constexpr any::Tag tag = any::Tag::Dictionary;
434+ static constexpr any::Tag tag = any::Tag::Map;
417435 };
418436
419437 template <size_t N>
@@ -440,8 +458,19 @@ inline auto cast(const any& a) ->
440458 return a;
441459}
442460
461+template <typename T>
462+inline auto cast(const any& a) ->
463+ typename std::enable_if<std::is_same<T, string>::value ||
464+ std::is_same<T, any::array>::value ||
465+ std::is_same<T, any::record>::value, const T&>::type {
466+ return a;
467+}
468+
443469template <typename T,
444− typename = typename std::enable_if<std::is_class<T>::value>::type>
470+ typename = typename std::enable_if<std::is_class<T>::value &&
471+ !std::is_same<T,string>::value &&
472+ !std::is_same<T,any::array>::value &&
473+ !std::is_same<T,any::record>::value>::type>
445474inline auto cast(const any& a) -> T& {
446475 return *static_cast<T*>(a.extractPointer(IF_DEBUG(Private::TagHelper<T>::tag)));
447476}