/////////////////////////////////////////////////////////////////////////////// // // Module : purescript.h // Copyright : (c) Andy Arvanitis 2018 // License : BSD // // Maintainer : Andy Arvanitis // Stability : experimental // Portability : // // Basic types and functions to support purescript-to-C++ rendering // /////////////////////////////////////////////////////////////////////////////// // #ifndef purescript_H #define purescript_H #include #include #include #include #include #include namespace purescript { using std::string; class boxed : public std::shared_ptr { using fn = std::function; using eff_fn = std::function; public: using std::shared_ptr::shared_ptr; boxed(const int n) : std::shared_ptr(std::make_shared(n)) { } boxed(const double n) : std::shared_ptr(std::make_shared(n)) { } boxed(const bool b) : std::shared_ptr(std::make_shared(b)) { } boxed(const char s[]) : std::shared_ptr(std::make_shared(s)) { } boxed(string&& s) : std::shared_ptr(std::make_shared(std::move(s))) { } boxed(const std::nullptr_t) : std::shared_ptr() { } boxed(std::initializer_list l) : std::shared_ptr(std::make_shared>(l)) { } boxed(std::initializer_list> m) : std::shared_ptr(std::make_shared>(m)) { } template ::value>::type> boxed(const T& f, typename std::enable_if,T>::value>::type* = 0) : std::shared_ptr(std::make_shared(f)) { } template ::value>::type> boxed(const T& f, typename std::enable_if,T>::value>::type* = 0) : std::shared_ptr(std::make_shared(f)) { } template ::value && std::is_convertible::value>::type> auto operator=(const T& right) -> boxed& { if (std::shared_ptr::operator bool()) { auto& f = *static_cast(get()); f = right; } else { reset(new fn(right)); } return *this; } auto operator()(const boxed& arg) const -> boxed { auto& f = *static_cast(get()); return f(arg); } auto operator()() const -> boxed { auto& f = *static_cast(get()); return f(); } auto operator[](const char key[]) const -> boxed { const auto& dict = *static_cast*>(get()); return dict.at(key); } }; template inline auto box(Args&&... args) -> boxed { return std::make_shared(std::forward(args)...); } template inline auto unbox(const boxed& b) -> const T& { const auto& unboxed = *static_cast(b.get()); return unboxed; } template inline auto peek(boxed& b) -> T& { auto& unboxed = *static_cast(b.get()); return unboxed; } template inline auto copy(const boxed& b) -> boxed { return box(unbox(b)); } using fn_t = std::function; using dict_t = std::map; using array_t = std::deque; using as_array = std::initializer_list; using as_dict = std::initializer_list>; constexpr auto undefined = nullptr; } // namespace purescript #define FOREIGN_EXPORTS(NS) namespace NS { using namespace purescript; auto _foreign_() -> dict_t&; static const auto& NS ## _foreign_init = []() { dict_t& foreign = _foreign_(); #define END_FOREIGN_EXPORTS return foreign; }(); } #endif // purescript_H