git.iko.soy/rowtype-yoga/purescript-native
on 4cf7428 help sign in
179 lines 5.5 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 <functional>
20#include <deque>
21#include <map>
22#include <string>
24#include <iostream>
26namespace purescript {
28 using std::string;
30 class boxed : public std::shared_ptr<void> {
32 public:
33 using fn_t = std::function<boxed(const boxed&)>;
34 using eff_fn_t = std::function<boxed(void)>;
35 using dict_t = std::map<const string, boxed>;
36 using array_t = std::deque<boxed>;
38 public:
39 using std::shared_ptr<void>::shared_ptr;
41 boxed(const int n) : std::shared_ptr<void>(std::make_shared<int>(n)) {
42 }
44 boxed(const double n) : std::shared_ptr<void>(std::make_shared<double>(n)) {
45 }
47 boxed(const bool b) : std::shared_ptr<void>(std::make_shared<bool>(b)) {
48 }
50 boxed(const char s[]) : std::shared_ptr<void>(std::make_shared<string>(s)) {
51 }
53 boxed(string&& s) : std::shared_ptr<void>(std::make_shared<string>(std::move(s))) {
54 }
56 boxed(const std::nullptr_t) : std::shared_ptr<void>() {
57 }
59 boxed(array_t&& l) : std::shared_ptr<void>(std::make_shared<array_t>(std::move(l))) {
60 }
62 boxed(dict_t&& m) : std::shared_ptr<void>(std::make_shared<dict_t>(std::move(m))) {
63 }
65 template <typename T,
66 typename = typename std::enable_if<!std::is_same<boxed,T>::value>::type>
67 boxed(const T& f,
68 typename std::enable_if<std::is_assignable<std::function<boxed(boxed)>,T>::value>::type* = 0) : std::shared_ptr<void>(std::make_shared<fn_t>(f)) {
69 }
71 template <typename T,
72 typename = typename std::enable_if<!std::is_same<boxed,T>::value>::type>
73 boxed(const T& f,
74 typename std::enable_if<std::is_assignable<std::function<boxed(void)>,T>::value>::type* = 0) : std::shared_ptr<void>(std::make_shared<eff_fn_t>(f)) {
75 }
77 template <typename T,
78 typename = typename std::enable_if<!std::is_same<boxed,T>::value &&
79 std::is_convertible<T,fn_t>::value>::type>
80 auto operator=(const T& right) -> boxed& {
81 if (std::shared_ptr<void>::operator bool()) {
82 auto& f = *static_cast<fn_t*>(get());
83 f = right;
84 } else {
85 reset(new fn_t(right));
86 }
87 return *this;
88 }
90 auto operator()(const boxed& arg) const -> boxed {
91 auto& f = *static_cast<fn_t*>(get());
92 return f(arg);
93 }
95 auto operator()() const -> boxed {
96 auto& f = *static_cast<eff_fn_t*>(get());
97 return f();
98 }
100 auto operator[](const string& key) const -> const boxed& {
101 const auto& dict = *static_cast<const dict_t*>(get());
102 return dict.at(key);
103 }
105 auto operator[](const string& key) -> boxed& {
106 auto& dict = *static_cast<dict_t*>(get());
107 return dict[key];
108 }
110#ifdef NDEBUG
111 auto operator[](const int index) const -> const boxed& {
112 const auto& array = *static_cast<const array_t*>(get());
113 return array[index];
114 }
116 auto operator[](const int index) -> boxed& {
117 auto& array = *static_cast<array_t*>(get());
118 return array[index];
119 }
120#else
121 auto operator[](const int index) const -> const boxed& {
122 const auto& array = *static_cast<const array_t*>(get());
123 return array.at(index);
124 }
126 auto operator[](const int index) -> boxed& {
127 auto& array = *static_cast<array_t*>(get());
128 return array.at(index);
129 }
131#endif // NDEBUG
133 }; // class boxed
135 template <typename T, typename... Args>
136 inline auto box(Args&&... args) -> boxed {
137 return std::make_shared<T>(std::forward<Args>(args)...);
138 }
140 template <typename T>
141 inline auto unbox(const boxed& b) -> const T& {
142 const auto& unboxed = *static_cast<const T*>(b.get());
143 return unboxed;
144 }
146 template <typename T,
147 typename = typename std::enable_if<!std::is_same<T, const boxed&>::value>::type>
148 constexpr auto unbox(const T value) -> T {
149 return value;
150 }
152 template <typename T>
153 inline auto peek(boxed& b) -> T& {
154 auto& unboxed = *static_cast<T*>(b.get());
155 return unboxed;
156 }
158 template <typename T>
159 inline auto copy(const boxed& b) -> boxed {
160 return box<T>(unbox<T>(b));
161 }
163 using fn_t = boxed::fn_t;
164 using eff_fn_t = boxed::eff_fn_t;
165 using dict_t = boxed::dict_t;
166 using array_t = boxed::array_t;
168 constexpr auto undefined = nullptr;
170} // namespace purescript
172#define FOREIGN_BEGIN(NS) namespace NS {\
173 using namespace purescript;\
174 auto _foreign_() -> dict_t&;\
175 static const auto& NS ## _foreign_init = []() {\
176 dict_t& exports = _foreign_();
177#define FOREIGN_END return exports; }(); }
179#endif // purescript_H