git.iko.soy/rowtype-yoga/purescript-native
on ade15d3 help sign in
126 lines 4.1 kB history raw
1#ifndef purescript_H
2#define purescript_H
4#include <memory>
5#include <functional>
6#include <deque>
7#include <map>
8#include <string>
10#include <iostream>
12namespace purescript {
14 using std::string;
16 class boxed : public std::shared_ptr<void> {
18 using fn = std::function<boxed(const boxed&)>;
19 using eff_fn = std::function<boxed(void)>;
21 public:
22 using std::shared_ptr<void>::shared_ptr;
24 boxed(const int n) : std::shared_ptr<void>(std::make_shared<int>(n)) {
25 }
27 boxed(const double n) : std::shared_ptr<void>(std::make_shared<double>(n)) {
28 }
30 boxed(const bool b) : std::shared_ptr<void>(std::make_shared<bool>(b)) {
31 }
33 boxed(const char s[]) : std::shared_ptr<void>(std::make_shared<string>(s)) {
34 }
36 boxed(string&& s) : std::shared_ptr<void>(std::make_shared<string>(std::move(s))) {
37 }
39 boxed(const std::nullptr_t) : std::shared_ptr<void>() {
40 }
42 boxed(std::initializer_list<boxed> l) : std::shared_ptr<void>(std::make_shared<std::deque<boxed>>(l)) {
43 }
45 boxed(std::initializer_list<std::pair<const string, boxed>> m) : std::shared_ptr<void>(std::make_shared<std::map<string, boxed>>(m)) {
46 }
48 template <typename T,
49 typename = typename std::enable_if<!std::is_same<boxed,T>::value>::type>
50 boxed(const T& f,
51 typename std::enable_if<std::is_assignable<std::function<boxed(boxed)>,T>::value>::type* = 0) : std::shared_ptr<void>(std::make_shared<fn>(f)) {
52 }
54 template <typename T,
55 typename = typename std::enable_if<!std::is_same<boxed,T>::value>::type>
56 boxed(const T& f,
57 typename std::enable_if<std::is_assignable<std::function<boxed(void)>,T>::value>::type* = 0) : std::shared_ptr<void>(std::make_shared<eff_fn>(f)) {
58 }
60 template <typename T,
61 typename = typename std::enable_if<!std::is_same<boxed,T>::value &&
62 std::is_convertible<T,fn>::value>::type>
63 auto operator=(const T& right) -> boxed& {
64 if (std::shared_ptr<void>::operator bool()) {
65 auto& f = *static_cast<fn*>(get());
66 f = right;
67 } else {
68 reset(new fn(right));
69 }
70 return *this;
71 }
73 auto operator()(const boxed& arg) const -> boxed {
74 auto& f = *static_cast<fn*>(get());
75 return f(arg);
76 }
78 auto operator()() const -> boxed {
79 auto& f = *static_cast<eff_fn*>(get());
80 return f();
81 }
83 auto operator[](const char key[]) const -> boxed {
84 const auto& dict = *static_cast<const std::map<const string, boxed>*>(get());
85 return dict.at(key);
86 }
88 };
90 template <typename T, typename... Args>
91 inline auto box(Args&&... args) -> boxed {
92 return std::make_shared<T>(std::forward<Args>(args)...);
93 }
95 template <typename T>
96 inline auto unbox(const boxed& b) -> const T& {
97 const auto& unboxed = *static_cast<const T*>(b.get());
98 return unboxed;
99 }
101 template <typename T>
102 inline auto peek(boxed& b) -> T& {
103 auto& unboxed = *static_cast<T*>(b.get());
104 return unboxed;
105 }
107 template <typename T>
108 inline auto copy(const boxed& b) -> boxed {
109 return box<T>(unbox<T>(b));
110 }
112 using fn_t = std::function<boxed(const boxed&)>;
113 using dict_t = std::map<const string, boxed>;
114 using array_t = std::deque<boxed>;
116 using as_array = std::initializer_list<boxed>;
117 using as_dict = std::initializer_list<std::pair<const string, boxed>>;
119 constexpr auto undefined = nullptr;
121} // namespace purescript
123#define FOREIGN_EXPORTS(NS) namespace NS { using namespace purescript; auto _foreign_() -> dict_t&; static const auto& NS ## _foreign_init = []() { dict_t& foreign = _foreign_();
124#define END_FOREIGN_EXPORTS return foreign; }(); }
126#endif // purescript_H