@@ -16,7 +16,6 @@
16#define purescript_H
16#define purescript_H
18#include <memory>
18#include <memory>
20#include <deque>
19#include <deque>
21#include <string>
20#include <string>
22#include <limits>
21#include <limits>
@@ -29,6 +28,7 @@ namespace purescript {
30 class boxed {
29 class boxed {
31 std::shared_ptr<void> shared;
30 std::shared_ptr<void> shared;
34 int _int_;
34 int _int_;
@@ -36,8 +36,38 @@ namespace purescript {
36 bool _bool_;
36 bool _bool_;
39− using fn_t = std::function<boxed(const boxed&)>;
39+ class fn_t {
40− using eff_fn_t = std::function<boxed(void)>;
40+ public:
42+ virtual auto operator ()(const boxed&) const -> boxed = 0;
45+ template <typename T>
46+ class fn_template_t : public fn_t {
49+ fn_template_t(T f) : fn(std::move(f)) {}
50+ auto operator ()(const boxed& arg) const -> boxed override {
57+ virtual ~eff_fn_t() {}
58+ virtual auto operator ()() const -> boxed = 0;
61+ template <typename T>
62+ class eff_fn_template_t : public eff_fn_t {
65+ eff_fn_template_t(T f) : fn(std::move(f)) {}
66+ auto operator ()() const -> boxed override {
41 using dict_t = string_literal_dict_t<boxed>;
71 using dict_t = string_literal_dict_t<boxed>;
42 using array_t = std::deque<boxed>;
72 using array_t = std::deque<boxed>;
@@ -81,16 +111,18 @@ namespace purescript {
82 template <typename T,
112 template <typename T,
83 typename = typename std::enable_if<!std::is_same<boxed,T>::value>::type>
113 typename = typename std::enable_if<!std::is_same<boxed,T>::value>::type>
84− boxed(const T& f,
114+ boxed(T f,
85− typename std::enable_if<std::is_assignable<std::function<boxed(boxed)>,T>::value>::type* = 0)
115+ typename std::enable_if<std::is_same<decltype(std::declval<T>()(std::declval<boxed>())),
116+ boxed>::value>::type* = 0)
86− : shared(std::make_shared<fn_t>(f)) {
117+ : shared(std::make_shared<fn_template_t<T>>(std::move(f))) {
89 template <typename T,
120 template <typename T,
90 typename = typename std::enable_if<!std::is_same<boxed,T>::value>::type>
121 typename = typename std::enable_if<!std::is_same<boxed,T>::value>::type>
91− boxed(const T& f,
122+ boxed(T f,
92− typename std::enable_if<std::is_assignable<std::function<boxed(void)>,T>::value>::type* = 0)
123+ typename std::enable_if<std::is_same<decltype(std::declval<T>()()),
124+ boxed>::value>::type* = 0)
93− : shared(std::make_shared<eff_fn_t>(f)) {
125+ : shared(std::make_shared<eff_fn_template_t<T>>(std::move(f))) {
96 inline auto get() const noexcept -> void * {
128 inline auto get() const noexcept -> void * {