git.iko.soy/rowtype-yoga/purescript-native
on golang help sign in
Revert "Revert "C++: revamp arrays""
41678bcAndy Arvanitis
pcc/include/purescript.cc+15−8
@@ -27,6 +27,7 @@ namespace PureScript {
27 case Type::String: new (&s) shared<std::string>(src.s); break; \
27 case Type::String: new (&s) shared<std::string>(src.s); break; \
28 case Type::Map: new (&m) shared<map>(src.m); break; \
28 case Type::Map: new (&m) shared<map>(src.m); break; \
29 case Type::Vector: new (&v) shared<vector>(src.v); break; \
29 case Type::Vector: new (&v) shared<vector>(src.v); break; \
30+ case Type::Array: new (&a) shared<array>(src.a); break; \
30 case Type::Function: f = src.f; break; \
31 case Type::Function: f = src.f; break; \
31 case Type::Closure: new (&l) shared<closure>(src.l); break; \
32 case Type::Closure: new (&l) shared<closure>(src.l); break; \
32 case Type::EffFunction: new (&e) shared<eff_fn>(src.e); break; \
33 case Type::EffFunction: new (&e) shared<eff_fn>(src.e); break; \
@@ -46,6 +47,7 @@ namespace PureScript {
46 case Type::String: new (&s) shared<std::string>(std::move(src.s)); break; \
47 case Type::String: new (&s) shared<std::string>(std::move(src.s)); break; \
47 case Type::Map: new (&m) shared<map>(std::move(src.m)); break; \
48 case Type::Map: new (&m) shared<map>(std::move(src.m)); break; \
48 case Type::Vector: new (&v) shared<vector>(std::move(src.v)); break; \
49 case Type::Vector: new (&v) shared<vector>(std::move(src.v)); break; \
50+ case Type::Array: new (&a) shared<array>(std::move(src.a)); break; \
49 case Type::Function: f = src.f; break; \
51 case Type::Function: f = src.f; break; \
50 case Type::Closure: new (&l) shared<closure>(std::move(src.l)); break; \
52 case Type::Closure: new (&l) shared<closure>(std::move(src.l)); break; \
51 case Type::EffFunction: new (&e) shared<eff_fn>(std::move(src.e)); break; \
53 case Type::EffFunction: new (&e) shared<eff_fn>(std::move(src.e)); break; \
@@ -92,6 +94,7 @@ any::~any() {
92 case Type::String: s.~shared<std::string>(); break;
94 case Type::String: s.~shared<std::string>(); break;
93 case Type::Map: m.~shared<map>(); break;
95 case Type::Map: m.~shared<map>(); break;
94 case Type::Vector: v.~shared<vector>(); break;
96 case Type::Vector: v.~shared<vector>(); break;
97+ case Type::Array: a.~shared<array>(); break;
95 case Type::Function: ; break;
98 case Type::Function: ; break;
96 case Type::Closure: l.~shared<closure>(); break;
99 case Type::Closure: l.~shared<closure>(); break;
97 case Type::EffFunction: e.~shared<eff_fn>(); break;
100 case Type::EffFunction: e.~shared<eff_fn>(); break;
@@ -149,10 +152,10 @@ auto any::cast() const -> typename std::enable_if<std::is_same<T, map>::value, c
149template auto any::cast<any::map>() const -> const map&;
152template auto any::cast<any::map>() const -> const map&;
150
153
151template <typename T>
154template <typename T>
152−auto any::cast() const -> typename std::enable_if<std::is_same<T, vector>::value, const T&>::type {
155+auto any::cast() const -> typename std::enable_if<std::is_same<T, array>::value, const T&>::type {
153− RETURN_VALUE(Type::Vector, v, *)
156+ RETURN_VALUE(Type::Array, a, *)
154}
157}
155−template auto any::cast<any::vector>() const -> const vector&;
158+template auto any::cast<any::array>() const -> const array&;
156
159
157auto any::operator()(const any& arg) const -> any {
160auto any::operator()(const any& arg) const -> any {
158 const any& variant = unthunkVariant(*this);
161 const any& variant = unthunkVariant(*this);
@@ -198,6 +201,10 @@ any::operator const vector&() const {
198 return cast<vector>();
201 return cast<vector>();
199}
202}
200
203
204+any::operator const array&() const {
205+ return cast<array>();
206+}
207+
201auto any::extractPointer() const -> void* {
208auto any::extractPointer() const -> void* {
202 RETURN_VALUE(Type::Pointer, p.get(),)
209 RETURN_VALUE(Type::Pointer, p.get(),)
203}
210}
@@ -228,16 +235,16 @@ auto any::operator[](const char rhs[]) const -> const any& {
228 throw runtime_error("map key not found");
235 throw runtime_error("map key not found");
229}
236}
230
237
231−auto any::operator[](const vector::size_type rhs) const -> const any& {
238+auto any::operator[](const size_t rhs) const -> const any& {
232 const any& variant = unthunkVariant(*this);
239 const any& variant = unthunkVariant(*this);
233− assert(variant.type == Type::Vector);
240+ assert(variant.type == Type::Array);
234− return (*variant.v)[rhs];
241+ return (*variant.a)[rhs];
235}
242}
236
243
237auto any::operator[](const any& rhs) const -> const any& {
244auto any::operator[](const any& rhs) const -> const any& {
238 const any& variant = unthunkVariant(*this);
245 const any& variant = unthunkVariant(*this);
239− assert(variant.type == Type::Vector);
246+ assert(variant.type == Type::Array);
240− return (*variant.v)[rhs.cast<long>()];
247+ return (*variant.a)[rhs.cast<long>()];
241}
248}
242
249
243auto any::contains(const char key[]) const -> bool {
250auto any::contains(const char key[]) const -> bool {
pcc/include/purescript.hh+23−4
@@ -29,6 +29,7 @@
29#include <functional>
29#include <functional>
30#include <string>
30#include <string>
31#include <vector>
31#include <vector>
32+#include <deque>
32#include <utility>
33#include <utility>
33#include <stdexcept>
34#include <stdexcept>
34
35
@@ -56,7 +57,7 @@ public:
56};
57};
57
58
58const bool undefined = false;
59const bool undefined = false;
59−const std::vector<int>::size_type kDataCtor = 0;
60+const size_t kDataCtor = 0;
60
61
61// A variant data class designed to provide some features of dynamic typing.
62// A variant data class designed to provide some features of dynamic typing.
62//
63//
@@ -73,6 +74,7 @@ class any {
73 String,
74 String,
74 Map,
75 Map,
75 Vector,
76 Vector,
77+ Array,
76 Function,
78 Function,
77 Closure,
79 Closure,
78 EffFunction,
80 EffFunction,
@@ -80,17 +82,22 @@ class any {
80 Pointer
82 Pointer
81 };
83 };
82
84
85+ private:
83 mutable Type type = Type::Unknown;
86 mutable Type type = Type::Unknown;
87+ using vector = std::vector<any>;
84
88
89+ public:
85 struct as_thunk {
90 struct as_thunk {
86 };
91 };
87 static constexpr as_thunk unthunk = as_thunk{};
92 static constexpr as_thunk unthunk = as_thunk{};
88
93
89 using map = std::vector<std::pair<const char * const, const any>>;
94 using map = std::vector<std::pair<const char * const, const any>>;
90− using vector = std::vector<any>;
95+ using data = vector;
96+ using array = std::deque<any>;
91 using fn = auto (*)(const any&) -> any;
97 using fn = auto (*)(const any&) -> any;
92 using thunk = auto (*)(const as_thunk) -> const any&;
98 using thunk = auto (*)(const as_thunk) -> const any&;
93
99
100+ private:
94 class closure {
101 class closure {
95 public:
102 public:
96 virtual auto operator()(const any&) const -> any = 0;
103 virtual auto operator()(const any&) const -> any = 0;
@@ -121,6 +128,7 @@ class any {
121 }
128 }
122 };
129 };
123
130
131+ public:
124 template <typename T>
132 template <typename T>
125 using shared = std::shared_ptr<T>;
133 using shared = std::shared_ptr<T>;
126
134
@@ -139,6 +147,7 @@ class any {
139 mutable shared<std::string> s;
147 mutable shared<std::string> s;
140 mutable shared<map> m;
148 mutable shared<map> m;
141 mutable shared<vector> v;
149 mutable shared<vector> v;
150+ mutable shared<array> a;
142 mutable fn f;
151 mutable fn f;
143 mutable shared<closure> l;
152 mutable shared<closure> l;
144 mutable shared<eff_fn> e;
153 mutable shared<eff_fn> e;
@@ -173,6 +182,9 @@ class any {
173 any(const vector& val) : type(Type::Vector), v(make_shared<vector>(val)) {}
182 any(const vector& val) : type(Type::Vector), v(make_shared<vector>(val)) {}
174 any(vector&& val) noexcept : type(Type::Vector), v(make_shared<vector>(std::move(val))) {}
183 any(vector&& val) noexcept : type(Type::Vector), v(make_shared<vector>(std::move(val))) {}
175
184
185+ any(const array& val) : type(Type::Array), a(make_shared<array>(val)) {}
186+ any(array&& val) noexcept : type(Type::Array), a(make_shared<array>(std::move(val))) {}
187+
176 template <typename T>
188 template <typename T>
177 any(const T& val, typename std::enable_if<std::is_convertible<T,fn>::value>::type* = 0)
189 any(const T& val, typename std::enable_if<std::is_convertible<T,fn>::value>::type* = 0)
178 : type(Type::Function), f(val) {}
190 : type(Type::Function), f(val) {}
@@ -228,8 +240,14 @@ class any {
228 template <typename T>
240 template <typename T>
229 auto cast() const -> typename std::enable_if<std::is_same<T, map>::value, const T&>::type;
241 auto cast() const -> typename std::enable_if<std::is_same<T, map>::value, const T&>::type;
230
242
243+ // These cannot be thunked
244+ template <typename T>
245+ inline auto cast() const -> typename std::enable_if<std::is_same<T, vector>::value, const T&>::type {
246+ return *v;
247+ }
248+
231 template <typename T>
249 template <typename T>
232− auto cast() const -> typename std::enable_if<std::is_same<T, vector>::value, const T&>::type;
250+ auto cast() const -> typename std::enable_if<std::is_same<T, array>::value, const T&>::type;
233
251
234 template <typename T>
252 template <typename T>
235 auto cast() const -> typename std::enable_if<std::is_assignable<shared<void>,T>::value, typename T::element_type*>::type {
253 auto cast() const -> typename std::enable_if<std::is_assignable<shared<void>,T>::value, typename T::element_type*>::type {
@@ -249,9 +267,10 @@ class any {
249 operator string() const;
267 operator string() const;
250 operator const map&() const;
268 operator const map&() const;
251 operator const vector&() const;
269 operator const vector&() const;
270+ operator const array&() const;
252
271
253 auto operator[](const char[]) const -> const any&;
272 auto operator[](const char[]) const -> const any&;
254− auto operator[](const vector::size_type) const -> const any&;
273+ auto operator[](const size_t) const -> const any&;
255 auto operator[](const any&) const -> const any&;
274 auto operator[](const any&) const -> const any&;
256
275
257 auto contains(const char[]) const -> bool;
276 auto contains(const char[]) const -> bool;
src/Language/PureScript/CodeGen/Cpp.hs+4−4
@@ -135,7 +135,7 @@ moduleToCpp env (Module _ mn imps _ foreigns decls) = do
135 CppFunction (identToCpp ident)
135 CppFunction (identToCpp ident)
136 [] (Just $ CppAny [])
136 [] (Just $ CppAny [])
137 [CppInline]
137 [CppInline]
138− (CppBlock [CppReturn (CppArrayLiteral [CppStringLiteral (identToCpp ident)])])
138+ (CppBlock [CppReturn (CppDataLiteral [CppStringLiteral (identToCpp ident)])])
139
139
140 declToCpp _ ident (Constructor _ _ (ProperName _) fields) = return . CppNamespace [] $
140 declToCpp _ ident (Constructor _ _ (ProperName _) fields) = return . CppNamespace [] $
141 [ CppFunction ('$' : identToCpp ident) (farg <$> fields')
141 [ CppFunction ('$' : identToCpp ident) (farg <$> fields')
@@ -159,7 +159,7 @@ moduleToCpp env (Module _ mn imps _ foreigns decls) = do
159 (Just $ CppAny [])
159 (Just $ CppAny [])
160 (CppBlock $ fieldLambdas fs')]
160 (CppBlock $ fieldLambdas fs')]
161 | otherwise = fullyConstructed
161 | otherwise = fullyConstructed
162− fullyConstructed = [CppReturn (CppArrayLiteral (CppStringLiteral name : (CppVar <$> fields')))]
162+ fullyConstructed = [CppReturn (CppDataLiteral (CppStringLiteral name : (CppVar <$> fields')))]
163
163
164 declToCpp _ ident val = do
164 declToCpp _ ident val = do
165 val' <- valueToCpp val
165 val' <- valueToCpp val
@@ -421,7 +421,7 @@ moduleToCpp env (Module _ mn imps _ foreigns decls) = do
421 return $ case ctorType of
421 return $ case ctorType of
422 ProductType -> cpps
422 ProductType -> cpps
423 SumType ->
423 SumType ->
424− [ CppIfElse (CppBinary Equal (CppIndexer (CppVar ctorKey) (CppVar varName))
424+ [ CppIfElse (CppBinary Equal (CppIndexer (CppVar ctorKey) (CppCast dataType $ CppVar varName))
425 (CppStringLiteral ctor))
425 (CppStringLiteral ctor))
426 (CppBlock cpps)
426 (CppBlock cpps)
427 Nothing ]
427 Nothing ]
@@ -434,7 +434,7 @@ moduleToCpp env (Module _ mn imps _ foreigns decls) = do
434 cpps <- binderToCpp argVar done'' binder
434 cpps <- binderToCpp argVar done'' binder
435 return (CppVariableIntroduction (argVar, Nothing)
435 return (CppVariableIntroduction (argVar, Nothing)
436 []
436 []
437− (Just (CppIndexer (fieldToIndex field) (CppVar varName)))
437+ (Just (CppIndexer (fieldToIndex field) (CppCast dataType $ CppVar varName)))
438 : cpps)
438 : cpps)
439 fieldToIndex :: Ident -> Cpp
439 fieldToIndex :: Ident -> Cpp
440 fieldToIndex = CppNumericLiteral . Left . (+1) . read . dropWhile isLetter . runIdent
440 fieldToIndex = CppNumericLiteral . Left . (+1) . read . dropWhile isLetter . runIdent
src/Language/PureScript/CodeGen/Cpp/AST.hs+7
@@ -170,6 +170,10 @@ data Cpp
170 --
170 --
171 | CppArrayLiteral [Cpp]
171 | CppArrayLiteral [Cpp]
172 -- |
172 -- |
173+ -- A data literal
174+ --
175+ | CppDataLiteral [Cpp]
176+ -- |
173 -- An array indexer expression
177 -- An array indexer expression
174 --
178 --
175 | CppIndexer Cpp Cpp
179 | CppIndexer Cpp Cpp
@@ -282,6 +286,7 @@ everywhereOnCpp f = go
282 go (CppUnary op j) = f (CppUnary op (go j))
286 go (CppUnary op j) = f (CppUnary op (go j))
283 go (CppBinary op j1 j2) = f (CppBinary op (go j1) (go j2))
287 go (CppBinary op j1 j2) = f (CppBinary op (go j1) (go j2))
284 go (CppArrayLiteral cpp) = f (CppArrayLiteral (map go cpp))
288 go (CppArrayLiteral cpp) = f (CppArrayLiteral (map go cpp))
289+ go (CppDataLiteral cpp) = f (CppDataLiteral (map go cpp))
285 go (CppIndexer j1 j2) = f (CppIndexer (go j1) (go j2))
290 go (CppIndexer j1 j2) = f (CppIndexer (go j1) (go j2))
286 go (CppObjectLiteral cpp) = f (CppObjectLiteral (map (fmap go) cpp))
291 go (CppObjectLiteral cpp) = f (CppObjectLiteral (map (fmap go) cpp))
287 go (CppAccessor prop j) = f (CppAccessor (go prop) (go j))
292 go (CppAccessor prop j) = f (CppAccessor (go prop) (go j))
@@ -311,6 +316,7 @@ everywhereOnCppTopDownM f = f >=> go
311 go (CppUnary op j) = CppUnary op <$> f' j
316 go (CppUnary op j) = CppUnary op <$> f' j
312 go (CppBinary op j1 j2) = CppBinary op <$> f' j1 <*> f' j2
317 go (CppBinary op j1 j2) = CppBinary op <$> f' j1 <*> f' j2
313 go (CppArrayLiteral cpp) = CppArrayLiteral <$> traverse f' cpp
318 go (CppArrayLiteral cpp) = CppArrayLiteral <$> traverse f' cpp
319+ go (CppDataLiteral cpp) = CppDataLiteral <$> traverse f' cpp
314 go (CppIndexer j1 j2) = CppIndexer <$> f' j1 <*> f' j2
320 go (CppIndexer j1 j2) = CppIndexer <$> f' j1 <*> f' j2
315 go (CppObjectLiteral cpp) = CppObjectLiteral <$> traverse (sndM f') cpp
321 go (CppObjectLiteral cpp) = CppObjectLiteral <$> traverse (sndM f') cpp
316 go (CppAccessor prop j) = CppAccessor prop <$> f' j
322 go (CppAccessor prop j) = CppAccessor prop <$> f' j
@@ -336,6 +342,7 @@ everythingOnCpp (<>) f = go
336 go j@(CppUnary _ j1) = f j <> go j1
342 go j@(CppUnary _ j1) = f j <> go j1
337 go j@(CppBinary _ j1 j2) = f j <> go j1 <> go j2
343 go j@(CppBinary _ j1 j2) = f j <> go j1 <> go j2
338 go j@(CppArrayLiteral cpp) = foldl (<>) (f j) (map go cpp)
344 go j@(CppArrayLiteral cpp) = foldl (<>) (f j) (map go cpp)
345+ go j@(CppDataLiteral cpp) = foldl (<>) (f j) (map go cpp)
339 go j@(CppIndexer j1 j2) = f j <> go j1 <> go j2
346 go j@(CppIndexer j1 j2) = f j <> go j1 <> go j2
340 go j@(CppObjectLiteral cpp) = foldl (<>) (f j) (map (go . snd) cpp)
347 go j@(CppObjectLiteral cpp) = foldl (<>) (f j) (map (go . snd) cpp)
341 go j@(CppAccessor j1 j2) = f j <> go j1 <> go j2
348 go j@(CppAccessor j1 j2) = f j <> go j1 <> go j2
src/Language/PureScript/CodeGen/Cpp/Optimizer/Inliner.hs+1
@@ -48,6 +48,7 @@ shouldInline (CppStringLiteral _) = True
48shouldInline (CppBooleanLiteral _) = True
48shouldInline (CppBooleanLiteral _) = True
49shouldInline (CppAccessor _ val) = shouldInline val
49shouldInline (CppAccessor _ val) = shouldInline val
50shouldInline (CppIndexer index val) = shouldInline index && shouldInline val
50shouldInline (CppIndexer index val) = shouldInline index && shouldInline val
51+shouldInline (CppCast _ val) = shouldInline val
51shouldInline _ = False
52shouldInline _ = False
52
53
53etaConvert :: Cpp -> Cpp
54etaConvert :: Cpp -> Cpp
src/Language/PureScript/CodeGen/Cpp/Types.hs+4−1
@@ -108,8 +108,11 @@ charType = CppPrimitive "char"
108mapType :: CppType
108mapType :: CppType
109mapType = CppPrimitive "any::map"
109mapType = CppPrimitive "any::map"
110
110
111+dataType :: CppType
112+dataType = CppPrimitive "any::data"
113+
111arrayType :: CppType
114arrayType :: CppType
112−arrayType = CppPrimitive "any::vector"
115+arrayType = CppPrimitive "any::array"
113
116
114thunkMarkerType :: CppType
117thunkMarkerType :: CppType
115thunkMarkerType = CppPrimitive "any::as_thunk"
118thunkMarkerType = CppPrimitive "any::as_thunk"
src/Language/PureScript/Pretty/Cpp.hs+6
@@ -71,6 +71,12 @@ literals = mkPattern' match
71 , fmap (intercalate ", ") $ forM xs prettyPrintCpp'
71 , fmap (intercalate ", ") $ forM xs prettyPrintCpp'
72 , return " }"
72 , return " }"
73 ]
73 ]
74+ match (CppDataLiteral xs) = fmap concat $ sequence
75+ [ return $ runType dataType
76+ , return "{ "
77+ , fmap (intercalate ", ") $ forM xs prettyPrintCpp'
78+ , return " }"
79+ ]
74 match (CppObjectLiteral ps) = fmap concat $ sequence
80 match (CppObjectLiteral ps) = fmap concat $ sequence
75 [ return $ runType mapType ++ "{\n"
81 [ return $ runType mapType ++ "{\n"
76 , withIndent $ do
82 , withIndent $ do