git.iko.soy/rowtype-yoga/purescript-native
on golang help sign in
pscpp -> psgo
127af89Andy Arvanitis
app/Main.hs+9−39
@@ -101,65 +101,35 @@ transpile opts baseOutpath jsonFile = do
101 implPath = outpath </> implFileName mn
101 implPath = outpath </> implFileName mn
102 putStrLn interfacePath
102 putStrLn interfacePath
103 createDirectoryIfMissing True outpath
103 createDirectoryIfMissing True outpath
104− B.writeFile interfacePath $ T.encodeUtf8 $ conv interface
104+ B.writeFile interfacePath $ T.encodeUtf8 interface
105 putStrLn implPath
105 putStrLn implPath
106− B.writeFile implPath $ T.encodeUtf8 $ conv (implHeader <> implementation <> implFooter)
106+ B.writeFile implPath $ T.encodeUtf8 (implHeader <> implementation <> implFooter)
107− where
108− conv :: Text -> Text
109− conv
110− | "--ucns" `elem` opts = toUCNs
111− | otherwise = id
112
107
113writeRuntimeFiles :: FilePath -> IO ()
108writeRuntimeFiles :: FilePath -> IO ()
114writeRuntimeFiles baseOutpath = do
109writeRuntimeFiles baseOutpath = do
115 createDirectoryIfMissing True baseOutpath
110 createDirectoryIfMissing True baseOutpath
116− let runtimeHeader = baseOutpath </> "purescript.h"
117− runtimeSource = baseOutpath </> "purescript.cpp"
111+ let runtimeSource = baseOutpath </> "purescript.go"
118− fn = baseOutpath </> "functions.h"
119− dict = baseOutpath </> "dictionary.h"
120− recur = baseOutpath </> "recursion.h"
121− runtimeExists <- doesFileExist runtimeHeader
112+ runtimeExists <- doesFileExist runtimeSource
122 when (not runtimeExists) $ do
113 when (not runtimeExists) $ do
123− B.writeFile runtimeHeader $(embedFile "runtime/purescript.h")
124− B.writeFile runtimeSource $(embedFile "runtime/purescript.cpp")
114+ B.writeFile runtimeSource $(embedFile "runtime/purescript.go")
125− B.writeFile fn $(embedFile "runtime/functions.h")
126− B.writeFile dict $(embedFile "runtime/dictionary.h")
127− B.writeFile recur $(embedFile "runtime/recursion.h")
128
115
129outdir :: FilePath
116outdir :: FilePath
130outdir = "src"
117outdir = "src"
131
118
132interfaceFileName :: String -> FilePath
119interfaceFileName :: String -> FilePath
133−interfaceFileName mn = mn <> ".h"
120+interfaceFileName mn = mn <> ".go"
134
121
135implFileName :: Text -> FilePath
122implFileName :: Text -> FilePath
136−implFileName mn = T.unpack $ mn <> ".cpp"
123+implFileName mn = T.unpack $ mn <> ".go"
137−
138−escape :: Text -> Text
139−escape = T.concatMap go
140− where
141− go :: Char -> Text
142− go c = T.pack $ printf "0x%04x," (ord c)
143−
144−
145−toUCNs :: Text -> Text
146−toUCNs = T.pack . concatMap toUCN . T.unpack
147−
148−toUCN :: Char -> String
149−toUCN c | isAscii c = [c]
150−toUCN c = printf "\\U%08x" $ ord c
151
124
152help :: String
125help :: String
153−help = "Usage: pscpp OPTIONS COREFN-FILES\n\
126+help = "Usage: psgo OPTIONS COREFN-FILES\n\
154− \ PureScript-to-C++ compiler\n\n\
127+ \ PureScript-to-go compiler\n\n\
155 \Available options:\n\
128 \Available options:\n\
156 \ --help Show this help text\n\n\
129 \ --help Show this help text\n\n\
157 \ --makefile Generate a GNU Makefile which can be used for compiling\n\
130 \ --makefile Generate a GNU Makefile which can be used for compiling\n\
158 \ a PureScript program and libraries to a native binary via\n\
131 \ a PureScript program and libraries to a native binary via\n\
159 \ purs corefn output and C++\n\n\
132 \ purs corefn output and C++\n\n\
160− \ --ucns Use UCN encoding of unicode characters in literals and\n\
161− \ strings in generated C++ code (for compilers that do not\n\
162− \ support unicode literals, such as gcc)\n\n\
163 \ --tests Run test cases (under construction)\n\n\
133 \ --tests Run test cases (under construction)\n\n\
164 \See also:\n\
134 \See also:\n\
165 \ purs compile --help\n"
135 \ purs compile --help\n"
package.yaml+8−9
@@ -1,6 +1,6 @@
1−name: pscpp
1+name: psgo
2version: 0.1.0.0
2version: 0.1.0.0
3−github: "andyarvanitis/purescript-cpp"
3+github: "andyarvanitis/purescript-native"
4license: BSD3
4license: BSD3
5author: "Andy Arvanitis"
5author: "Andy Arvanitis"
6maintainer: "example@example.com"
6maintainer: "example@example.com"
@@ -9,8 +9,7 @@ copyright: "2018 Andy Arvanitis"
9extra-source-files:
9extra-source-files:
10- README.md
10- README.md
11- ChangeLog.md
11- ChangeLog.md
12−- runtime/*.h
12+- runtime/*.go
13−- runtime/*.cpp
14
13
15# Metadata used when publishing your package
14# Metadata used when publishing your package
16# synopsis: Short description of your package
15# synopsis: Short description of your package
@@ -19,7 +18,7 @@ extra-source-files:
19# To avoid duplicated efforts in documentation and dealing with the
18# To avoid duplicated efforts in documentation and dealing with the
20# complications of embedding Haddock markup inside cabal files, it is
19# complications of embedding Haddock markup inside cabal files, it is
21# common to point users to the README.md file.
20# common to point users to the README.md file.
22−description: Please see the README on Github at <https://github.com/andyarvanitis/purescript-cpp#readme>
21+description: Please see the README on Github at <https://github.com/andyarvanitis/purescript-native#readme>
23
22
24dependencies:
23dependencies:
25- base >= 4.7 && < 5
24- base >= 4.7 && < 5
@@ -62,7 +61,7 @@ library:
62 - ViewPatterns
61 - ViewPatterns
63
62
64executables:
63executables:
65− pscpp:
64+ psgo:
66 main: Main.hs
65 main: Main.hs
67 source-dirs: app
66 source-dirs: app
68 ghc-options:
67 ghc-options:
@@ -70,10 +69,10 @@ executables:
70 - -rtsopts
69 - -rtsopts
71 - -with-rtsopts=-N
70 - -with-rtsopts=-N
72 dependencies:
71 dependencies:
73− - pscpp
72+ - psgo
74
73
75tests:
74tests:
76− pscpp-test:
75+ psgo-test:
77 main: Spec.hs
76 main: Spec.hs
78 source-dirs: test
77 source-dirs: test
79 ghc-options:
78 ghc-options:
@@ -81,4 +80,4 @@ tests:
81 - -rtsopts
80 - -rtsopts
82 - -with-rtsopts=-N
81 - -with-rtsopts=-N
83 dependencies:
82 dependencies:
84− - pscpp
83+ - psgo
runtime/dictionary.hdeleted−91
@@ -1,91 +0,0 @@
1−///////////////////////////////////////////////////////////////////////////////
2−//
3−// Module : dictionary.h
4−// Copyright : (c) Andy Arvanitis 2018
5−// License : BSD
6−//
7−// Maintainer : Andy Arvanitis
8−// Stability : experimental
9−// Portability :
10−//
11−// A simple dictionary optimized for this runtime's particular use –
12−// *not* intended for general use or as a replacement for containers
13−// such as std::map or std::unordered_map. It relies on the following
14−// assumptions:
15−//
16−// 1) Keys are C-type string literals. No copying or (memory management)
17−// of the keys occurs
18−// 2) The number of elements in the container is generally small – say,
19−// under 20. There is no sorting and a linear search is used to
20−// locate elements
21−//
22−///////////////////////////////////////////////////////////////////////////////
23−//
24−#ifndef purescript_dictionary_H
25−#define purescript_dictionary_H
26−
27−#include <cstring>
28−#include <vector>
29−#include <utility>
30−#if !defined(NDEBUG)
31−#include <string>
32−#endif
33−
34−namespace purescript {
35− namespace _template_ {
36−
37− template <typename T>
38− class dict_t : public std::vector<std::pair<const char *, T>> {
39−
40− static auto null() -> const T& {
41− static const T value;
42− return value;
43− }
44−
45− public:
46− using std::vector<std::pair<const char *, T>>::vector;
47−
48− auto operator[](const char key[]) const -> const T& {
49− for (auto it = this->cbegin(), end=this->cend(); it != end; it++) {
50− const auto& elem_key = it->first;
51− if (elem_key == key || !std::strcmp(elem_key, key)) {
52− return it->second;
53− }
54− }
55−#if !defined(NDEBUG) && !defined(PURESCRIPT_DISABLE_EXCEPTIONS)
56− throw std::runtime_error("dictionary key \"" + std::string(key) + "\" not found");
57−#endif
58− return null();
59− }
60−
61− auto at(const char key[]) const -> const T& {
62− return (*this)[key];
63− }
64−
65− auto operator[](const char key[]) -> T& {
66− const auto end = this->end();
67− for (auto it = this->begin(); it != end; it++) {
68− const auto& elem_key = it->first;
69− if (elem_key == key || !std::strcmp(elem_key, key)) {
70− return it->second;
71− }
72− }
73− return this->emplace(end, key, T())->second;
74− }
75−
76− auto contains(const char key[]) const -> bool {
77− for (auto it = this->cbegin(), end=this->cend(); it != end; it++) {
78− const auto& elem_key = it->first;
79− if (elem_key == key || !std::strcmp(elem_key, key)) {
80− return true;
81− }
82− }
83− return false;
84− }
85−
86− };
87−
88− } // namespace _template_
89−} // namespace purescript
90−
91−#endif // purescript_dictionary_H
runtime/functions.hdeleted−58
@@ -1,58 +0,0 @@
1−///////////////////////////////////////////////////////////////////////////////
2−//
3−// Module : functions.h
4−// Copyright : (c) Andy Arvanitis 2019
5−// License : BSD
6−//
7−// Maintainer : Andy Arvanitis
8−// Stability : experimental
9−// Portability :
10−//
11−// Runtime function types (for regular functions and lambdas)
12−//
13−///////////////////////////////////////////////////////////////////////////////
14−//
15−#ifndef purescript_functions_H
16−#define purescript_functions_H
17−
18−namespace purescript {
19− namespace _template_ {
20−
21− template <typename T>
22− class fn_t {
23− public:
24− virtual ~fn_t() {}
25− virtual auto operator ()(const T&) const -> T = 0;
26− };
27−
28− template <typename T, typename U>
29− class fn_T : public fn_t<T> {
30− U fn;
31− public:
32− fn_T(U&& f) noexcept : fn(std::move(f)) {}
33− auto operator ()(const T& arg) const -> T override {
34− return fn(arg);
35− }
36− };
37−
38− template <typename T>
39− class eff_fn_t {
40− public:
41− virtual ~eff_fn_t() {}
42− virtual auto operator ()() const -> T = 0;
43− };
44−
45− template <typename T, typename U>
46− class eff_fn_T : public eff_fn_t<T> {
47− U fn;
48− public:
49− eff_fn_T(U&& f) noexcept : fn(std::move(f)) {}
50− auto operator ()() const -> T override {
51− return fn();
52− }
53− };
54−
55− } // namespace _template_
56−} // namespace purescript
57−
58−#endif // purescript_functions_H
runtime/purescript.cppdeleted−59
@@ -1,59 +0,0 @@
1−///////////////////////////////////////////////////////////////////////////////
2−//
3−// Module : purescript.cpp
4−// Copyright : (c) Andy Arvanitis 2019
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−#include "purescript.h"
16−
17−namespace purescript {
18−
19−template class _template_::fn_t<boxed>;
20−template class _template_::eff_fn_t<boxed>;
21−template class _template_::dict_t<boxed>;
22−template class _template_::weak<boxed>;
23−template class _template_::recur<boxed>;
24−
25−boxed::boxed(const long n) : _int_(static_cast<int>(n)) {
26−#if !defined(NDEBUG) && !defined(PURESCRIPT_DISABLE_EXCEPTIONS)
27− if (n < std::numeric_limits<int>::min() || n > std::numeric_limits<int>::max()) {
28− throw std::runtime_error("integer out of range");
29− }
30−#endif
31−}
32−
33−boxed::boxed(const unsigned long n) : _int_(static_cast<int>(n)) {
34−#if !defined(NDEBUG) && !defined(PURESCRIPT_DISABLE_EXCEPTIONS)
35− if (n > std::numeric_limits<int>::max()) {
36− throw std::runtime_error("integer out of range");
37− }
38−#endif
39−}
40−
41−auto boxed::operator[](const int index) const -> const boxed& {
42−#if !defined(NDEBUG)
43− return static_cast<const array_t*>(shared.get())->at(index);
44−#else
45− return (*static_cast<const array_t*>(shared.get()))[index];
46−#endif
47−}
48−
49−auto boxed::operator[](const int index) -> boxed& {
50−#if !defined(NDEBUG)
51− return static_cast<array_t*>(shared.get())->at(index);
52−#else
53− return (*static_cast<array_t*>(shared.get()))[index];
54−#endif
55−}
56−
57−const boxed undefined;
58−
59−} // namespace purescript
runtime/purescript.gonew file+22
@@ -0,0 +1,22 @@
1+package purescript
2+
3+//go:generate purs --version
4+
5+type Any = interface{}
6+
7+type Fn = func(Any) Any
8+type EffFn = func() Any
9+
10+func Apply(f Any, args ...Any) Any {
11+ result := f
12+ for _, arg := range args {
13+ fn, _ := result.(Fn)
14+ result = fn(arg)
15+ }
16+ return result
17+}
18+
19+func Get(dict Any, key string) Any {
20+ d, _ := dict.(func(string) Any)
21+ return d(key)
22+}
runtime/purescript.hdeleted−244
@@ -1,244 +0,0 @@
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
17−
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"
31−
32−namespace purescript {
33−
34− using std::string;
35−
36− class boxed {
37− public:
38− std::shared_ptr<void> shared;
39− union {
40− int _int_;
41− double _double_;
42− bool _bool_;
43− };
44−
45− public:
46− using fn_t = _template_::fn_t<boxed>;
47− using eff_fn_t = _template_::eff_fn_t<boxed>;
48−
49− using dict_t = _template_::dict_t<boxed>;
50− using array_t = std::vector<boxed>;
51−
52− using weak = _template_::weak<boxed>;
53− using recur = _template_::recur<boxed>;
54−
55− private:
56− template <typename T>
57− using fn_T = _template_::fn_T<boxed, T>;
58−
59− template <typename T>
60− using eff_fn_T = _template_::eff_fn_T<boxed, T>;
61−
62− public:
63− boxed() noexcept : shared() {}
64− boxed(const std::nullptr_t) noexcept : shared() {}
65−
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()) {}
69−
70− template <typename T>
71− boxed(std::shared_ptr<T>&& other) noexcept : shared(std::move(other)) {}
72−
73− template <typename T>
74− boxed(const std::shared_ptr<T>& other) : shared(other) {}
75−
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)) {}
88−
89− template <typename T,
90− typename U = typename std::remove_reference<T>::type,
91− typename V = typename std::remove_const<U>::type,
92− typename = typename std::enable_if<!std::is_same<boxed,V>::value && !std::is_same<recur,V>::value>::type>
93− boxed(T&& f,
94− typename std::enable_if<std::is_same<decltype(std::declval<U>()(std::declval<boxed>())), boxed>::value>::type* = 0)
95− : shared(std::shared_ptr<fn_t>(std::make_shared<fn_T<T>>(std::forward<T>(f)))) {
96− }
97−
98− template <typename T,
99− typename U = typename std::remove_reference<T>::type,
100− typename V = typename std::remove_const<U>::type,
101− typename = typename std::enable_if<!std::is_same<boxed,V>::value && !std::is_same<recur,V>::value>::type>
102− boxed(T&& f,
103− typename std::enable_if<std::is_same<decltype(std::declval<U>()()), boxed>::value>::type* = 0)
104− : shared(std::shared_ptr<eff_fn_t>(std::make_shared<eff_fn_T<T>>(std::forward<T>(f)))) {
105− }
106−
107− auto get() const noexcept -> void * {
108− return shared.get();
109− }
110−
111− auto operator()(const boxed& arg) const -> boxed {
112− return (*static_cast<fn_t*>(shared.get()))(arg);
113− }
114−
115− auto operator()() const -> boxed {
116− return (*static_cast<eff_fn_t*>(shared.get()))();
117− }
118−
119− auto operator[](const char key[]) const -> const boxed& {
120− return (*static_cast<const dict_t*>(shared.get()))[key];
121− }
122−
123− auto operator[](const char key[]) -> boxed& {
124− return (*static_cast<dict_t*>(shared.get()))[key];
125− }
126−
127− auto operator[](const int index) const -> const boxed&;
128− auto operator[](const int index) -> boxed&;
129−
130− }; // class boxed
131−
132− extern template class _template_::fn_t<boxed>;
133− extern template class _template_::eff_fn_t<boxed>;
134− extern template class _template_::dict_t<boxed>;
135− extern template class _template_::weak<boxed>;
136− extern template class _template_::recur<boxed>;
137−
138− extern const boxed undefined;
139−
140− using fn_t = boxed::fn_t;
141− using eff_fn_t = boxed::eff_fn_t;
142− using dict_t = boxed::dict_t;
143− using array_t = boxed::array_t;
144−
145− template <typename T, typename... Args,
146− typename = typename std::enable_if<!std::is_same<T, int>::value &&
147− !std::is_same<T, double>::value &&
148− !std::is_same<T, bool>::value
149− >::type>
150− inline auto box(Args&&... args) -> boxed {
151− return std::make_shared<T>(std::forward<Args>(args)...);
152− }
153−
154− template <typename T,
155− typename std::enable_if<std::is_same<T, int>::value, T>::type* = nullptr>
156− inline auto box(T arg) noexcept -> boxed {
157− return boxed(arg);
158− }
159−
160− template <typename T,
161− typename std::enable_if<std::is_same<T, double>::value, T>::type* = nullptr>
162− inline auto box(T arg) noexcept -> boxed {
163− return boxed(arg);
164− }
165−
166− template <typename T,
167− typename std::enable_if<std::is_same<T, bool>::value, T>::type* = nullptr>
168− inline auto box(T arg) noexcept -> boxed {
169− return boxed(arg);
170− }
171−
172− template <typename T,
173− typename = typename std::enable_if<!std::is_same<T, int>::value &&
174− !std::is_same<T, double>::value &&
175− !std::is_same<T, bool>::value
176− >::type>
177− constexpr auto unbox(const boxed& b) -> const T& {
178− return *static_cast<const T*>(b.get());
179− }
180−
181− template <typename T,
182− typename std::enable_if<std::is_same<T, int>::value, T>::type* = nullptr>
183− constexpr auto unbox(const boxed& b) noexcept -> T {
184− return b._int_;
185− }
186−
187− template <typename T,
188− typename std::enable_if<std::is_same<T, double>::value, T>::type* = nullptr>
189− constexpr auto unbox(const boxed& b) noexcept -> T {
190− return b._double_;
191− }
192−
193− template <typename T,
194− typename std::enable_if<std::is_same<T, bool>::value, T>::type* = nullptr>
195− constexpr auto unbox(const boxed& b) noexcept -> T {
196− return b._bool_;
197− }
198−
199− template <typename T,
200− typename = typename std::enable_if<!std::is_same<T, int>::value &&
201− !std::is_same<T, double>::value &&
202− !std::is_same<T, bool>::value
203− >::type>
204− constexpr auto unbox(boxed& b) -> T& {
205− return *static_cast<T*>(b.get());
206− }
207−
208− template <typename T>
209− constexpr auto unbox(const T value) noexcept -> T {
210− return value;
211− }
212−
213− template <typename T,
214− typename = typename std::enable_if<std::is_same<T, int>::value>::type>
215− constexpr auto unbox(const std::size_t value) noexcept -> long long {
216− return value;
217− }
218−
219− inline auto array_length(const boxed& a) -> boxed::array_t::size_type {
220− return unbox<boxed::array_t>(a).size();
221− }
222−
223−} // namespace purescript
224−
225−#if !defined(PURESCRIPT_DISABLE_EXCEPTIONS)
226−#define THROW_(s) throw std::runtime_error(s)
227−#else
228−#define THROW_(_) return undefined
229−#endif
230−
231−#define DEFINE_FOREIGN_DICTIONARY_AND_ACCESSOR() \
232− inline auto foreign() -> dict_t& {\
233− static dict_t _;\
234− return _;\
235− }
236−
237−#define FOREIGN_BEGIN(NS) namespace NS {\
238− using namespace purescript;\
239− DEFINE_FOREIGN_DICTIONARY_AND_ACCESSOR()\
240− static const auto data = ([]() -> char {\
241− dict_t& exports = foreign();
242−#define FOREIGN_END return 0; }()); }
243−
244−#endif // purescript_H
runtime/recursion.hdeleted−92
@@ -1,92 +0,0 @@
1−///////////////////////////////////////////////////////////////////////////////
2−//
3−// Module : recursion.h
4−// Copyright : (c) Andy Arvanitis 2019
5−// License : BSD
6−//
7−// Maintainer : Andy Arvanitis
8−// Stability : experimental
9−// Portability :
10−//
11−// Runtime types to support recursion
12−//
13−///////////////////////////////////////////////////////////////////////////////
14−//
15−#ifndef purescript_recursion_H
16−#define purescript_recursion_H
17−
18−#include <memory>
19−
20−namespace purescript {
21−
22− namespace _template_ {
23−
24− template <typename T>
25− class weak {
26− std::weak_ptr<void> wptr;
27−
28− public:
29− weak() = delete;
30− weak(T& b) : wptr(b.shared) {}
31−
32− auto shared() const -> std::shared_ptr<void> {
33−#if defined(NDEBUG)
34− return wptr.lock();
35−#else
36− return static_cast<std::shared_ptr<void>>(wptr);
37−#endif
38− }
39−
40− }; // class weak
41−
42− template <typename T>
43− class recur {
44− std::shared_ptr<T> sptr;
45− std::shared_ptr<typename T::weak> wptr;
46−
47− public:
48− recur() : sptr(std::make_shared<T>())
49− , wptr(std::make_shared<typename T::weak>(*sptr)) {}
50−
51− auto shared() const -> std::shared_ptr<void> {
52− return sptr->shared;
53− }
54−
55− auto operator()() const -> T {
56− return (*sptr)();
57− }
58−
59− auto operator()(const T& arg) const -> T {
60− return (*sptr)(arg);
61− }
62−
63− template <typename U>
64− auto operator=(U&& right) -> recur& {
65− *sptr = std::forward<U>(right);
66− *wptr = *sptr;
67− return *this;
68− }
69−
70− class weak {
71− std::shared_ptr<typename T::weak> wptr;
72− public:
73− weak(const recur& r) : wptr(r.wptr) {}
74−
75− auto shared() const -> std::shared_ptr<void> {
76− return wptr->shared();
77− }
78−
79− auto operator()() const -> T {
80− return static_cast<T>(*wptr)();
81− }
82−
83− auto operator()(const T& arg) const -> T {
84− return static_cast<T>(*wptr)(arg);
85− }
86− }; // class recur::weak
87− }; // class recur
88−
89− } // namespace _template_
90−} // namespace purescript
91−
92−#endif // purescript_recursion_H