git.iko.soy/rowtype-yoga/purescript-native
on 9651f53 help sign in
242 lines 8.2 kB history raw
1///////////////////////////////////////////////////////////////////////////////
2//
3// Module : purescript.h
4// Copyright : (c) Andy Arvanitis 2018
5// License : BSD
6//
7// Maintainer : Andy Arvanitis
8// Stability : experimental
9// Portability :
10//
11// Basic types and functions to support purescript-to-C++ rendering
12//
13///////////////////////////////////////////////////////////////////////////////
14//
15#ifndef purescript_H
16#define purescript_H
18#include <memory>
19#include <vector>
20#include <string>
21#include <utility>
22#if !defined(NDEBUG)
23#include <limits>
24#endif
25#if !defined(PURESCRIPT_DISABLE_EXCEPTIONS)
26#include <stdexcept>
27#endif
28#include "functions.h"
29#include "dictionary.h"
30#include "recursion.h"
32namespace purescript {
34 using std::string;
36 class boxed {
37 public:
38 std::shared_ptr<void> shared;
39 union {
40 int _int_;
41 double _double_;
42 bool _bool_;
43 };
45 public:
46 using fn_t = _template_::fn_t<boxed>;
47 using eff_fn_t = _template_::eff_fn_t<boxed>;
49 using dict_t = _template_::dict_t<boxed>;
50 using array_t = std::vector<boxed>;
52 using weak = _template_::weak<boxed>;
53 using recur = _template_::recur<boxed>;
55 private:
56 template <typename T>
57 using fn_T = _template_::fn_T<boxed, T>;
59 template <typename T>
60 using eff_fn_T = _template_::eff_fn_T<boxed, T>;
62 public:
63 boxed() noexcept : shared() {}
64 boxed(const std::nullptr_t) noexcept : shared() {}
66 boxed(const weak& w) : shared(w.shared()) {}
67 boxed(const recur& r) : shared(r.shared()) {}
68 boxed(const recur::weak& w) : shared(w.shared()) {}
70 template <typename T>
71 boxed(std::shared_ptr<T>&& other) noexcept : shared(std::move(other)) {}
73 template <typename T>
74 boxed(const std::shared_ptr<T>& other) : shared(other) {}
76 boxed(const int n) noexcept : _int_(n) {}
77 boxed(const long n);
78 boxed(const unsigned long n);
79 boxed(const double n) noexcept : _double_(n) {}
80 boxed(const bool b) noexcept : _bool_(b) {}
81 boxed(const char s[]) : shared(std::make_shared<string>(s)) {}
82 boxed(string&& s) : shared(std::make_shared<string>(std::move(s))) {}
83 boxed(const string& s) : shared(std::make_shared<string>(s)) {}
84 boxed(array_t&& l) : shared(std::make_shared<array_t>(std::move(l))) {}
85 boxed(const array_t& l) : shared(std::make_shared<array_t>(l)) {}
86 boxed(dict_t&& m) : shared(std::make_shared<dict_t>(std::move(m))) {}
87 boxed(const dict_t& m) : shared(std::make_shared<dict_t>(m)) {}
89 template <typename T,
90 typename = typename std::enable_if<!std::is_same<boxed,T>::value>::type>
91 boxed(T f,
92 typename std::enable_if<std::is_same<decltype(std::declval<T>()(std::declval<boxed>())),
93 boxed>::value>::type* = 0)
94 : shared(std::shared_ptr<fn_t>(std::make_shared<fn_T<T>>(std::move(f)))) {
95 }
97 template <typename T,
98 typename = typename std::enable_if<!std::is_same<boxed,T>::value>::type>
99 boxed(T f,
100 typename std::enable_if<std::is_same<decltype(std::declval<T>()()),
101 boxed>::value>::type* = 0)
102 : shared(std::shared_ptr<eff_fn_t>(std::make_shared<eff_fn_T<T>>(std::move(f)))) {
103 }
105 auto get() const noexcept -> void * {
106 return shared.get();
107 }
109 auto operator()(const boxed& arg) const -> boxed {
110 return (*static_cast<fn_t*>(shared.get()))(arg);
111 }
113 auto operator()() const -> boxed {
114 return (*static_cast<eff_fn_t*>(shared.get()))();
115 }
117 auto operator[](const char key[]) const -> const boxed& {
118 return (*static_cast<const dict_t*>(shared.get()))[key];
119 }
121 auto operator[](const char key[]) -> boxed& {
122 return (*static_cast<dict_t*>(shared.get()))[key];
123 }
125 auto operator[](const int index) const -> const boxed&;
126 auto operator[](const int index) -> boxed&;
128 }; // class boxed
130 extern template class _template_::fn_t<boxed>;
131 extern template class _template_::eff_fn_t<boxed>;
132 extern template class _template_::dict_t<boxed>;
133 extern template class _template_::weak<boxed>;
134 extern template class _template_::recur<boxed>;
136 extern const boxed undefined;
138 using fn_t = boxed::fn_t;
139 using eff_fn_t = boxed::eff_fn_t;
140 using dict_t = boxed::dict_t;
141 using array_t = boxed::array_t;
143 template <typename T, typename... Args,
144 typename = typename std::enable_if<!std::is_same<T, int>::value &&
145 !std::is_same<T, double>::value &&
146 !std::is_same<T, bool>::value
147 >::type>
148 inline auto box(Args&&... args) -> boxed {
149 return std::make_shared<T>(std::forward<Args>(args)...);
150 }
152 template <typename T,
153 typename std::enable_if<std::is_same<T, int>::value, T>::type* = nullptr>
154 inline auto box(T arg) noexcept -> boxed {
155 return boxed(arg);
156 }
158 template <typename T,
159 typename std::enable_if<std::is_same<T, double>::value, T>::type* = nullptr>
160 inline auto box(T arg) noexcept -> boxed {
161 return boxed(arg);
162 }
164 template <typename T,
165 typename std::enable_if<std::is_same<T, bool>::value, T>::type* = nullptr>
166 inline auto box(T arg) noexcept -> boxed {
167 return boxed(arg);
168 }
170 template <typename T,
171 typename = typename std::enable_if<!std::is_same<T, int>::value &&
172 !std::is_same<T, double>::value &&
173 !std::is_same<T, bool>::value
174 >::type>
175 constexpr auto unbox(const boxed& b) -> const T& {
176 return *static_cast<const T*>(b.get());
177 }
179 template <typename T,
180 typename std::enable_if<std::is_same<T, int>::value, T>::type* = nullptr>
181 constexpr auto unbox(const boxed& b) noexcept -> T {
182 return b._int_;
183 }
185 template <typename T,
186 typename std::enable_if<std::is_same<T, double>::value, T>::type* = nullptr>
187 constexpr auto unbox(const boxed& b) noexcept -> T {
188 return b._double_;
189 }
191 template <typename T,
192 typename std::enable_if<std::is_same<T, bool>::value, T>::type* = nullptr>
193 constexpr auto unbox(const boxed& b) noexcept -> T {
194 return b._bool_;
195 }
197 template <typename T,
198 typename = typename std::enable_if<!std::is_same<T, int>::value &&
199 !std::is_same<T, double>::value &&
200 !std::is_same<T, bool>::value
201 >::type>
202 constexpr auto unbox(boxed& b) -> T& {
203 return *static_cast<T*>(b.get());
204 }
206 template <typename T>
207 constexpr auto unbox(const T value) noexcept -> T {
208 return value;
209 }
211 template <typename T,
212 typename = typename std::enable_if<std::is_same<T, int>::value>::type>
213 constexpr auto unbox(const std::size_t value) noexcept -> long long {
214 return value;
215 }
217 inline auto array_length(const boxed& a) -> boxed::array_t::size_type {
218 return unbox<boxed::array_t>(a).size();
219 }
221} // namespace purescript
223#if !defined(PURESCRIPT_DISABLE_EXCEPTIONS)
224#define THROW_(e) throw std::runtime_error(s)
225#else
226#define THROW_(e) return undefined
227#endif
229#define DEFINE_FOREIGN_DICTIONARY_AND_ACCESSOR() \
230 inline auto foreign() -> dict_t& {\
231 static dict_t _;\
232 return _;\
233 }
235#define FOREIGN_BEGIN(NS) namespace NS {\
236 using namespace purescript;\
237 DEFINE_FOREIGN_DICTIONARY_AND_ACCESSOR()\
238 static const auto data = ([]() -> char {\
239 dict_t& exports = foreign();
240#define FOREIGN_END return 0; }()); }
242#endif // purescript_H