@@ -27,8 +27,8 @@ namespace purescript {
28 using std::string;
28 using std::string;
30− class boxed : public std::shared_ptr<void> {
31+ std::shared_ptr<void> shared;
33 using fn_t = std::function<boxed(const boxed&)>;
33 using fn_t = std::function<boxed(const boxed&)>;
34 using eff_fn_t = std::function<boxed(void)>;
34 using eff_fn_t = std::function<boxed(void)>;
@@ -36,102 +36,163 @@ namespace purescript {
36 using array_t = std::deque<boxed>;
36 using array_t = std::deque<boxed>;
39− using std::shared_ptr<void>::shared_ptr;
39+ boxed() noexcept : shared() {}
40+ boxed(const std::nullptr_t) noexcept : shared() {}
41− boxed() noexcept : std::shared_ptr<void>() {}
42+ template <typename T>
42− boxed(const std::nullptr_t) noexcept : std::shared_ptr<void>() {}
43+ boxed(std::shared_ptr<T>&& other) : shared(std::move(other)) {}
45+ template <typename T>
43− boxed(const std::shared_ptr<void>& p) : std::shared_ptr<void>::shared_ptr(p) {}
46+ boxed(const std::shared_ptr<T>& other) : shared(other) {}
44− boxed(const int n) : std::shared_ptr<void>(std::make_shared<int>(n)) {}
48+ boxed(const int n) : shared(std::make_shared<int>(n)) {}
45− boxed(const long n) : std::shared_ptr<void>(std::make_shared<int>(static_cast<int>(n))) {
50+ boxed(const long n) : shared(std::make_shared<int>(static_cast<int>(n))) {
46#if !defined(NDEBUG) // if debug build
51#if !defined(NDEBUG) // if debug build
47 if (n < std::numeric_limits<int>::min() || n > std::numeric_limits<int>::max()) {
52 if (n < std::numeric_limits<int>::min() || n > std::numeric_limits<int>::max()) {
48 throw std::runtime_error("integer out of range");
53 throw std::runtime_error("integer out of range");
50#endif // !defined(NDEBUG)
55#endif // !defined(NDEBUG)
52− boxed(const unsigned long n) : std::shared_ptr<void>(std::make_shared<int>(static_cast<int>(n))) {
58+ boxed(const unsigned long n) : shared(std::make_shared<int>(static_cast<int>(n))) {
53#if !defined(NDEBUG) // if debug build
59#if !defined(NDEBUG) // if debug build
54 if (n > std::numeric_limits<int>::max()) {
60 if (n > std::numeric_limits<int>::max()) {
55 throw std::runtime_error("integer out of range");
61 throw std::runtime_error("integer out of range");
57#endif // !defined(NDEBUG)
63#endif // !defined(NDEBUG)
59− boxed(const double n) : std::shared_ptr<void>(std::make_shared<double>(n)) {}
66+ boxed(const double n) : shared(std::make_shared<double>(n)) {}
60− boxed(const bool b) : std::shared_ptr<void>(std::make_shared<bool>(b)) {}
67+ boxed(const bool b) : shared(std::make_shared<bool>(b)) {}
61− boxed(const char s[]) : std::shared_ptr<void>(std::make_shared<string>(s)) {}
68+ boxed(const char s[]) : shared(std::make_shared<string>(s)) {}
62− boxed(string&& s) : std::shared_ptr<void>(std::make_shared<string>(std::move(s))) {}
69+ boxed(string&& s) : shared(std::make_shared<string>(std::move(s))) {}
63− boxed(const string& s) : std::shared_ptr<void>(std::make_shared<string>(s)) {}
70+ boxed(const string& s) : shared(std::make_shared<string>(s)) {}
64− boxed(array_t&& l) : std::shared_ptr<void>(std::make_shared<array_t>(std::move(l))) {}
71+ boxed(array_t&& l) : shared(std::make_shared<array_t>(std::move(l))) {}
65− boxed(const array_t& l) : std::shared_ptr<void>(std::make_shared<array_t>(l)) {}
72+ boxed(const array_t& l) : shared(std::make_shared<array_t>(l)) {}
66− boxed(dict_t&& m) : std::shared_ptr<void>(std::make_shared<dict_t>(std::move(m))) {}
73+ boxed(dict_t&& m) : shared(std::make_shared<dict_t>(std::move(m))) {}
67− boxed(const dict_t& m) : std::shared_ptr<void>(std::make_shared<dict_t>(m)) {}
74+ boxed(const dict_t& m) : shared(std::make_shared<dict_t>(m)) {}
69 template <typename T,
76 template <typename T,
70 typename = typename std::enable_if<!std::is_same<boxed,T>::value>::type>
77 typename = typename std::enable_if<!std::is_same<boxed,T>::value>::type>
71 boxed(const T& f,
78 boxed(const T& f,
72 typename std::enable_if<std::is_assignable<std::function<boxed(boxed)>,T>::value>::type* = 0)
79 typename std::enable_if<std::is_assignable<std::function<boxed(boxed)>,T>::value>::type* = 0)
73− : std::shared_ptr<void>(std::make_shared<fn_t>(f)) {
80+ : shared(std::make_shared<fn_t>(f)) {
76 template <typename T,
83 template <typename T,
77 typename = typename std::enable_if<!std::is_same<boxed,T>::value>::type>
84 typename = typename std::enable_if<!std::is_same<boxed,T>::value>::type>
78 boxed(const T& f,
85 boxed(const T& f,
79 typename std::enable_if<std::is_assignable<std::function<boxed(void)>,T>::value>::type* = 0)
86 typename std::enable_if<std::is_assignable<std::function<boxed(void)>,T>::value>::type* = 0)
80− : std::shared_ptr<void>(std::make_shared<eff_fn_t>(f)) {
87+ : shared(std::make_shared<eff_fn_t>(f)) {
90+ inline auto get() const noexcept -> void * {
83 auto operator()(const boxed& arg) const -> boxed {
94 auto operator()(const boxed& arg) const -> boxed {
84− auto& f = *static_cast<fn_t*>(get());
95+ auto& f = *static_cast<fn_t*>(shared.get());
85 return f(arg);
96 return f(arg);
88 auto operator()() const -> boxed {
99 auto operator()() const -> boxed {
89− auto& f = *static_cast<eff_fn_t*>(get());
100+ auto& f = *static_cast<eff_fn_t*>(shared.get());
90 return f();
101 return f();
93 auto operator[](const char key[]) const -> const boxed& {
104 auto operator[](const char key[]) const -> const boxed& {
94− return (*static_cast<const dict_t*>(get()))[key];
105+ return (*static_cast<const dict_t*>(shared.get()))[key];
97 auto operator[](const char key[]) -> boxed& {
108 auto operator[](const char key[]) -> boxed& {
98− return (*static_cast<dict_t*>(get()))[key];
109+ return (*static_cast<dict_t*>(shared.get()))[key];
101#if !defined(NDEBUG) // if debug build
112#if !defined(NDEBUG) // if debug build
102 auto operator[](const int index) const -> const boxed& {
113 auto operator[](const int index) const -> const boxed& {
103− return static_cast<const array_t*>(get())->at(index);
114+ return static_cast<const array_t*>(shared.get())->at(index);
106 auto operator[](const int index) -> boxed& {
117 auto operator[](const int index) -> boxed& {
107− return static_cast<array_t*>(get())->at(index);
118+ return static_cast<array_t*>(shared.get())->at(index);
109#else // not debug build
120#else // not debug build
110 auto operator[](const int index) const -> const boxed& {
121 auto operator[](const int index) const -> const boxed& {
111− return (*static_cast<const array_t*>(get()))[index];
122+ return (*static_cast<const array_t*>(shared.get()))[index];
114 auto operator[](const int index) -> boxed& {
125 auto operator[](const int index) -> boxed& {
115− return (*static_cast<array_t*>(get()))[index];
126+ return (*static_cast<array_t*>(shared.get()))[index];
117#endif // !defined(NDEBUG)
128#endif // !defined(NDEBUG)
119 class weak {
130 class weak {
120− std::weak_ptr<void> ptr;
131+ std::weak_ptr<void> wptr;
123 weak() = delete;
134 weak() = delete;
124− weak(boxed& b) : ptr(b) {}
135+ weak(boxed& b) : wptr(b.shared) {}
126 operator boxed() const {
137 operator boxed() const {
127#if defined(NDEBUG)
138#if defined(NDEBUG)
128− return ptr.lock();
139+ return wptr.lock();
130− return static_cast<std::shared_ptr<void>>(ptr);
141+ return static_cast<std::shared_ptr<void>>(wptr);
134− }; // class weak
145+ }; // class boxed::weak
148+ std::shared_ptr<boxed> sptr;
149+ std::shared_ptr<boxed::weak> wptr;
152+ ref() : sptr(std::make_shared<boxed>())
153+ , wptr(std::make_shared<boxed::weak>(*sptr)) {}
155+ operator const boxed&() const {
163+ auto operator()() const -> boxed {
167+ auto operator()(const boxed& arg) const -> boxed {
168+ return (*sptr)(arg);
171+ template <typename T>
172+ auto operator=(T&& right) -> ref& {
173+ *sptr = std::forward<T>(right);
179+ std::shared_ptr<boxed::weak> wptr;
181+ weak(const ref& r) : wptr(r.wptr) {}
183+ operator boxed() const {
187+ auto operator()() const -> boxed {
188+ return static_cast<boxed>(*wptr)();
191+ auto operator()(const boxed& arg) const -> boxed {
192+ return static_cast<boxed>(*wptr)(arg);
194+ }; // class ref::weak
195+ }; // class boxed::ref
136 }; // class boxed
197 }; // class boxed
@@ -166,60 +227,6 @@ namespace purescript {
166 return value;
227 return value;
170− friend class boxed_weak_r;
171− std::shared_ptr<boxed> ptr;
172− std::shared_ptr<boxed::weak> wptr;
175− boxed_r() : ptr(std::make_shared<boxed>())
176− , wptr(std::make_shared<boxed::weak>(*ptr)) {}
178− operator const boxed&() const {
186− auto operator()() const -> boxed {
190− auto operator()(const boxed& arg) const -> boxed {
194− template <typename T>
195− auto operator=(T&& right) -> boxed_r& {
196− *ptr = std::forward<T>(right);
203− class boxed_weak_r {
204− std::shared_ptr<boxed::weak> wptr;
207− boxed_weak_r(const boxed_r& r) : wptr(r.wptr) {}
209− operator boxed() const {
213− auto operator()() const -> boxed {
214− return static_cast<boxed>(*wptr)();
217− auto operator()(const boxed& arg) const -> boxed {
218− return static_cast<boxed>(*wptr)(arg);
221− }; // class boxed_weak_r
223 inline auto array_length(const boxed& a) -> boxed::array_t::size_type {
230 inline auto array_length(const boxed& a) -> boxed::array_t::size_type {
224 return unbox<boxed::array_t>(a).size();
231 return unbox<boxed::array_t>(a).size();