1///////////////////////////////////////////////////////////////////////////////
3// Module : purescript.h
4// Copyright : (c) Andy Arvanitis 2018
7// Maintainer : Andy Arvanitis
8// Stability : experimental
11// Basic types and functions to support purescript-to-C++ rendering
13///////////////////////////////////////////////////////////////////////////////
23#include "string_literal_dict.h"
30 class boxed : public std::shared_ptr<void> {
33 using fn_t = std::function<boxed(const boxed&)>;
34 using eff_fn_t = std::function<boxed(void)>;
35 using dict_t = string_literal_dict_t<boxed>;
36 using array_t = std::deque<boxed>;
39 using std::shared_ptr<void>::shared_ptr;
41 boxed() noexcept : std::shared_ptr<void>() {}
42 boxed(const std::nullptr_t) noexcept : std::shared_ptr<void>() {}
43 boxed(const int n) : std::shared_ptr<void>(std::make_shared<int>(n)) {}
45 boxed(const long n) : std::shared_ptr<void>(std::make_shared<int>(static_cast<int>(n))) {
46#if !defined(NDEBUG) // if debug build
47 if (n < std::numeric_limits<int>::min() || n > std::numeric_limits<int>::max()) {
48 throw std::runtime_error("integer out of range");
50#endif // !defined(NDEBUG)
53 boxed(const unsigned long n) : std::shared_ptr<void>(std::make_shared<int>(static_cast<int>(n))) {
54#if !defined(NDEBUG) // if debug build
55 if (n > std::numeric_limits<int>::max()) {
56 throw std::runtime_error("integer out of range");
58#endif // !defined(NDEBUG)
61 boxed(const double n) : std::shared_ptr<void>(std::make_shared<double>(n)) {}
62 boxed(const bool b) : std::shared_ptr<void>(std::make_shared<bool>(b)) {}
63 boxed(const char s[]) : std::shared_ptr<void>(std::make_shared<string>(s)) {}
64 boxed(string&& s) : std::shared_ptr<void>(std::make_shared<string>(std::move(s))) {}
65 boxed(const string& s) : std::shared_ptr<void>(std::make_shared<string>(s)) {}
66 boxed(array_t&& l) : std::shared_ptr<void>(std::make_shared<array_t>(std::move(l))) {}
67 boxed(const array_t& l) : std::shared_ptr<void>(std::make_shared<array_t>(l)) {}
68 boxed(dict_t&& m) : std::shared_ptr<void>(std::make_shared<dict_t>(std::move(m))) {}
69 boxed(const dict_t& m) : std::shared_ptr<void>(std::make_shared<dict_t>(m)) {}
72 typename = typename std::enable_if<!std::is_same<boxed,T>::value>::type>
74 typename std::enable_if<std::is_assignable<std::function<boxed(boxed)>,T>::value>::type* = 0)
75 : std::shared_ptr<void>(std::make_shared<fn_t>(f)) {
79 typename = typename std::enable_if<!std::is_same<boxed,T>::value>::type>
81 typename std::enable_if<std::is_assignable<std::function<boxed(void)>,T>::value>::type* = 0)
82 : std::shared_ptr<void>(std::make_shared<eff_fn_t>(f)) {
85 auto operator()(const boxed& arg) const -> boxed {
86 auto& f = *static_cast<fn_t*>(get());
90 auto operator()() const -> boxed {
91 auto& f = *static_cast<eff_fn_t*>(get());
95 auto operator[](const char key[]) const -> const boxed& {
96 return (*static_cast<const dict_t*>(get()))[key];
99 auto operator[](const char key[]) -> boxed& {
100 return (*static_cast<dict_t*>(get()))[key];
103#if !defined(NDEBUG) // if debug build
104 auto operator[](const int index) const -> const boxed& {
105 return static_cast<const array_t*>(get())->at(index);
108 auto operator[](const int index) -> boxed& {
109 return static_cast<array_t*>(get())->at(index);
111#else // not debug build
112 auto operator[](const int index) const -> const boxed& {
113 return (*static_cast<const array_t*>(get()))[index];
116 auto operator[](const int index) -> boxed& {
117 return (*static_cast<array_t*>(get()))[index];
119#endif // !defined(NDEBUG)
123 using fn_t = boxed::fn_t;
124 using eff_fn_t = boxed::eff_fn_t;
125 using dict_t = boxed::dict_t;
126 using array_t = boxed::array_t;
128 class boxed_r : private std::shared_ptr<void> {
130 boxed_r() : std::shared_ptr<void>(std::make_shared<boxed>()) {}
132 operator const boxed&() const {
133 return *static_cast<const boxed*>(get());
136 auto operator()(const boxed& arg) const -> boxed {
137 auto& b = *static_cast<boxed*>(get());
138 auto& f = *static_cast<fn_t*>(b.get());
142 auto operator()() const -> boxed {
143 auto& b = *static_cast<boxed*>(get());
144 auto& f = *static_cast<eff_fn_t*>(b.get());
148 template <typename T>
149 auto operator=(T&& right) -> boxed_r& {
150 auto& b = *static_cast<boxed*>(get());
151 b = std::forward<T>(right);
157 template <typename T, typename... Args>
158 inline auto box(Args&&... args) -> boxed {
159 return std::make_shared<T>(std::forward<Args>(args)...);
162 template <typename T>
163 constexpr auto unbox(const boxed& b) -> const T& {
164 return *static_cast<const T*>(b.get());
167 template <typename T>
168 constexpr auto unbox(boxed& b) -> T& {
169 return *static_cast<T*>(b.get());
172 template <typename T>
173 constexpr auto unbox(const T value) -> T {
177 template <typename T,
178 typename = typename std::enable_if<std::is_same<T, int>::value>::type>
179 constexpr auto unbox(const std::size_t value) -> long long {
183 inline auto array_length(const boxed& a) -> boxed::array_t::size_type {
184 return unbox<boxed::array_t>(a).size();
187 constexpr auto undefined = nullptr;
189} // namespace purescript
191#define DEFINE_FOREIGN_DICTIONARY_AND_ACCESSOR() \
192 inline auto foreign() -> dict_t& {\
193 static dict_t $dict$;\
197#define FOREIGN_BEGIN(NS) namespace NS {\
198 using namespace purescript;\
199 DEFINE_FOREIGN_DICTIONARY_AND_ACCESSOR()\
200 static const auto $foreign_exports_init$ = ([]() -> char {\
201 dict_t& exports = foreign();
202#define FOREIGN_END return 0; }()); }
204#endif // purescript_H
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list