git.iko.soy/rowtype-yoga/purescript-native
on b351f82 help sign in
129 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 int64_t n) : std::shared_ptr<void>(std::make_shared<int64_t>(n)) {
25 }
27 boxed(const int n) : std::shared_ptr<void>(std::make_shared<int64_t>(n)) {
28 }
30 boxed(const unsigned int n) : std::shared_ptr<void>(std::make_shared<int64_t>(n)) {
31 }
33 boxed(const double n) : std::shared_ptr<void>(std::make_shared<double>(n)) {
34 }
36 boxed(const char s[]) : std::shared_ptr<void>(std::make_shared<string>(s)) {
37 }
39 boxed(string&& s) : std::shared_ptr<void>(std::make_shared<string>(std::move(s))) {
40 }
42 boxed(const std::nullptr_t) : std::shared_ptr<void>() {
43 }
45 boxed(std::initializer_list<boxed> l) : std::shared_ptr<void>(std::make_shared<std::deque<boxed>>(l)) {
46 }
48 boxed(std::initializer_list<std::pair<const string, boxed>> m) : std::shared_ptr<void>(std::make_shared<std::map<string, boxed>>(m)) {
49 }
51 template <typename T,
52 typename = typename std::enable_if<!std::is_same<boxed,T>::value>::type>
53 boxed(const T& f,
54 typename std::enable_if<std::is_assignable<std::function<boxed(boxed)>,T>::value>::type* = 0) : std::shared_ptr<void>(std::make_shared<fn>(f)) {
55 }
57 template <typename T,
58 typename = typename std::enable_if<!std::is_same<boxed,T>::value>::type>
59 boxed(const T& f,
60 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)) {
61 }
63 template <typename T,
64 typename = typename std::enable_if<!std::is_same<boxed,T>::value &&
65 std::is_convertible<T,fn>::value>::type>
66 auto operator=(const T& right) -> boxed& {
67 if (std::shared_ptr<void>::operator bool()) {
68 auto& f = *static_cast<fn*>(get());
69 f = right;
70 } else {
71 reset(new fn(right));
72 }
73 return *this;
74 }
76 auto operator()(const boxed& arg) const -> boxed {
77 auto& f = *static_cast<fn*>(get());
78 return f(arg);
79 }
81 auto operator()() const -> boxed {
82 auto& f = *static_cast<eff_fn*>(get());
83 return f();
84 }
86 auto operator[](const char key[]) const -> boxed {
87 const auto& dict = *static_cast<const std::map<const string, boxed>*>(get());
88 return dict.at(key);
89 }
91 };
93 template <typename T, typename... Args>
94 inline auto box(Args&&... args) -> boxed {
95 return std::make_shared<T>(std::forward<Args>(args)...);
96 }
98 template <typename T>
99 inline auto unbox(const boxed& b) -> const T& {
100 const auto& unboxed = *static_cast<const T*>(b.get());
101 return unboxed;
102 }
104 template <typename T>
105 inline auto peek(boxed& b) -> T& {
106 auto& unboxed = *static_cast<T*>(b.get());
107 return unboxed;
108 }
110 template <typename T>
111 inline auto copy(const boxed& b) -> boxed {
112 return box<T>(unbox<T>(b));
113 }
115 using fn_t = std::function<boxed(const boxed&)>;
116 using dict_t = std::map<const string, boxed>;
117 using array_t = std::deque<boxed>;
119 using as_array = std::initializer_list<boxed>;
120 using as_dict = std::initializer_list<std::pair<const string, boxed>>;
122 constexpr auto undefined = nullptr;
124} // namespace purescript
126#define FOREIGN_EXPORTS(NS) namespace NS { static const auto& NS ## _foreign_init = []() { dict_t& foreign = _foreign_();
127#define END_FOREIGN_EXPORTS return foreign; }(); }
129#endif // purescript_H