git.iko.soy/rowtype-yoga/purescript-native
on golang help sign in
C++: switch 'map' to std::array
fc1751cAndy Arvanitis
pcc/include/purescript.cc+15−27
@@ -70,10 +70,6 @@ any::operator cstring() const {
70 return variant.s->c_str();
70 return variant.s->c_str();
71}
71}
72
72
73−any::operator const map&() const {
74− RETURN_VALUE(Type::Map, m, *)
75−}
76−
77any::operator const array&() const {
73any::operator const array&() const {
78 RETURN_VALUE(Type::Array, a, *)
74 RETURN_VALUE(Type::Array, a, *)
79}
75}
@@ -90,21 +86,17 @@ auto any::unthunkVariant(const any& a) -> const any& {
90 return *variant;
86 return *variant;
91}
87}
92
88
93−auto any::operator[](const char rhs[]) const -> const any& {
89+auto any::operator[](const symbol_t key) const -> const any& {
94 const any& variant = unthunkVariant(*this);
90 const any& variant = unthunkVariant(*this);
95 assert(variant.type == Type::Map);
91 assert(variant.type == Type::Map);
96− const auto begin = variant.m->cbegin();
92+ // TODO: assumes at least one element -- safe assumption?
97− const auto end = variant.m->cend();
93+ const auto m = cast<map<1>>(variant);
98− for (auto it = begin; it != end; ++it) {
94+ decltype(m)::size_type i = 0;
95+ do {
99− if (it->first == rhs) {
96+ if (m[i].first == key) {
100− return it->second;
97+ return m[i].second;
101 }
98 }
102− }
99+ } while (m[++i].first != nullptr);
103− for (auto it = begin; it != end; ++it) {
104− if (strcmp(it->first, rhs) == 0) {
105− return it->second;
106− }
107− }
108 throw runtime_error("map key not found");
100 throw runtime_error("map key not found");
109}
101}
110
102
@@ -120,21 +112,17 @@ auto any::operator[](const any& rhs) const -> const any& {
120 return (*variant.a)[cast<int>(rhs)];
112 return (*variant.a)[cast<int>(rhs)];
121}
113}
122
114
123−auto any::contains(const char key[]) const -> bool {
115+auto any::contains(const symbol_t key) const -> bool {
124 const any& variant = unthunkVariant(*this);
116 const any& variant = unthunkVariant(*this);
125 assert(variant.type == Type::Map);
117 assert(variant.type == Type::Map);
126− const auto begin = variant.m->cbegin();
118+ // TODO: assumes at least one element -- safe assumption?
127− const auto end = variant.m->cend();
119+ const auto m = cast<map<1>>(variant);
128− for (auto it = begin; it != end; ++it) {
120+ decltype(m)::size_type i = 0;
121+ do {
129− if (it->first == key) {
122+ if (m[i].first == key) {
130 return true;
123 return true;
131 }
124 }
132− }
125+ } while (m[++i].first != nullptr);
133− for (auto it = begin; it != end; ++it) {
134− if (strcmp(it->first, key) == 0) {
135− return true;
136− }
137− }
138 return false;
126 return false;
139}
127}
140
128
pcc/include/purescript.hh+39−24
@@ -30,7 +30,6 @@
30
30
31#include <functional>
31#include <functional>
32#include <string>
32#include <string>
33−#include <vector>
34#include <array>
33#include <array>
35#include <deque>
34#include <deque>
36#include <utility>
35#include <utility>
@@ -43,6 +42,18 @@ namespace PureScript {
43using cstring = const char *;
42using cstring = const char *;
44using std::nullptr_t;
43using std::nullptr_t;
45
44
45+struct symbol_generator_anchor {};
46+using symbol_t = const symbol_generator_anchor *;
47+
48+template <typename T>
49+struct symbol_generator {
50+ constexpr static symbol_generator_anchor anchor = symbol_generator_anchor{};
51+};
52+template <typename T>
53+constexpr symbol_generator_anchor symbol_generator<T>::anchor;
54+
55+#define SYMBOL(S) &symbol_generator<symbol::S>::anchor
56+
46// Workaround for missing C++11 version in gcc
57// Workaround for missing C++11 version in gcc
47class runtime_error : public std::runtime_error {
58class runtime_error : public std::runtime_error {
48public:
59public:
@@ -84,11 +95,13 @@ class any {
84 };
95 };
85 static constexpr as_thunk unthunk = as_thunk{};
96 static constexpr as_thunk unthunk = as_thunk{};
86
97
87− using map_pair = std::pair<const char * const, const any>;
98+ using map_pair = std::pair<const symbol_t, const any>;
99+
100+ template <size_t N>
88− using map = std::vector<map_pair WITH_ALLOCATOR(map_pair)>;
101+ using map = std::array<const map_pair, N>;
89
102
90 template <size_t N>
103 template <size_t N>
91− using data = std::array<any, N>;
104+ using data = std::array<const any, N>;
92
105
93 using array = std::deque<any WITH_ALLOCATOR(any)>;
106 using array = std::deque<any WITH_ALLOCATOR(any)>;
94 using fn = auto (*)(const any&) -> any;
107 using fn = auto (*)(const any&) -> any;
@@ -140,7 +153,6 @@ class any {
140 mutable eff_fn e;
153 mutable eff_fn e;
141 mutable void * u;
154 mutable void * u;
142 mutable managed<std::string> s;
155 mutable managed<std::string> s;
143− mutable managed<map> m;
144 mutable managed<array> a;
156 mutable managed<array> a;
145 mutable managed<closure> l;
157 mutable managed<closure> l;
146 mutable managed<eff_closure> k;
158 mutable managed<eff_closure> k;
@@ -170,8 +182,8 @@ class any {
170 any(const managed<std::string>& val) noexcept : type(Type::String), s(val) {}
182 any(const managed<std::string>& val) noexcept : type(Type::String), s(val) {}
171 any(managed<std::string>&& val) noexcept : type(Type::String), s(std::move(val)) {}
183 any(managed<std::string>&& val) noexcept : type(Type::String), s(std::move(val)) {}
172
184
173− any(const map& val) : type(Type::Map), m(make_managed<map>(val)) {}
185+ template <size_t N>
174− any(map&& val) noexcept : type(Type::Map), m(make_managed<map>(std::move(val))) {}
186+ any(map<N>&& val) noexcept : type(Type::Map), p(make_managed<map<N>>(std::move(val))) {}
175
187
176 template <size_t N>
188 template <size_t N>
177 any(data<N>&& val) noexcept : type(Type::Data), p(make_managed<data<N>>(std::move(val))) {}
189 any(data<N>&& val) noexcept : type(Type::Data), p(make_managed<data<N>>(std::move(val))) {}
@@ -216,7 +228,7 @@ class any {
216 any(const T& val, typename std::enable_if<std::is_same<T,void*>::value>::type* = 0) noexcept
228 any(const T& val, typename std::enable_if<std::is_same<T,void*>::value>::type* = 0) noexcept
217 : type(Type::RawPointer), u(val) {}
229 : type(Type::RawPointer), u(val) {}
218
230
219− any(std::nullptr_t) noexcept : type(Type::Pointer), p(nullptr) {}
231+ any(std::nullptr_t) noexcept : type(Type::RawPointer), u(nullptr) {}
220
232
221
233
222#if !defined(USE_GC)
234#if !defined(USE_GC)
@@ -249,10 +261,10 @@ class any {
249 case Type::RawPointer: u = other.u; break;
261 case Type::RawPointer: u = other.u; break;
250
262
251 case Type::String: new (&s) managed<std::string>(move_if_rvalue<T>(other.s)); break;
263 case Type::String: new (&s) managed<std::string>(move_if_rvalue<T>(other.s)); break;
252− case Type::Map: new (&m) managed<map>(move_if_rvalue<T>(other.m)); break;
253 case Type::Array: new (&a) managed<array>(move_if_rvalue<T>(other.a)); break;
264 case Type::Array: new (&a) managed<array>(move_if_rvalue<T>(other.a)); break;
254 case Type::Closure: new (&l) managed<closure>(move_if_rvalue<T>(other.l)); break;
265 case Type::Closure: new (&l) managed<closure>(move_if_rvalue<T>(other.l)); break;
255 case Type::EffClosure: new (&k) managed<eff_closure>(move_if_rvalue<T>(other.k)); break;
266 case Type::EffClosure: new (&k) managed<eff_closure>(move_if_rvalue<T>(other.k)); break;
267+ case Type::Map:
256 case Type::Data:
268 case Type::Data:
257 case Type::Pointer: new (&p) managed<void>(move_if_rvalue<T>(other.p)); break;
269 case Type::Pointer: new (&p) managed<void>(move_if_rvalue<T>(other.p)); break;
258
270
@@ -263,10 +275,10 @@ class any {
263 auto destruct() -> void {
275 auto destruct() -> void {
264 switch (type) {
276 switch (type) {
265 case Type::String: s.~managed<std::string>(); break;
277 case Type::String: s.~managed<std::string>(); break;
266− case Type::Map: m.~managed<map>(); break;
267 case Type::Array: a.~managed<array>(); break;
278 case Type::Array: a.~managed<array>(); break;
268 case Type::Closure: l.~managed<closure>(); break;
279 case Type::Closure: l.~managed<closure>(); break;
269 case Type::EffClosure: k.~managed<eff_closure>(); break;
280 case Type::EffClosure: k.~managed<eff_closure>(); break;
281+ case Type::Map:
270 case Type::Data:
282 case Type::Data:
271 case Type::Pointer: p.~managed<void>(); break;
283 case Type::Pointer: p.~managed<void>(); break;
272
284
@@ -314,14 +326,13 @@ class any {
314 operator bool() const;
326 operator bool() const;
315 operator char() const;
327 operator char() const;
316 operator cstring() const;
328 operator cstring() const;
317− operator const map&() const;
318 operator const array&() const;
329 operator const array&() const;
319
330
320− auto operator[](const char[]) const -> const any&;
331+ auto operator[](const symbol_t) const -> const any&;
321 auto operator[](const size_t) const -> const any&;
332 auto operator[](const size_t) const -> const any&;
322 auto operator[](const any&) const -> const any&;
333 auto operator[](const any&) const -> const any&;
323
334
324− auto contains(const char[]) const -> bool;
335+ auto contains(const symbol_t) const -> bool;
325
336
326 auto extractPointer(IF_DEBUG(const Type)) const -> void*;
337 auto extractPointer(IF_DEBUG(const Type)) const -> void*;
327
338
@@ -389,19 +400,25 @@ class any {
389 DEFINE_OPERATOR(%, char, char)
400 DEFINE_OPERATOR(%, char, char)
390
401
391 friend auto operator-(const any&) -> any; // unary negate
402 friend auto operator-(const any&) -> any; // unary negate
392−};
403+
404+}; // class any
393
405
394template <typename T, typename U=void>
406template <typename T, typename U=void>
395−struct TypeTag {};
407+struct tag_helper {};
408+
409+template <size_t N>
410+struct tag_helper<any::map<N>> {
411+ static constexpr any::Type tag = any::Type::Map;
412+};
396
413
397template <size_t N>
414template <size_t N>
398−struct TypeTag<any::data<N>> {
415+struct tag_helper<any::data<N>> {
399− static constexpr any::Type TypeId = any::Type::Data;
416+ static constexpr any::Type tag = any::Type::Data;
400};
417};
401
418
402template <typename T>
419template <typename T>
403−struct TypeTag<T> {
420+struct tag_helper<T> {
404− static constexpr any::Type TypeId = any::Type::Pointer;
421+ static constexpr any::Type tag = any::Type::Pointer;
405};
422};
406
423
407template <typename T>
424template <typename T>
@@ -413,16 +430,14 @@ inline auto cast(const any& a) ->
413
430
414template <typename T>
431template <typename T>
415inline auto cast(const any& a) ->
432inline auto cast(const any& a) ->
416− typename std::enable_if<std::is_same<T, any::map>::value ||
433+ typename std::enable_if<std::is_same<T, any::array>::value, const T&>::type {
417− std::is_same<T, any::array>::value, const T&>::type {
418 return a;
434 return a;
419}
435}
420
436
421template <typename T, typename = typename std::enable_if<std::is_class<T>::value>::type>
437template <typename T, typename = typename std::enable_if<std::is_class<T>::value>::type>
422inline auto cast(const any& a) ->
438inline auto cast(const any& a) ->
423− typename std::enable_if<!std::is_same<T, any::map>::value &&
439+ typename std::enable_if<!std::is_same<T, any::array>::value, T&>::type {
424− !std::is_same<T, any::array>::value, T&>::type {
425− return *static_cast<T*>(a.extractPointer(IF_DEBUG(TypeTag<T>::TypeId)));
440+ return *static_cast<T*>(a.extractPointer(IF_DEBUG(tag_helper<T>::tag)));
426}
441}
427
442
428template <typename T>
443template <typename T>
src/Language/PureScript/CodeGen/Cpp.hs+37−11
@@ -99,9 +99,10 @@ moduleToCpp env (Module _ mn imps _ foreigns decls) = do
99 P.linebreak ++
99 P.linebreak ++
100 fileEnd mn "HH"
100 fileEnd mn "HH"
101 let bodyCpps = toBodyDecl optimized ++ toBody optimized
101 let bodyCpps = toBodyDecl optimized ++ toBody optimized
102+ symbols = allSymbols bodyCpps
102 moduleBody =
103 moduleBody =
103 CppInclude (runModuleName mn) (runModuleName mn) :
104 CppInclude (runModuleName mn) (runModuleName mn) :
104− P.linebreak ++
105+ symbolDefs symbols :
105 (if null bodyCpps
106 (if null bodyCpps
106 then []
107 then []
107 else [ CppNamespace (runModuleName mn) $
108 else [ CppNamespace (runModuleName mn) $
@@ -186,10 +187,15 @@ moduleToCpp env (Module _ mn imps _ foreigns decls) = do
186 args' = (\i -> (identToCpp i, aty)) <$> fst abs'
187 args' = (\i -> (identToCpp i, aty)) <$> fst abs'
187 abs' = unAbs body []
188 abs' = unAbs body []
188 isAccessor :: Expr Ann -> Bool
189 isAccessor :: Expr Ann -> Bool
189− isAccessor Accessor{} = True
190+ isAccessor (Accessor _ _ e)
191+ | (_, f, _, _) <- everythingOnValues (&&) (const False) notAbs (const False) (const False) = f e
192+ where
193+ notAbs :: Expr Ann -> Bool
194+ notAbs Abs{} = False
195+ notAbs _ = True
190 isAccessor _ = False
196 isAccessor _ = False
191 isIndexer :: Cpp -> Bool
197 isIndexer :: Cpp -> Bool
192− isIndexer (CppIndexer (CppStringLiteral _) (CppVar _)) = True
198+ isIndexer (CppIndexer (CppSymbol _) (CppVar _)) = True
193 isIndexer _ = False
199 isIndexer _ = False
194 classes = qualifiedToCpp (Ident . runProperName) . T.constraintClass <$>
200 classes = qualifiedToCpp (Ident . runProperName) . T.constraintClass <$>
195 maybe [] extractConstraints ty'
201 maybe [] extractConstraints ty'
@@ -440,18 +446,20 @@ moduleToCpp env (Module _ mn imps _ foreigns decls) = do
440 CppArrayLiteral <$> mapM valueToCpp xs
446 CppArrayLiteral <$> mapM valueToCpp xs
441
447
442 valueToCpp (Literal _ (ObjectLiteral ps)) =
448 valueToCpp (Literal _ (ObjectLiteral ps)) =
443− CppObjectLiteral CppRecord <$> sortBy (compare `on` fst) <$> mapM (sndM valueToCpp) ps
449+ CppObjectLiteral CppRecord <$>
450+ mapM (sndM valueToCpp) ((\(k,v) -> (CppSymbol k, v)) <$> sortBy (compare `on` fst) ps)
444
451
445 valueToCpp (Accessor _ prop val) =
452 valueToCpp (Accessor _ prop val) =
446− CppIndexer <$> pure (CppStringLiteral prop) <*> valueToCpp val
453+ CppIndexer <$> pure (CppSymbol prop) <*> valueToCpp val
447
454
448 -- TODO: use a more efficient way of copying/updating the map?
455 -- TODO: use a more efficient way of copying/updating the map?
449 valueToCpp (ObjectUpdate (_, _, Just ty, _) obj ps) = do
456 valueToCpp (ObjectUpdate (_, _, Just ty, _) obj ps) = do
450 obj' <- valueToCpp obj
457 obj' <- valueToCpp obj
451 updatedFields <- mapM (sndM valueToCpp) ps
458 updatedFields <- mapM (sndM valueToCpp) ps
452 let origKeys = (allKeys ty) \\ (fst <$> updatedFields)
459 let origKeys = (allKeys ty) \\ (fst <$> updatedFields)
453− origFields = (\key -> (key, CppIndexer (CppStringLiteral key) obj')) <$> origKeys
460+ origFields = (\key -> (key, CppIndexer (CppSymbol key) obj')) <$> origKeys
461+ return $ CppObjectLiteral CppRecord $
454− return $ CppObjectLiteral CppRecord . sortBy (compare `on` fst) $ origFields ++ updatedFields
462+ (\(k,v) -> (CppSymbol k, v)) <$> sortBy (compare `on` fst) (origFields ++ updatedFields)
455 where
463 where
456 allKeys :: T.Type -> [String]
464 allKeys :: T.Type -> [String]
457 allKeys (T.TypeApp (T.TypeConstructor _) r@(T.RCons {})) = fst <$> (fst $ T.rowToList r)
465 allKeys (T.TypeApp (T.TypeConstructor _) r@(T.RCons {})) = fst <$> (fst $ T.rowToList r)
@@ -485,7 +493,7 @@ moduleToCpp env (Module _ mn imps _ foreigns decls) = do
485 let Just (_, constraints, fns) = findClass (Qualified mn' (ProperName classname)) in
493 let Just (_, constraints, fns) = findClass (Qualified mn' (ProperName classname)) in
486 return . CppObjectLiteral CppInstance $
494 return . CppObjectLiteral CppInstance $
487 zip
495 zip
488− ((sort $ superClassDictionaryNames constraints) ++ (fst <$> fns))
496+ (CppSymbol <$> (sort $ superClassDictionaryNames constraints) ++ (fst <$> fns))
489 args'
497 args'
490 Var _ (Qualified (Just _) _) -> applied f args' curriedName'
498 Var _ (Qualified (Just _) _) -> applied f args' curriedName'
491 _ -> applied f args' id
499 _ -> applied f args' id
@@ -716,7 +724,7 @@ moduleToCpp env (Module _ mn imps _ foreigns decls) = do
716 (propVar, Nothing)
724 (propVar, Nothing)
717 []
725 []
718 (Just $ CppIndexer
726 (Just $ CppIndexer
719− (CppStringLiteral prop)
727+ (CppSymbol prop)
720 (CppVar varName))
728 (CppVar varName))
721 : cpp
729 : cpp
722
730
@@ -872,12 +880,12 @@ extractConstraints = go []
872---------------------------------------------------------------------------------------------------
880---------------------------------------------------------------------------------------------------
873dictIndexerToEnum :: [(Cpp,Cpp)] -> Cpp -> Cpp
881dictIndexerToEnum :: [(Cpp,Cpp)] -> Cpp -> Cpp
874---------------------------------------------------------------------------------------------------
882---------------------------------------------------------------------------------------------------
875−dictIndexerToEnum repls (CppIndexer (CppStringLiteral prop) dict)
883+dictIndexerToEnum repls (CppIndexer (CppSymbol prop) dict)
876 | Just cls <- lookup dict repls =
884 | Just cls <- lookup dict repls =
877 CppBinary Dot
885 CppBinary Dot
878 (CppIndexer
886 (CppIndexer
879 (CppAccessor (CppVar . identToCpp $ Ident prop) cls)
887 (CppAccessor (CppVar . identToCpp $ Ident prop) cls)
880− (CppCast mapType dict))
888+ (CppCast (mapType 1) dict))
881 (CppVar "second")
889 (CppVar "second")
882dictIndexerToEnum _ cpp = cpp
890dictIndexerToEnum _ cpp = cpp
883
891
@@ -918,3 +926,21 @@ convertIfPrimFn (Just ty) (CppFunction name params _ qs body)
918 | (tys', Just rty') <- primFn ty =
926 | (tys', Just rty') <- primFn ty =
919 CppFunction name (zipWith (\(p, _) t -> (p, Just t)) params tys') (Just rty') qs body
927 CppFunction name (zipWith (\(p, _) t -> (p, Just t)) params tys') (Just rty') qs body
920convertIfPrimFn _ cpp = cpp
928convertIfPrimFn _ cpp = cpp
929+
930+---------------------------------------------------------------------------------------------------
931+allSymbols :: [Cpp] -> [String]
932+---------------------------------------------------------------------------------------------------
933+allSymbols cpps = nub $ concatMap (everythingOnCpp (++) symbols) cpps
934+ where
935+ symbols :: Cpp -> [String]
936+ symbols (CppSymbol s) = [symbolname s]
937+ symbols _ = []
938+
939+---------------------------------------------------------------------------------------------------
940+symbolDefs :: [String] -> Cpp
941+---------------------------------------------------------------------------------------------------
942+symbolDefs [] = CppNoOp
943+symbolDefs syms = CppNamespace "PureScript" [CppNamespace "symbol" (asFunc <$> syms)]
944+ where
945+ asFunc :: String -> Cpp
946+ asFunc s = CppStruct s []
src/Language/PureScript/CodeGen/Cpp/AST.hs+11−6
@@ -185,7 +185,7 @@ data Cpp
185 -- |
185 -- |
186 -- An object literal
186 -- An object literal
187 --
187 --
188− | CppObjectLiteral CppObjectType [(String, Cpp)]
188+ | CppObjectLiteral CppObjectType [(Cpp, Cpp)]
189 -- |
189 -- |
190 -- An general property accessor expression (property, expr)
190 -- An general property accessor expression (property, expr)
191 --
191 --
@@ -211,6 +211,11 @@ data Cpp
211 --
211 --
212 | CppVar String
212 | CppVar String
213 -- |
213 -- |
214+ -- Unique system-wide name/constant
215+ --
216+ | CppSymbol String
217+ -- |
218+ -- |
214 -- A block of expressions in braces
219 -- A block of expressions in braces
215 --
220 --
216 | CppBlock [Cpp]
221 | CppBlock [Cpp]
@@ -297,7 +302,7 @@ everywhereOnCpp f = go
297 go (CppArrayLiteral cpp) = f (CppArrayLiteral (map go cpp))
302 go (CppArrayLiteral cpp) = f (CppArrayLiteral (map go cpp))
298 go (CppDataLiteral cpp) = f (CppDataLiteral (map go cpp))
303 go (CppDataLiteral cpp) = f (CppDataLiteral (map go cpp))
299 go (CppIndexer j1 j2) = f (CppIndexer (go j1) (go j2))
304 go (CppIndexer j1 j2) = f (CppIndexer (go j1) (go j2))
300− go (CppObjectLiteral t cpp) = f (CppObjectLiteral t (map (fmap go) cpp))
305+ go (CppObjectLiteral t cpps) = f (CppObjectLiteral t (map (fmap go) cpps))
301 go (CppAccessor prop j) = f (CppAccessor (go prop) (go j))
306 go (CppAccessor prop j) = f (CppAccessor (go prop) (go j))
302 go (CppFunction name args rty qs j) = f (CppFunction name args rty qs (go j))
307 go (CppFunction name args rty qs j) = f (CppFunction name args rty qs (go j))
303 go (CppLambda cps args rty j) = f (CppLambda cps args rty (go j))
308 go (CppLambda cps args rty j) = f (CppLambda cps args rty (go j))
@@ -328,7 +333,7 @@ everywhereOnCppTopDownM f = f >=> go
328 go (CppArrayLiteral cpp) = CppArrayLiteral <$> traverse f' cpp
333 go (CppArrayLiteral cpp) = CppArrayLiteral <$> traverse f' cpp
329 go (CppDataLiteral cpp) = CppDataLiteral <$> traverse f' cpp
334 go (CppDataLiteral cpp) = CppDataLiteral <$> traverse f' cpp
330 go (CppIndexer j1 j2) = CppIndexer <$> f' j1 <*> f' j2
335 go (CppIndexer j1 j2) = CppIndexer <$> f' j1 <*> f' j2
331− go (CppObjectLiteral t cpp) = CppObjectLiteral t <$> traverse (sndM f') cpp
336+ go (CppObjectLiteral t cpps) = CppObjectLiteral t <$> traverse (pairM f' f') cpps
332 go (CppAccessor prop j) = CppAccessor prop <$> f' j
337 go (CppAccessor prop j) = CppAccessor prop <$> f' j
333 go (CppFunction name args rty qs j) = CppFunction name args rty qs <$> f' j
338 go (CppFunction name args rty qs j) = CppFunction name args rty qs <$> f' j
334 go (CppLambda cps args rty j) = CppLambda cps args rty <$> f' j
339 go (CppLambda cps args rty j) = CppLambda cps args rty <$> f' j
@@ -341,7 +346,7 @@ everywhereOnCppTopDownM f = f >=> go
341 go (CppAssignment j1 j2) = CppAssignment <$> f' j1 <*> f' j2
346 go (CppAssignment j1 j2) = CppAssignment <$> f' j1 <*> f' j2
342 go (CppWhile j1 j2) = CppWhile <$> f' j1 <*> f' j2
347 go (CppWhile j1 j2) = CppWhile <$> f' j1 <*> f' j2
343 go (CppIfElse j1 j2 j3) = CppIfElse <$> f' j1 <*> f' j2 <*> traverse f' j3
348 go (CppIfElse j1 j2 j3) = CppIfElse <$> f' j1 <*> f' j2 <*> traverse f' j3
344− go (CppSwitch cpp cpps) = CppSwitch <$> f' cpp <*> traverse (sndM f') cpps
349+ go (CppSwitch cpp cpps) = CppSwitch <$> f' cpp <*> traverse (pairM f' f') cpps
345 go (CppReturn j) = CppReturn <$> f' j
350 go (CppReturn j) = CppReturn <$> f' j
346 go (CppThrow j) = CppThrow <$> f' j
351 go (CppThrow j) = CppThrow <$> f' j
347 go (CppComment com j) = CppComment com <$> f' j
352 go (CppComment com j) = CppComment com <$> f' j
@@ -355,7 +360,7 @@ everythingOnCpp (<>) f = go
355 go j@(CppArrayLiteral cpp) = foldl (<>) (f j) (map go cpp)
360 go j@(CppArrayLiteral cpp) = foldl (<>) (f j) (map go cpp)
356 go j@(CppDataLiteral cpp) = foldl (<>) (f j) (map go cpp)
361 go j@(CppDataLiteral cpp) = foldl (<>) (f j) (map go cpp)
357 go j@(CppIndexer j1 j2) = f j <> go j1 <> go j2
362 go j@(CppIndexer j1 j2) = f j <> go j1 <> go j2
358− go j@(CppObjectLiteral _ cpp) = foldl (<>) (f j) (map (go . snd) cpp)
363+ go j@(CppObjectLiteral _ cpps) = foldl (<>) (f j) ((map (go . fst) cpps) ++ (map (go . snd) cpps))
359 go j@(CppAccessor j1 j2) = f j <> go j1 <> go j2
364 go j@(CppAccessor j1 j2) = f j <> go j1 <> go j2
360 go j@(CppFunction _ _ _ _ j1) = f j <> go j1
365 go j@(CppFunction _ _ _ _ j1) = f j <> go j1
361 go j@(CppLambda _ _ _ j1) = f j <> go j1
366 go j@(CppLambda _ _ _ j1) = f j <> go j1
@@ -369,7 +374,7 @@ everythingOnCpp (<>) f = go
369 go j@(CppWhile j1 j2) = f j <> go j1 <> go j2
374 go j@(CppWhile j1 j2) = f j <> go j1 <> go j2
370 go j@(CppIfElse j1 j2 Nothing) = f j <> go j1 <> go j2
375 go j@(CppIfElse j1 j2 Nothing) = f j <> go j1 <> go j2
371 go j@(CppIfElse j1 j2 (Just j3)) = f j <> go j1 <> go j2 <> go j3
376 go j@(CppIfElse j1 j2 (Just j3)) = f j <> go j1 <> go j2 <> go j3
372− go j@(CppSwitch cpp cpps) = foldl (<>) (f j <> go cpp) (map (go . snd) cpps)
377+ go j@(CppSwitch cpp cpps) = foldl (<>) (f j <> go cpp) ((map (go . fst) cpps) ++ (map (go . snd) cpps))
373 go j@(CppReturn j1) = f j <> go j1
378 go j@(CppReturn j1) = f j <> go j1
374 go j@(CppThrow j1) = f j <> go j1
379 go j@(CppThrow j1) = f j <> go j1
375 go j@(CppComment _ j1) = f j <> go j1
380 go j@(CppComment _ j1) = f j <> go j1
src/Language/PureScript/CodeGen/Cpp/Common.hs+1
@@ -167,6 +167,7 @@ nameIsCppReserved name =
167 , "string"
167 , "string"
168 , "struct"
168 , "struct"
169 , "switch"
169 , "switch"
170+ , "symbol"
170 , "template"
171 , "template"
171 , "this"
172 , "this"
172 , "thread_local"
173 , "thread_local"
src/Language/PureScript/CodeGen/Cpp/File.hs+1−1
@@ -141,7 +141,7 @@ toBody = catMaybes . map go
141 addCaptures :: Cpp -> Cpp
141 addCaptures :: Cpp -> Cpp
142 addCaptures (CppObjectLiteral t objs) = CppObjectLiteral t (objlam <$> objs)
142 addCaptures (CppObjectLiteral t objs) = CppObjectLiteral t (objlam <$> objs)
143 where
143 where
144− objlam :: (String, Cpp) -> (String, Cpp)
144+ objlam :: (Cpp, Cpp) -> (Cpp, Cpp)
145 objlam (name', (CppLambda _ args rty body)) = (name' , CppLambda [] args rty $ addCaptures body)
145 objlam (name', (CppLambda _ args rty body)) = (name' , CppLambda [] args rty $ addCaptures body)
146 objlam obj = obj
146 objlam obj = obj
147 addCaptures (CppApp (CppLambda _ [] rty body) []) = CppApp (CppLambda [] [] rty (addCaptures body)) []
147 addCaptures (CppApp (CppLambda _ [] rty body) []) = CppApp (CppLambda [] [] rty (addCaptures body)) []
src/Language/PureScript/CodeGen/Cpp/Optimizer/MagicDo.hs+1−1
@@ -128,7 +128,7 @@ inlineST = everywhereOnCpp convertBlock
128 -- or in a more aggressive way, turning wrappers into local variables depending on the
128 -- or in a more aggressive way, turning wrappers into local variables depending on the
129 -- agg(ressive) parameter.
129 -- agg(ressive) parameter.
130 convert agg (CppApp f [arg]) | isSTFunc C.newSTRef f =
130 convert agg (CppApp f [arg]) | isSTFunc C.newSTRef f =
131− CppLambda [CppCaptureAll] [] Nothing (CppBlock [CppReturn $ if agg then arg else CppObjectLiteral CppRecord [(C.stRefValue, arg)]])
131+ CppLambda [CppCaptureAll] [] Nothing (CppBlock [CppReturn $ if agg then arg else CppObjectLiteral CppRecord [(CppSymbol C.stRefValue, arg)]])
132 convert agg (CppApp (CppApp f [ref]) []) | isSTFunc C.readSTRef f =
132 convert agg (CppApp (CppApp f [ref]) []) | isSTFunc C.readSTRef f =
133 if agg then ref else CppAccessor (CppVar C.stRefValue) ref
133 if agg then ref else CppAccessor (CppVar C.stRefValue) ref
134 convert agg (CppApp (CppApp (CppApp f [ref]) [arg]) []) | isSTFunc C.writeSTRef f =
134 convert agg (CppApp (CppApp (CppApp f [ref]) [arg]) []) | isSTFunc C.writeSTRef f =
src/Language/PureScript/CodeGen/Cpp/Types.hs+8−2
@@ -124,8 +124,11 @@ stringType = CppPrimitive "string"
124charType :: CppType
124charType :: CppType
125charType = CppPrimitive "char"
125charType = CppPrimitive "char"
126
126
127+voidType :: CppType
128+voidType = CppPrimitive "void"
129+
127−mapType :: CppType
130+mapType :: Int -> CppType
128−mapType = CppPrimitive "any::map"
131+mapType n = CppPrimitive $ "any::map<" ++ show n ++ ">"
129
132
130dataType :: Int -> CppType
133dataType :: Int -> CppType
131dataType n = CppPrimitive $ "any::data<" ++ show n ++ ">"
134dataType n = CppPrimitive $ "any::data<" ++ show n ++ ">"
@@ -141,3 +144,6 @@ ctorKey = "constructor"
141
144
142constAnyRef :: Maybe CppType
145constAnyRef :: Maybe CppType
143constAnyRef = Just $ CppAny [CppConst, CppRef]
146constAnyRef = Just $ CppAny [CppConst, CppRef]
147+
148+symbolname :: String -> String
149+symbolname = identToCpp . Ident
src/Language/PureScript/Pretty/Cpp.hs+6−5
@@ -40,7 +40,6 @@ import qualified Control.Arrow as A
40import Language.PureScript.CodeGen.Cpp.AST
40import Language.PureScript.CodeGen.Cpp.AST
41import Language.PureScript.CodeGen.Cpp.Types
41import Language.PureScript.CodeGen.Cpp.Types
42import Language.PureScript.Comments
42import Language.PureScript.Comments
43−-- import Language.PureScript.Pretty.Common
44import qualified Language.PureScript.Constants as C
43import qualified Language.PureScript.Constants as C
45import Numeric
44import Numeric
46-- import Debug.Trace
45-- import Debug.Trace
@@ -118,17 +117,17 @@ literals = mkPattern' match
118 , return " }"
117 , return " }"
119 ]
118 ]
120 match (CppObjectLiteral _ ps) = fmap concat $ sequence
119 match (CppObjectLiteral _ ps) = fmap concat $ sequence
121− [ return $ runType mapType ++ "{\n"
120+ [ return $ runType (mapType $ length ps + 1) ++ "{{\n"
122 , withIndent $ do
121 , withIndent $ do
123 cpps <- forM ps $ \(key, value) -> do
122 cpps <- forM ps $ \(key, value) -> do
124 value' <- prettyPrintCpp' value
123 value' <- prettyPrintCpp' value
125− key' <- prettyPrintCpp' (CppStringLiteral key)
124+ key' <- prettyPrintCpp' key
126 return $ "{ " ++ key' ++ ", " ++ value' ++ " }"
125 return $ "{ " ++ key' ++ ", " ++ value' ++ " }"
127 indentString <- currentIndent
126 indentString <- currentIndent
128− return $ intercalate ", \n" $ map (indentString ++) cpps
127+ return $ intercalate ", \n" $ map (indentString ++) (cpps ++ ["{ nullptr, nullptr }"])
129 , return "\n"
128 , return "\n"
130 , currentIndent
129 , currentIndent
131− , return "}"
130+ , return "}}"
132 ]
131 ]
133
132
134 match (CppFunction name args rty qs ret) =
133 match (CppFunction name args rty qs ret) =
@@ -196,6 +195,7 @@ literals = mkPattern' match
196 isUseNamespace :: Cpp -> Bool
195 isUseNamespace :: Cpp -> Bool
197 isUseNamespace (CppUseNamespace{}) = True
196 isUseNamespace (CppUseNamespace{}) = True
198 isUseNamespace _ = False
197 isUseNamespace _ = False
198+ match (CppStruct (name) []) = return $ "struct " ++ name ++ " {}"
199 match (CppStruct (name) mems) = fmap concat $ sequence $
199 match (CppStruct (name) mems) = fmap concat $ sequence $
200 [ return "\n"
200 [ return "\n"
201 , currentIndent
201 , currentIndent
@@ -240,6 +240,7 @@ literals = mkPattern' match
240
240
241 match (CppVar ident) | ident == C.__unused = match (CppVar $ '$':ident)
241 match (CppVar ident) | ident == C.__unused = match (CppVar $ '$':ident)
242 match (CppVar ident) = return ident
242 match (CppVar ident) = return ident
243+ match (CppSymbol ident) = return $ "SYMBOL" ++ parens (symbolname ident)
243 match (CppApp v [CppNoOp]) = return (prettyPrintCpp1 v)
244 match (CppApp v [CppNoOp]) = return (prettyPrintCpp1 v)
244 match (CppVariableIntroduction (ident, typ) qs value)
245 match (CppVariableIntroduction (ident, typ) qs value)
245 | ident == C.__unused = match (CppVariableIntroduction ('$':ident, typ) qs value)
246 | ident == C.__unused = match (CppVariableIntroduction ('$':ident, typ) qs value)