git.iko.soy/rowtype-yoga/purescript-native
on 080f35f help sign in
140 lines 4.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 using fn = std::function<boxed(const boxed&)>;
33 using eff_fn = std::function<boxed(void)>;
35 public:
36 using std::shared_ptr<void>::shared_ptr;
38 boxed(const int n) : std::shared_ptr<void>(std::make_shared<int>(n)) {
39 }
41 boxed(const double n) : std::shared_ptr<void>(std::make_shared<double>(n)) {
42 }
44 boxed(const bool b) : std::shared_ptr<void>(std::make_shared<bool>(b)) {
45 }
47 boxed(const char s[]) : std::shared_ptr<void>(std::make_shared<string>(s)) {
48 }
50 boxed(string&& s) : std::shared_ptr<void>(std::make_shared<string>(std::move(s))) {
51 }
53 boxed(const std::nullptr_t) : std::shared_ptr<void>() {
54 }
56 boxed(std::initializer_list<boxed> l) : std::shared_ptr<void>(std::make_shared<std::deque<boxed>>(l)) {
57 }
59 boxed(std::initializer_list<std::pair<const string, boxed>> m) : std::shared_ptr<void>(std::make_shared<std::map<string, boxed>>(m)) {
60 }
62 template <typename T,
63 typename = typename std::enable_if<!std::is_same<boxed,T>::value>::type>
64 boxed(const T& f,
65 typename std::enable_if<std::is_assignable<std::function<boxed(boxed)>,T>::value>::type* = 0) : std::shared_ptr<void>(std::make_shared<fn>(f)) {
66 }
68 template <typename T,
69 typename = typename std::enable_if<!std::is_same<boxed,T>::value>::type>
70 boxed(const T& f,
71 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)) {
72 }
74 template <typename T,
75 typename = typename std::enable_if<!std::is_same<boxed,T>::value &&
76 std::is_convertible<T,fn>::value>::type>
77 auto operator=(const T& right) -> boxed& {
78 if (std::shared_ptr<void>::operator bool()) {
79 auto& f = *static_cast<fn*>(get());
80 f = right;
81 } else {
82 reset(new fn(right));
83 }
84 return *this;
85 }
87 auto operator()(const boxed& arg) const -> boxed {
88 auto& f = *static_cast<fn*>(get());
89 return f(arg);
90 }
92 auto operator()() const -> boxed {
93 auto& f = *static_cast<eff_fn*>(get());
94 return f();
95 }
97 auto operator[](const char key[]) const -> boxed {
98 const auto& dict = *static_cast<const std::map<const string, boxed>*>(get());
99 return dict.at(key);
100 }
102 };
104 template <typename T, typename... Args>
105 inline auto box(Args&&... args) -> boxed {
106 return std::make_shared<T>(std::forward<Args>(args)...);
107 }
109 template <typename T>
110 inline auto unbox(const boxed& b) -> const T& {
111 const auto& unboxed = *static_cast<const T*>(b.get());
112 return unboxed;
113 }
115 template <typename T>
116 inline auto peek(boxed& b) -> T& {
117 auto& unboxed = *static_cast<T*>(b.get());
118 return unboxed;
119 }
121 template <typename T>
122 inline auto copy(const boxed& b) -> boxed {
123 return box<T>(unbox<T>(b));
124 }
126 using fn_t = std::function<boxed(const boxed&)>;
127 using dict_t = std::map<const string, boxed>;
128 using array_t = std::deque<boxed>;
130 using as_array = std::initializer_list<boxed>;
131 using as_dict = std::initializer_list<std::pair<const string, boxed>>;
133 constexpr auto undefined = nullptr;
135} // namespace purescript
137#define FOREIGN_EXPORTS(NS) namespace NS { using namespace purescript; auto _foreign_() -> dict_t&; static const auto& NS ## _foreign_init = []() { dict_t& foreign = _foreign_();
138#define END_FOREIGN_EXPORTS return foreign; }(); }
140#endif // purescript_H