git.iko.soy/rowtype-yoga/purescript-native
on golang help sign in
Merge remote-tracking branch 'pure11/pure11' into native
a6c8000Andy Arvanitis
pcc/runtime/purescript.cc+9−1
@@ -88,6 +88,10 @@ any::operator const array&() const {
88 RETURN_VALUE(Tag::Array, a, *)
88 RETURN_VALUE(Tag::Array, a, *)
89}
89}
90
90
91+any::operator const record&() const {
92+ RETURN_VALUE(Tag::Record, r, *)
93+}
94+
91auto any::extractPointer(IF_DEBUG(const any::Tag t)) const -> void* {
95auto any::extractPointer(IF_DEBUG(const any::Tag t)) const -> void* {
92 RETURN_VALUE(t, POINTER_FROM_MEMBER(p),)
96 RETURN_VALUE(t, POINTER_FROM_MEMBER(p),)
93}
97}
@@ -115,7 +119,7 @@ auto any::empty() const -> bool {
115
119
116auto any::contains(const Private::Symbol key) const -> bool {
120auto any::contains(const Private::Symbol key) const -> bool {
117 // TODO: assumes at least one element -- safe assumption?
121 // TODO: assumes at least one element -- safe assumption?
118− const auto& m = cast<map<unknown_size>>(*this);
122+ const auto& m = cast<dict<unknown_size>>(*this);
119 std::remove_reference<decltype(m)>::type::size_type i = 0;
123 std::remove_reference<decltype(m)>::type::size_type i = 0;
120 do {
124 do {
121 if (m[i].first == key) {
125 if (m[i].first == key) {
@@ -125,6 +129,10 @@ auto any::contains(const Private::Symbol key) const -> bool {
125 return false;
129 return false;
126}
130}
127
131
132+auto any::at(const std::string& key) const -> const any& {
133+ return static_cast<const record&>(*this).at(key);
134+}
135+
128//-----------------------------------------------------------------------------
136//-----------------------------------------------------------------------------
129// Operator helper macros
137// Operator helper macros
130//-----------------------------------------------------------------------------
138//-----------------------------------------------------------------------------
pcc/runtime/purescript.hh+35−23
@@ -36,6 +36,7 @@
36#include <string>
36#include <string>
37#include <array>
37#include <array>
38#include <deque>
38#include <deque>
39+#include <unordered_map>
39#include <utility>
40#include <utility>
40#include <stdexcept>
41#include <stdexcept>
41#include <iso646.h> // mostly for MS Visual Studio compiler
42#include <iso646.h> // mostly for MS Visual Studio compiler
@@ -61,14 +62,14 @@ namespace Private {
61 using Symbol = const SymbolGeneratorAnchor *;
62 using Symbol = const SymbolGeneratorAnchor *;
62}
63}
63
64
64−#define define_symbol(S) namespace PureScript { \
65+#define DEFINE_SYMBOL(S) namespace PureScript { \
65 namespace Private { \
66 namespace Private { \
66 namespace Symbols { \
67 namespace Symbols { \
67 struct S_ ## S {}; \
68 struct S_ ## S {}; \
68 } \
69 } \
69 } \
70 } \
70 }
71 }
71−#define symbol(S) (&Private::SymbolGenerator<::PureScript::Private::Symbols::S_ ## S>::anchor)
72+#define SYM(S) (&Private::SymbolGenerator<::PureScript::Private::Symbols::S_ ## S>::anchor)
72
73
73constexpr bool undefined = false;
74constexpr bool undefined = false;
74
75
@@ -93,6 +94,7 @@ class any {
93 Map,
94 Map,
94 Data,
95 Data,
95 Array,
96 Array,
97+ Record,
96 Closure,
98 Closure,
97 EffClosure,
99 EffClosure,
98 Pointer
100 Pointer
@@ -106,15 +108,17 @@ class any {
106 };
108 };
107 static constexpr as_thunk unthunk = as_thunk{};
109 static constexpr as_thunk unthunk = as_thunk{};
108
110
109− using map_pair = std::pair<const Private::Symbol, const any>;
111+ using dict_pair = std::pair<const Private::Symbol, const any>;
110
112
111 template <size_t N>
113 template <size_t N>
112− using map = std::array<const map_pair, N>;
114+ using dict = std::array<const dict_pair, N>;
113
115
114 template <size_t N>
116 template <size_t N>
115 using data = std::array<const any, N>;
117 using data = std::array<const any, N>;
116
118
117− using array = std::deque<any WITH_ALLOCATOR(any)>;
119+ using array = std::deque<any WITH_ALLOCATOR(any)>;
120+ using record = std::unordered_map<std::string, any WITH_ALLOCATOR_PAIR(std::string, any)>;
121+
118 using fn = auto (*)(const any&) -> any;
122 using fn = auto (*)(const any&) -> any;
119 using eff_fn = auto (*)() -> any;
123 using eff_fn = auto (*)() -> any;
120 using thunk = auto (*)(const as_thunk) -> const any&;
124 using thunk = auto (*)(const as_thunk) -> const any&;
@@ -164,6 +168,7 @@ class any {
164 mutable void * v;
168 mutable void * v;
165 mutable managed<string> s;
169 mutable managed<string> s;
166 mutable managed<array> a;
170 mutable managed<array> a;
171+ mutable managed<record> r;
167 mutable managed<Closure> l;
172 mutable managed<Closure> l;
168 mutable managed<EffClosure> k;
173 mutable managed<EffClosure> k;
169 mutable managed<void> p;
174 mutable managed<void> p;
@@ -183,15 +188,15 @@ class any {
183 template <typename T, typename = typename std::enable_if<std::is_same<bool,T>::value>::type>
188 template <typename T, typename = typename std::enable_if<std::is_same<bool,T>::value>::type>
184 any(const T val) noexcept : tag(Tag::Boolean), b(val) {}
189 any(const T val) noexcept : tag(Tag::Boolean), b(val) {}
185
190
186− any(const char * val) : tag(Tag::String), s(make_managed<string>(val)) {}
191+ any(const char * val) : tag(Tag::String), s(make_managed_and_finalized<string>(val)) {}
187− any(const string& val) : tag(Tag::String), s(make_managed<string>(val)) {}
192+ any(const string& val) : tag(Tag::String), s(make_managed_and_finalized<string>(val)) {}
188− any(string&& val) noexcept : tag(Tag::String), s(make_managed<string>(std::move(val))) {}
193+ any(string&& val) noexcept : tag(Tag::String), s(make_managed_and_finalized<string>(std::move(val))) {}
189
194
190 any(const managed<string>& val) noexcept : tag(Tag::String), s(val) {}
195 any(const managed<string>& val) noexcept : tag(Tag::String), s(val) {}
191 any(managed<string>&& val) noexcept : tag(Tag::String), s(std::move(val)) {}
196 any(managed<string>&& val) noexcept : tag(Tag::String), s(std::move(val)) {}
192
197
193 template <size_t N>
198 template <size_t N>
194− any(map<N>&& val) noexcept : tag(Tag::Map), p(make_managed<map<N>>(std::move(val))) {}
199+ any(dict<N>&& val) noexcept : tag(Tag::Map), p(make_managed<dict<N>>(std::move(val))) {}
195
200
196 template <size_t N>
201 template <size_t N>
197 any(data<N>&& val) noexcept : tag(Tag::Data), p(make_managed<data<N>>(std::move(val))) {}
202 any(data<N>&& val) noexcept : tag(Tag::Data), p(make_managed<data<N>>(std::move(val))) {}
@@ -199,6 +204,9 @@ class any {
199 any(const array& val) : tag(Tag::Array), a(make_managed<array>(val)) {}
204 any(const array& val) : tag(Tag::Array), a(make_managed<array>(val)) {}
200 any(array&& val) noexcept : tag(Tag::Array), a(make_managed<array>(std::move(val))) {}
205 any(array&& val) noexcept : tag(Tag::Array), a(make_managed<array>(std::move(val))) {}
201
206
207+ any(const record& val) : tag(Tag::Record), r(make_managed<record>(val)) {}
208+ any(record&& val) noexcept : tag(Tag::Record), r(make_managed<record>(std::move(val))) {}
209+
202 template <typename T>
210 template <typename T>
203 any(const T& val, typename std::enable_if<std::is_convertible<T,fn>::value>::type* = 0) noexcept
211 any(const T& val, typename std::enable_if<std::is_convertible<T,fn>::value>::type* = 0) noexcept
204 : tag(Tag::Function), f(val) {}
212 : tag(Tag::Function), f(val) {}
@@ -269,6 +277,7 @@ class any {
269
277
270 case Tag::String: new (&s) managed<string>(move_if_rvalue<T>(other.s)); break;
278 case Tag::String: new (&s) managed<string>(move_if_rvalue<T>(other.s)); break;
271 case Tag::Array: new (&a) managed<array>(move_if_rvalue<T>(other.a)); break;
279 case Tag::Array: new (&a) managed<array>(move_if_rvalue<T>(other.a)); break;
280+ case Tag::Record: new (&r) managed<record>(move_if_rvalue<T>(other.r)); break;
272 case Tag::Closure: new (&l) managed<Closure>(move_if_rvalue<T>(other.l)); break;
281 case Tag::Closure: new (&l) managed<Closure>(move_if_rvalue<T>(other.l)); break;
273 case Tag::EffClosure: new (&k) managed<EffClosure>(move_if_rvalue<T>(other.k)); break;
282 case Tag::EffClosure: new (&k) managed<EffClosure>(move_if_rvalue<T>(other.k)); break;
274 case Tag::Map:
283 case Tag::Map:
@@ -283,6 +292,7 @@ class any {
283 switch (tag) {
292 switch (tag) {
284 case Tag::String: s.~managed<string>(); break;
293 case Tag::String: s.~managed<string>(); break;
285 case Tag::Array: a.~managed<array>(); break;
294 case Tag::Array: a.~managed<array>(); break;
295+ case Tag::Record: r.~managed<record>(); break;
286 case Tag::Closure: l.~managed<Closure>(); break;
296 case Tag::Closure: l.~managed<Closure>(); break;
287 case Tag::EffClosure: k.~managed<EffClosure>(); break;
297 case Tag::EffClosure: k.~managed<EffClosure>(); break;
288 case Tag::Map:
298 case Tag::Map:
@@ -337,9 +347,10 @@ class any {
337 operator const string&() const;
347 operator const string&() const;
338 operator const char *() const;
348 operator const char *() const;
339 operator const array&() const;
349 operator const array&() const;
350+ operator const record&() const;
340
351
341 auto operator[](const size_t) const -> const any&;
352 auto operator[](const size_t) const -> const any&;
342−
353+ auto at(const std::string&) const -> const any&;
343 auto size() const -> size_t;
354 auto size() const -> size_t;
344 auto empty() const -> bool;
355 auto empty() const -> bool;
345 auto contains(const Private::Symbol) const -> bool;
356 auto contains(const Private::Symbol) const -> bool;
@@ -419,7 +430,7 @@ namespace Private {
419 struct TagHelper {};
430 struct TagHelper {};
420
431
421 template <size_t N>
432 template <size_t N>
422− struct TagHelper<any::map<N>> {
433+ struct TagHelper<any::dict<N>> {
423 static constexpr any::Tag tag = any::Tag::Map;
434 static constexpr any::Tag tag = any::Tag::Map;
424 };
435 };
425
436
@@ -450,14 +461,16 @@ inline auto cast(const any& a) ->
450template <typename T>
461template <typename T>
451inline auto cast(const any& a) ->
462inline auto cast(const any& a) ->
452 typename std::enable_if<std::is_same<T, string>::value ||
463 typename std::enable_if<std::is_same<T, string>::value ||
453− std::is_same<T, any::array>::value, const T&>::type {
464+ std::is_same<T, any::array>::value ||
465+ std::is_same<T, any::record>::value, const T&>::type {
454 return a;
466 return a;
455}
467}
456
468
457template <typename T,
469template <typename T,
458 typename = typename std::enable_if<std::is_class<T>::value &&
470 typename = typename std::enable_if<std::is_class<T>::value &&
459 !std::is_same<T,string>::value &&
471 !std::is_same<T,string>::value &&
460− !std::is_same<T,any::array>::value>::type>
472+ !std::is_same<T,any::array>::value &&
473+ !std::is_same<T,any::record>::value>::type>
461inline auto cast(const any& a) -> T& {
474inline auto cast(const any& a) -> T& {
462 return *static_cast<T*>(a.extractPointer(IF_DEBUG(Private::TagHelper<T>::tag)));
475 return *static_cast<T*>(a.extractPointer(IF_DEBUG(Private::TagHelper<T>::tag)));
463}
476}
@@ -476,7 +489,7 @@ inline auto cast(const any& a) ->
476 return a.rawPointer();
489 return a.rawPointer();
477}
490}
478
491
479−namespace map {
492+namespace dict {
480 template <size_t N, typename T>
493 template <size_t N, typename T>
481 inline auto get(const T& a) ->
494 inline auto get(const T& a) ->
482 typename std::enable_if<!std::is_same<any, T>::value, const any&>::type {
495 typename std::enable_if<!std::is_same<any, T>::value, const any&>::type {
@@ -485,29 +498,29 @@ namespace map {
485
498
486 template <size_t N>
499 template <size_t N>
487 inline auto get(const any& a) -> const any& {
500 inline auto get(const any& a) -> const any& {
488− return cast<any::map<N+1>>(a)[N].second;
501+ return cast<any::dict<N+1>>(a)[N].second;
489 }
502 }
490
503
491 template <size_t N>
504 template <size_t N>
492− inline auto get(const Private::Symbol key, const any::map<N>& a) -> const any& {
505+ inline auto get(const Private::Symbol key, const any::dict<N>& a) -> const any& {
493− static_assert(N > 0, "map size must be greater than zero");
506+ static_assert(N > 0, "dict size must be greater than zero");
494 typename std::remove_reference<decltype(a)>::type::size_type i = 0;
507 typename std::remove_reference<decltype(a)>::type::size_type i = 0;
495 do {
508 do {
496 if (a[i].first == key) {
509 if (a[i].first == key) {
497 return a[i].second;
510 return a[i].second;
498 }
511 }
499 } while (a[++i].first != nullptr);
512 } while (a[++i].first != nullptr);
500− assert(false && "map key not found");
513+ assert(false && "dict key not found");
501 static const any invalid_key(nullptr);
514 static const any invalid_key(nullptr);
502 return invalid_key;
515 return invalid_key;
503 }
516 }
504
517
505 inline auto get(const Private::Symbol key, const any& a) -> const any& {
518 inline auto get(const Private::Symbol key, const any& a) -> const any& {
506− return get(key, cast<any::map<unknown_size>>(a));
519+ return get(key, cast<any::dict<unknown_size>>(a));
507 }
520 }
508
521
509− #define P(N) any::map_pair&& arg ## N
522+ #define P(N) any::dict_pair&& arg ## N
510− #define T(N) any::map<N+1>
523+ #define T(N) any::dict<N+1>
511 #define E(N) std::forward<decltype(arg ## N)>(arg ## N)
524 #define E(N) std::forward<decltype(arg ## N)>(arg ## N)
512 #define M(...) {{ __VA_ARGS__, { nullptr, nullptr } }}
525 #define M(...) {{ __VA_ARGS__, { nullptr, nullptr } }}
513
526
@@ -542,8 +555,6 @@ namespace map {
542 #undef M
555 #undef M
543}
556}
544
557
545−namespace record = map;
546−
547namespace data {
558namespace data {
548 template <size_t N, typename T>
559 template <size_t N, typename T>
549 inline auto get(const T& a) ->
560 inline auto get(const T& a) ->
@@ -565,6 +576,7 @@ namespace data {
565} // namespace PureScript
576} // namespace PureScript
566
577
567#undef WITH_ALLOCATOR
578#undef WITH_ALLOCATOR
579+#undef WITH_ALLOCATOR_PAIR
568#undef IS_POINTER_TYPE
580#undef IS_POINTER_TYPE
569#undef DEFINE_OPERATOR
581#undef DEFINE_OPERATOR
570#undef DEFINE_COMPARISON_OPERATOR
582#undef DEFINE_COMPARISON_OPERATOR
pcc/runtime/purescript_memory.hh+3−1
@@ -20,15 +20,17 @@
20 #include <gc/gc_cpp.h>
20 #include <gc/gc_cpp.h>
21 #include <gc/gc_allocator.h>
21 #include <gc/gc_allocator.h>
22 #define WITH_ALLOCATOR(T) , gc_allocator<T>
22 #define WITH_ALLOCATOR(T) , gc_allocator<T>
23+ #define WITH_ALLOCATOR_PAIR(T, U) , std::hash<T>, std::equal_to<T>, gc_allocator<std::pair<const T, U>>
23 #define MANAGED_TYPE(T) T*
24 #define MANAGED_TYPE(T) T*
24 #define MAKE_MANAGED(T) new (GC) T
25 #define MAKE_MANAGED(T) new (GC) T
25− #define MAKE_MANAGED_FINALIZED(T) new (GC, [](void* p, void*){ static_cast<T*>(p)->~T(); }) T
26+ #define MAKE_MANAGED_FINALIZED(T) new (PointerFreeGC, [](void* p, void*){ static_cast<T*>(p)->~T(); }) T
26 #define IS_POINTER_TYPE(T) std::is_pointer<T>
27 #define IS_POINTER_TYPE(T) std::is_pointer<T>
27 #define POINTER_FROM_MEMBER(P) P
28 #define POINTER_FROM_MEMBER(P) P
28 #define INITIALIZE_GC() GC_INIT()
29 #define INITIALIZE_GC() GC_INIT()
29#else
30#else
30 #include <memory>
31 #include <memory>
31 #define WITH_ALLOCATOR(_)
32 #define WITH_ALLOCATOR(_)
33+ #define WITH_ALLOCATOR_PAIR(...)
32 #define MANAGED_TYPE(T) std::shared_ptr<T>
34 #define MANAGED_TYPE(T) std::shared_ptr<T>
33 #define MAKE_MANAGED(T) std::make_shared<T>
35 #define MAKE_MANAGED(T) std::make_shared<T>
34 #define MAKE_MANAGED_FINALIZED(T) MAKE_MANAGED(T)
36 #define MAKE_MANAGED_FINALIZED(T) MAKE_MANAGED(T)
pcc/support/Makefile+1−1
@@ -20,7 +20,7 @@ OUTPUT := output
20BIN := main
20BIN := main
21
21
22override PCCFLAGS += --comments
22override PCCFLAGS += --comments
23−override CXXFLAGS += -std=c++11 -Wno-logical-op-parentheses
23+override CXXFLAGS += -std=c++11 -Wno-logical-op-parentheses -Wno-missing-braces -Wmissing-field-initializers
24override LDFLAGS +=
24override LDFLAGS +=
25
25
26ifeq ($(GC),yes)
26ifeq ($(GC),yes)
src/Language/PureScript/CodeGen/Cpp.hs+18−24
@@ -57,7 +57,6 @@ import Language.PureScript.Traversals (sndM)
57
57
58import qualified Language.PureScript.Constants as C
58import qualified Language.PureScript.Constants as C
59import qualified Language.PureScript.Environment as E
59import qualified Language.PureScript.Environment as E
60−import Language.PureScript.Label (runLabel)
61import qualified Language.PureScript.Pretty.Cpp as P
60import qualified Language.PureScript.Pretty.Cpp as P
62import qualified Language.PureScript.Types as T
61import qualified Language.PureScript.Types as T
63
62
@@ -237,7 +236,7 @@ moduleToCpp otherOpts env (Module _ mn imps _ foreigns decls) = do
237 isAccessor Accessor {} = True
236 isAccessor Accessor {} = True
238 isAccessor _ = False
237 isAccessor _ = False
239 isGet :: Cpp -> Bool
238 isGet :: Cpp -> Bool
240− isGet (CppMapGet (CppSymbol _) (CppVar _)) = True
239+ isGet (CppDictGet (CppSymbol _) (CppVar _)) = True
241 isGet _ = False
240 isGet _ = False
242 classes =
241 classes =
243 zip
242 zip
@@ -370,24 +369,19 @@ moduleToCpp otherOpts env (Module _ mn imps _ foreigns decls) = do
370 valueToCpp (Literal _ (BooleanLiteral b)) = return (CppBooleanLiteral b)
369 valueToCpp (Literal _ (BooleanLiteral b)) = return (CppBooleanLiteral b)
371 valueToCpp (Literal _ (ArrayLiteral xs)) = CppArrayLiteral <$> mapM valueToCpp xs
370 valueToCpp (Literal _ (ArrayLiteral xs)) = CppArrayLiteral <$> mapM valueToCpp xs
372 valueToCpp (Literal _ (ObjectLiteral ps)) =
371 valueToCpp (Literal _ (ObjectLiteral ps)) =
373− CppMapLiteral Record <$>
372+ CppRecordLiteral <$>
374− mapM (sndM valueToCpp) ((\(k, v) -> (CppSymbol k, v)) <$> sortBy (compare `on` fst) ps)
373+ mapM (sndM valueToCpp) ((\(k, v) -> (CppStringLiteral k, v)) <$> ps)
375− valueToCpp (Accessor _ prop val) = CppMapGet <$> pure (CppSymbol prop) <*> valueToCpp val
374+ valueToCpp (Accessor (_, _, Just _, _) prop val) = CppRecordGet <$> pure prop <*> valueToCpp val
376− -- TODO: use a more efficient way of copying/updating the map?
375+ valueToCpp (Accessor _ prop val) = CppDictGet <$> pure (CppSymbol prop) <*> valueToCpp val
376+
377− valueToCpp (ObjectUpdate (_, _, Just ty, _) obj ps) = do
377+ valueToCpp (ObjectUpdate _ o ps) = do
378− obj' <- valueToCpp obj
378+ obj <- valueToCpp o
379− updatedFields <- mapM (sndM valueToCpp) ps
379+ updates <- mapM (sndM valueToCpp) ps
380− let origKeys = (allKeys ty) \\ (fst <$> updatedFields)
380+ obj' <- freshName
381− origFields = (\key -> (key, CppMapGet (CppSymbol key) obj')) <$> origKeys
381+ let copy = CppVariableIntroduction (obj', Just recordType) [] (Just obj)
382− return $
382+ assign (k, v) = CppAssignment (CppRecordGet k (CppVar obj')) v
383− CppMapLiteral Record $
383+ sts = copy : (assign <$> updates) ++ [CppReturn (CppVar obj')]
384− (\(k, v) -> (CppSymbol k, v)) <$> sortBy (compare `on` fst) (origFields ++ updatedFields)
384+ return $ CppApp (CppLambda [CaptureAll] [] Nothing (CppBlock sts)) []
385− where
386− allKeys :: T.Type -> [PSString]
387− allKeys (T.TypeApp (T.TypeConstructor _) r@(T.RCons {})) = runLabel . fst <$> (fst $ T.rowToList r)
388− allKeys (T.ForAll _ t _) = allKeys t
389− allKeys _ = error "Not a recognized row type"
390− valueToCpp (ObjectUpdate _ _ _) = error $ "Bad Type in object update!"
391 valueToCpp (Abs (_, _, ty, _) arg body) = do
385 valueToCpp (Abs (_, _, ty, _) arg body) = do
392 cpp <- valueToCpp body
386 cpp <- valueToCpp body
393 let cpp' = innerLambdas cpp
387 let cpp' = innerLambdas cpp
@@ -412,7 +406,7 @@ moduleToCpp otherOpts env (Module _ mn imps _ foreigns decls) = do
412 Var (_, _, _, Just IsNewtype) _ -> return (head args')
406 Var (_, _, _, Just IsNewtype) _ -> return (head args')
413 Var (_, _, _, Just IsTypeClassConstructor) (Qualified mn' (Ident classname)) ->
407 Var (_, _, _, Just IsTypeClassConstructor) (Qualified mn' (Ident classname)) ->
414 let Just (_, constraints, fns) = findClass (Qualified mn' (ProperName classname))
408 let Just (_, constraints, fns) = findClass (Qualified mn' (ProperName classname))
415− in return . CppMapLiteral Instance $
409+ in return . CppDictLiteral $
416 zip
410 zip
417 (CppSymbol . mkString <$> (sort $ superClassDictionaryNames constraints) ++ (fst <$> fns))
411 (CppSymbol . mkString <$> (sort $ superClassDictionaryNames constraints) ++ (fst <$> fns))
418 args'
412 args'
@@ -584,7 +578,7 @@ moduleToCpp otherOpts env (Module _ mn imps _ foreigns decls) = do
584 CppVariableIntroduction
578 CppVariableIntroduction
585 (propVar, Nothing)
579 (propVar, Nothing)
586 []
580 []
587− (Just $ CppMapGet (CppSymbol prop) (CppVar varName)) :
581+ (Just $ CppRecordGet prop (CppVar varName)) :
588 cpp
582 cpp
589 literalToBinderCpp varName done (ArrayLiteral bs) = do
583 literalToBinderCpp varName done (ArrayLiteral bs) = do
590 cpp <- go done 0 bs
584 cpp <- go done 0 bs
@@ -744,10 +738,10 @@ optIndexers :: [(Cpp, Cpp)] -> Cpp -> Cpp
744optIndexers classes = everywhereOnCpp dictIndexerToEnum
738optIndexers classes = everywhereOnCpp dictIndexerToEnum
745 where
739 where
746 dictIndexerToEnum :: Cpp -> Cpp
740 dictIndexerToEnum :: Cpp -> Cpp
747− dictIndexerToEnum (CppMapGet (CppSymbol prop) dict)
741+ dictIndexerToEnum (CppDictGet (CppSymbol prop) dict)
748 | Just cls <- lookup dict classes =
742 | Just cls <- lookup dict classes =
749 let index = CppAccessor (CppVar . safeName $ P.utf16Text prop) cls
743 let index = CppAccessor (CppVar . safeName $ P.utf16Text prop) cls
750− in CppMapGet index dict
744+ in CppDictGet index dict
751 dictIndexerToEnum cpp = cpp
745 dictIndexerToEnum cpp = cpp
752
746
753---------------------------------------------------------------------------------------------------
747---------------------------------------------------------------------------------------------------
src/Language/PureScript/CodeGen/Cpp/AST.hs+24−10
@@ -185,9 +185,13 @@ data Cpp
185 --
185 --
186 | CppIndexer Cpp Cpp
186 | CppIndexer Cpp Cpp
187 -- |
187 -- |
188− -- An object literal
188+ -- An instance dictionary literal
189 --
189 --
190− | CppMapLiteral MapType [(Cpp, Cpp)]
190+ | CppDictLiteral [(Cpp, Cpp)]
191+ -- |
192+ -- An record literal
193+ --
194+ | CppRecordLiteral [(Cpp, Cpp)]
191 -- |
195 -- |
192 -- An general property accessor expression (property, expr)
196 -- An general property accessor expression (property, expr)
193 --
197 --
@@ -205,14 +209,18 @@ data Cpp
205 --
209 --
206 | CppCast CppType Cpp
210 | CppCast CppType Cpp
207 -- |
211 -- |
208− -- Call to getter from templated map type
212+ -- Call to getter from templated dict type
209 --
213 --
210− | CppMapGet Cpp Cpp
214+ | CppDictGet Cpp Cpp
211 -- |
215 -- |
212 -- Call to getter from templated data type
216 -- Call to getter from templated data type
213 --
217 --
214 | CppDataGet Cpp Cpp
218 | CppDataGet Cpp Cpp
215 -- |
219 -- |
220+ -- Call to getter from record type
221+ --
222+ | CppRecordGet PSString Cpp
223+ -- |
216 -- Function application
224 -- Function application
217 --
225 --
218 | CppApp Cpp [Cpp]
226 | CppApp Cpp [Cpp]
@@ -315,13 +323,15 @@ everywhereOnCpp f = go
315 go (CppArrayLiteral cpp) = f (CppArrayLiteral (map go cpp))
323 go (CppArrayLiteral cpp) = f (CppArrayLiteral (map go cpp))
316 go (CppDataLiteral cpp) = f (CppDataLiteral (map go cpp))
324 go (CppDataLiteral cpp) = f (CppDataLiteral (map go cpp))
317 go (CppIndexer j1 j2) = f (CppIndexer (go j1) (go j2))
325 go (CppIndexer j1 j2) = f (CppIndexer (go j1) (go j2))
318− go (CppMapLiteral t cpps) = f (CppMapLiteral t (map (fmap go) cpps))
326+ go (CppDictLiteral cpps) = f (CppDictLiteral (map (fmap go) cpps))
327+ go (CppRecordLiteral cpps) = f (CppRecordLiteral (map (fmap go) cpps))
319 go (CppAccessor prop j) = f (CppAccessor (go prop) (go j))
328 go (CppAccessor prop j) = f (CppAccessor (go prop) (go j))
320 go (CppFunction name args rty qs j) = f (CppFunction name args rty qs (go j))
329 go (CppFunction name args rty qs j) = f (CppFunction name args rty qs (go j))
321 go (CppLambda cps args rty j) = f (CppLambda cps args rty (go j))
330 go (CppLambda cps args rty j) = f (CppLambda cps args rty (go j))
322 go (CppCast t cpp) = f (CppCast t (go cpp))
331 go (CppCast t cpp) = f (CppCast t (go cpp))
323− go (CppMapGet j1 j2) = f (CppMapGet (go j1) (go j2))
332+ go (CppDictGet j1 j2) = f (CppDictGet (go j1) (go j2))
324 go (CppDataGet j1 j2) = f (CppDataGet (go j1) (go j2))
333 go (CppDataGet j1 j2) = f (CppDataGet (go j1) (go j2))
334+ go (CppRecordGet k j) = f (CppRecordGet k (go j))
325 go (CppApp j cpp) = f (CppApp (go j) (map go cpp))
335 go (CppApp j cpp) = f (CppApp (go j) (map go cpp))
326 go (CppBlock cpp) = f (CppBlock (map go cpp))
336 go (CppBlock cpp) = f (CppBlock (map go cpp))
327 go (CppNamespace name cpp) = f (CppNamespace name (map go cpp))
337 go (CppNamespace name cpp) = f (CppNamespace name (map go cpp))
@@ -348,13 +358,15 @@ everywhereOnCppTopDownM f = f >=> go
348 go (CppArrayLiteral cpp) = CppArrayLiteral <$> traverse f' cpp
358 go (CppArrayLiteral cpp) = CppArrayLiteral <$> traverse f' cpp
349 go (CppDataLiteral cpp) = CppDataLiteral <$> traverse f' cpp
359 go (CppDataLiteral cpp) = CppDataLiteral <$> traverse f' cpp
350 go (CppIndexer j1 j2) = CppIndexer <$> f' j1 <*> f' j2
360 go (CppIndexer j1 j2) = CppIndexer <$> f' j1 <*> f' j2
351− go (CppMapLiteral t cpps) = CppMapLiteral t <$> traverse (pairM f' f') cpps
361+ go (CppDictLiteral cpps) = CppDictLiteral <$> traverse (pairM f' f') cpps
362+ go (CppRecordLiteral cpps) = CppRecordLiteral <$> traverse (pairM f' f') cpps
352 go (CppAccessor prop j) = CppAccessor prop <$> f' j
363 go (CppAccessor prop j) = CppAccessor prop <$> f' j
353 go (CppFunction name args rty qs j) = CppFunction name args rty qs <$> f' j
364 go (CppFunction name args rty qs j) = CppFunction name args rty qs <$> f' j
354 go (CppLambda cps args rty j) = CppLambda cps args rty <$> f' j
365 go (CppLambda cps args rty j) = CppLambda cps args rty <$> f' j
355 go (CppCast t cpp) = CppCast t <$> f' cpp
366 go (CppCast t cpp) = CppCast t <$> f' cpp
356− go (CppMapGet j1 j2) = CppMapGet <$> f' j1 <*> f' j2
367+ go (CppDictGet j1 j2) = CppDictGet <$> f' j1 <*> f' j2
357 go (CppDataGet j1 j2) = CppDataGet <$> f' j1 <*> f' j2
368 go (CppDataGet j1 j2) = CppDataGet <$> f' j1 <*> f' j2
369+ go (CppRecordGet k j) = CppRecordGet k <$> f' j
358 go (CppApp j cpp) = CppApp <$> f' j <*> traverse f' cpp
370 go (CppApp j cpp) = CppApp <$> f' j <*> traverse f' cpp
359 go (CppBlock cpp) = CppBlock <$> traverse f' cpp
371 go (CppBlock cpp) = CppBlock <$> traverse f' cpp
360 go (CppNamespace name cpp) = CppNamespace name <$> traverse f' cpp
372 go (CppNamespace name cpp) = CppNamespace name <$> traverse f' cpp
@@ -377,13 +389,15 @@ everythingOnCpp (<>) f = go
377 go j@(CppArrayLiteral cpp) = foldl (<>) (f j) (map go cpp)
389 go j@(CppArrayLiteral cpp) = foldl (<>) (f j) (map go cpp)
378 go j@(CppDataLiteral cpp) = foldl (<>) (f j) (map go cpp)
390 go j@(CppDataLiteral cpp) = foldl (<>) (f j) (map go cpp)
379 go j@(CppIndexer j1 j2) = f j <> go j1 <> go j2
391 go j@(CppIndexer j1 j2) = f j <> go j1 <> go j2
392+ go j@(CppDictLiteral cpps) = foldl (<>) (f j) ((map (go . fst) cpps) ++ (map (go . snd) cpps))
380− go j@(CppMapLiteral _ cpps) = foldl (<>) (f j) ((map (go . fst) cpps) ++ (map (go . snd) cpps))
393+ go j@(CppRecordLiteral cpps) = foldl (<>) (f j) ((map (go . fst) cpps) ++ (map (go . snd) cpps))
381 go j@(CppAccessor j1 j2) = f j <> go j1 <> go j2
394 go j@(CppAccessor j1 j2) = f j <> go j1 <> go j2
382 go j@(CppFunction _ _ _ _ j1) = f j <> go j1
395 go j@(CppFunction _ _ _ _ j1) = f j <> go j1
383 go j@(CppLambda _ _ _ j1) = f j <> go j1
396 go j@(CppLambda _ _ _ j1) = f j <> go j1
384 go j@(CppCast _ cpp) = f j <> go cpp
397 go j@(CppCast _ cpp) = f j <> go cpp
385− go j@(CppMapGet j1 j2) = f j <> go j1 <> go j2
398+ go j@(CppDictGet j1 j2) = f j <> go j1 <> go j2
386 go j@(CppDataGet j1 j2) = f j <> go j1 <> go j2
399 go j@(CppDataGet j1 j2) = f j <> go j1 <> go j2
400+ go j@(CppRecordGet _ j1) = f j <> go j1
387 go j@(CppApp j1 cpp) = foldl (<>) (f j <> go j1) (map go cpp)
401 go j@(CppApp j1 cpp) = foldl (<>) (f j <> go j1) (map go cpp)
388 go j@(CppBlock cpp) = foldl (<>) (f j) (map go cpp)
402 go j@(CppBlock cpp) = foldl (<>) (f j) (map go cpp)
389 go j@(CppNamespace _ cpp) = foldl (<>) (f j) (map go cpp)
403 go j@(CppNamespace _ cpp) = foldl (<>) (f j) (map go cpp)
src/Language/PureScript/CodeGen/Cpp/Common.hs+2−2
@@ -154,7 +154,6 @@ nameIsCppReserved name =
154 , "ctor"
154 , "ctor"
155 , "decltype"
155 , "decltype"
156 , "default"
156 , "default"
157− , "define_symbol"
158 , "delete"
157 , "delete"
159 , "do"
158 , "do"
160 , "double"
159 , "double"
@@ -213,7 +212,6 @@ nameIsCppReserved name =
213 , "string"
212 , "string"
214 , "struct"
213 , "struct"
215 , "switch"
214 , "switch"
216− , "symbol"
217 , "synchronized"
215 , "synchronized"
218 , "template"
216 , "template"
219 , "the_value"
217 , "the_value"
@@ -267,4 +265,6 @@ properNameIsCppReserved :: Text -> Bool
267properNameIsCppReserved name =
265properNameIsCppReserved name =
268 name `elem` [ "Private"
266 name `elem` [ "Private"
269 , "PureScript"
267 , "PureScript"
268+ , "SYM"
269+ , "DEFINE_SYMBOL"
270 ]
270 ]
src/Language/PureScript/CodeGen/Cpp/File.hs+3−3
@@ -54,7 +54,7 @@ toHeader = catMaybes . map go
54 -- Generate thunks for top-level values
54 -- Generate thunks for top-level values
55 go (CppVariableIntroduction (name, _) _ (Just cpp)) =
55 go (CppVariableIntroduction (name, _) _ (Just cpp)) =
56 case cpp of
56 case cpp of
57− CppMapLiteral Instance _ ->
57+ CppDictLiteral _ ->
58 Just $ CppFunction name [("", Just thunkMarkerType)] (Just $ Any [Const, Ref]) [] CppNoOp
58 Just $ CppFunction name [("", Just thunkMarkerType)] (Just $ Any [Const, Ref]) [] CppNoOp
59 _ -> Just $ CppVariableIntroduction (name, Just $ Any [Const]) [Extern] Nothing
59 _ -> Just $ CppVariableIntroduction (name, Just $ Any [Const]) [Extern] Nothing
60 go cpp@(CppStruct {}) = Just cpp
60 go cpp@(CppStruct {}) = Just cpp
@@ -119,7 +119,7 @@ toBody = catMaybes . map go
119 -- Generate thunks for top-level values
119 -- Generate thunks for top-level values
120 go (CppVariableIntroduction (name, _) _ (Just cpp)) =
120 go (CppVariableIntroduction (name, _) _ (Just cpp)) =
121 case cpp of
121 case cpp of
122− CppMapLiteral Instance _ ->
122+ CppDictLiteral _ ->
123 Just $ CppFunction name [("", Just thunkMarkerType)] (Just $ Any [Const, Ref]) [] block
123 Just $ CppFunction name [("", Just thunkMarkerType)] (Just $ Any [Const, Ref]) [] block
124 _ -> Just $ CppVariableIntroduction (name, Just $ Any [Const]) [] (Just lambda)
124 _ -> Just $ CppVariableIntroduction (name, Just $ Any [Const]) [] (Just lambda)
125 where
125 where
@@ -127,7 +127,7 @@ toBody = catMaybes . map go
127 block = CppBlock [val, CppReturn (CppVar "the_value")]
127 block = CppBlock [val, CppReturn (CppVar "the_value")]
128 lambda = CppLambda [] [("", Just $ thunkMarkerType)] (Just $ Any [Const, Ref]) block
128 lambda = CppLambda [] [("", Just $ thunkMarkerType)] (Just $ Any [Const, Ref]) block
129 addCaptures :: Cpp -> Cpp
129 addCaptures :: Cpp -> Cpp
130− addCaptures (CppMapLiteral t objs) = CppMapLiteral t (objlam <$> objs)
130+ addCaptures (CppDictLiteral objs) = CppDictLiteral (objlam <$> objs)
131 where
131 where
132 objlam :: (Cpp, Cpp) -> (Cpp, Cpp)
132 objlam :: (Cpp, Cpp) -> (Cpp, Cpp)
133 objlam (name', (CppLambda _ args rty body)) =
133 objlam (name', (CppLambda _ args rty body)) =
src/Language/PureScript/CodeGen/Cpp/Optimizer/Blocks.hs−1
@@ -25,7 +25,6 @@ import Data.Maybe
25
25
26import Language.PureScript.CodeGen.Cpp.AST
26import Language.PureScript.CodeGen.Cpp.AST
27import Language.PureScript.CodeGen.Cpp.Types
27import Language.PureScript.CodeGen.Cpp.Types
28−import qualified Language.PureScript.Constants as C
29
28
30-- |
29-- |
31-- Collapse blocks which appear nested directly below another block
30-- Collapse blocks which appear nested directly below another block
src/Language/PureScript/CodeGen/Cpp/Optimizer/Common.hs+2−1
@@ -65,7 +65,8 @@ targetVariable :: Cpp -> Text
65targetVariable (CppVar var) = var
65targetVariable (CppVar var) = var
66targetVariable (CppAccessor _ tgt) = targetVariable tgt
66targetVariable (CppAccessor _ tgt) = targetVariable tgt
67targetVariable (CppIndexer _ tgt) = targetVariable tgt
67targetVariable (CppIndexer _ tgt) = targetVariable tgt
68+targetVariable (CppDictGet _ tgt) = targetVariable tgt
68−targetVariable (CppMapGet _ tgt) = targetVariable tgt
69+targetVariable (CppRecordGet _ tgt) = targetVariable tgt
69targetVariable _ = error "Invalid argument to targetVariable"
70targetVariable _ = error "Invalid argument to targetVariable"
70
71
71isUpdated :: Text -> Cpp -> Bool
72isUpdated :: Text -> Cpp -> Bool
src/Language/PureScript/CodeGen/Cpp/Optimizer/Inliner.hs+1−1
@@ -50,7 +50,7 @@ shouldInline (CppStringLiteral _) = True
50shouldInline (CppBooleanLiteral _) = True
50shouldInline (CppBooleanLiteral _) = True
51shouldInline (CppAccessor _ val) = shouldInline val
51shouldInline (CppAccessor _ val) = shouldInline val
52shouldInline (CppIndexer index val) = shouldInline index && shouldInline val
52shouldInline (CppIndexer index val) = shouldInline index && shouldInline val
53−shouldInline (CppMapGet index val) = shouldInline index && shouldInline val
53+shouldInline (CppDictGet index val) = shouldInline index && shouldInline val
54shouldInline (CppDataGet index val) = shouldInline index && shouldInline val
54shouldInline (CppDataGet index val) = shouldInline index && shouldInline val
55shouldInline (CppCast _ val) = shouldInline val
55shouldInline (CppCast _ val) = shouldInline val
56shouldInline _ = False
56shouldInline _ = False
src/Language/PureScript/CodeGen/Cpp/Optimizer/MagicDo.hs+4−4
@@ -13,7 +13,7 @@
13-- and bind for the Eff monad, as well as some of its actions.
13-- and bind for the Eff monad, as well as some of its actions.
14--
14--
15-----------------------------------------------------------------------------
15-----------------------------------------------------------------------------
16−module Language.PureScript.CodeGen.Cpp.Optimizer.MagicDo (magicDo) where
16+module Language.PureScript.CodeGen.Cpp.Optimizer.MagicDo (magicDo, inlineST) where
17
17
18import Prelude.Compat
18import Prelude.Compat
19
19
@@ -26,7 +26,7 @@ import Language.PureScript.CodeGen.Cpp.Optimizer.Common
26import Language.PureScript.CodeGen.Cpp.Types
26import Language.PureScript.CodeGen.Cpp.Types
27import Language.PureScript.Options
27import Language.PureScript.Options
28import qualified Language.PureScript.Constants as C
28import qualified Language.PureScript.Constants as C
29−import Language.PureScript.PSString (mkString)
29+-- import Language.PureScript.PSString (mkString)
30
30
31magicDo :: Options -> Cpp -> Cpp
31magicDo :: Options -> Cpp -> Cpp
32magicDo opts | optionsNoMagicDo opts = id
32magicDo opts | optionsNoMagicDo opts = id
@@ -121,8 +121,8 @@ inlineST = everywhereOnCpp convertBlock
121 -- Convert a block in a safe way, preserving object wrappers of references,
121 -- Convert a block in a safe way, preserving object wrappers of references,
122 -- or in a more aggressive way, turning wrappers into local variables depending on the
122 -- or in a more aggressive way, turning wrappers into local variables depending on the
123 -- agg(ressive) parameter.
123 -- agg(ressive) parameter.
124− convert agg (CppApp f [arg]) | isSTFunc C.newSTRef f =
124+ -- convert agg (CppApp f [arg]) | isSTFunc C.newSTRef f =
125− CppLambda [CaptureAll] [] Nothing (CppBlock [CppReturn $ if agg then arg else CppMapLiteral Record [(CppSymbol $ mkString C.stRefValue, arg)]])
125+ -- CppLambda [CaptureAll] [] Nothing (CppBlock [CppReturn $ if agg then arg else CppMapLiteral Record [(CppSymbol $ mkString C.stRefValue, arg)]])
126 convert agg (CppApp (CppApp f [ref]) []) | isSTFunc C.readSTRef f =
126 convert agg (CppApp (CppApp f [ref]) []) | isSTFunc C.readSTRef f =
127 if agg then ref else CppAccessor (CppVar C.stRefValue) ref
127 if agg then ref else CppAccessor (CppVar C.stRefValue) ref
128 convert agg (CppApp (CppApp (CppApp f [ref]) [arg]) []) | isSTFunc C.writeSTRef f =
128 convert agg (CppApp (CppApp (CppApp f [ref]) [arg]) []) | isSTFunc C.writeSTRef f =
src/Language/PureScript/CodeGen/Cpp/Types.hs+10−13
@@ -66,12 +66,6 @@ data ValueQual
66data CaptureType = CaptureAll
66data CaptureType = CaptureAll
67 deriving (Show, Read, Eq)
67 deriving (Show, Read, Eq)
68
68
69−-- |
70−-- C++ object/map literal type
71−--
72−data MapType = Instance | Record
73− deriving (Show, Eq)
74−
75runType :: CppType -> Text
69runType :: CppType -> Text
76runType (Primitive t) = t
70runType (Primitive t) = t
77runType (Auto []) = "auto"
71runType (Auto []) = "auto"
@@ -116,12 +110,12 @@ charType = Primitive "char"
116voidType :: CppType
110voidType :: CppType
117voidType = Primitive "void"
111voidType = Primitive "void"
118
112
119−mapType :: Int -> CppType
113+dictType :: Int -> CppType
120−mapType = maptype
114+dictType = typ
121 where
115 where
122− maptype 0 = mapprim "unknown_size"
116+ typ 0 = prim "unknown_size"
123− maptype n = mapprim . pack $ show n
117+ typ n = prim . pack $ show n
124− mapprim s = Primitive $ "any::map<" <> s <> ">"
118+ prim s = Primitive $ "any::dict<" <> s <> ">"
125
119
126dataType :: Int -> CppType
120dataType :: Int -> CppType
127dataType n = Primitive $ "any::data<" <> pack (show n) <> ">"
121dataType n = Primitive $ "any::data<" <> pack (show n) <> ">"
@@ -129,11 +123,14 @@ dataType n = Primitive $ "any::data<" <> pack (show n) <> ">"
129arrayType :: CppType
123arrayType :: CppType
130arrayType = Primitive "any::array"
124arrayType = Primitive "any::array"
131
125
126+recordType :: CppType
127+recordType = Primitive "any::record"
128+
132thunkMarkerType :: CppType
129thunkMarkerType :: CppType
133thunkMarkerType = Primitive "any::as_thunk"
130thunkMarkerType = Primitive "any::as_thunk"
134
131
135−mapNS :: Text
132+dictNS :: Text
136−mapNS = "map"
133+dictNS = "dict"
137
134
138dataNS :: Text
135dataNS :: Text
139dataNS = "data"
136dataNS = "data"
src/Language/PureScript/Pretty/Cpp.hs+40−16
@@ -93,17 +93,21 @@ literals = mkPattern' match
93 match (CppBooleanLiteral True) = return "true"
93 match (CppBooleanLiteral True) = return "true"
94 match (CppBooleanLiteral False) = return "false"
94 match (CppBooleanLiteral False) = return "false"
95 match (CppArrayLiteral []) = return $ runType arrayType <> "{}"
95 match (CppArrayLiteral []) = return $ runType arrayType <> "{}"
96+ match (CppArrayLiteral [x]) =
97+ return $ runType arrayType <> "{ { " <> prettyPrintCpp1 x <> " } }"
96 match (CppArrayLiteral xs) = mconcat <$> sequence
98 match (CppArrayLiteral xs) = mconcat <$> sequence
97 [ return $ runType arrayType
99 [ return $ runType arrayType
98− , return "{{ "
100+ , return "{ "
99 , fmap (T.intercalate ", ") $ forM xs prettyPrintCpp'
101 , fmap (T.intercalate ", ") $ forM xs prettyPrintCpp'
100− , return " }}"
102+ , return " }"
101 ]
103 ]
104+ match (CppDataLiteral [x]) =
105+ return $ runType (dataType 1) <> "{ { " <> prettyPrintCpp1 x <> " } }"
102 match (CppDataLiteral xs) = mconcat <$> sequence
106 match (CppDataLiteral xs) = mconcat <$> sequence
103 [ return $ runType (dataType $ length xs)
107 [ return $ runType (dataType $ length xs)
104− , return "{{ "
108+ , return "{ "
105 , fmap (T.intercalate ", ") $ forM xs prettyPrintCpp'
109 , fmap (T.intercalate ", ") $ forM xs prettyPrintCpp'
106− , return " }}"
110+ , return " }"
107 ]
111 ]
108 match (CppEnum name ty es) = mconcat <$> sequence
112 match (CppEnum name ty es) = mconcat <$> sequence
109 [ return "enum"
113 [ return "enum"
@@ -113,10 +117,9 @@ literals = mkPattern' match
113 , return $ T.intercalate ", " es
117 , return $ T.intercalate ", " es
114 , return " }"
118 , return " }"
115 ]
119 ]
116− match (CppMapLiteral Record []) = return "nullptr"
120+ match (CppDictLiteral ps)
117− match (CppMapLiteral _ ps)
118 | length ps <= 8 = mconcat <$> sequence
121 | length ps <= 8 = mconcat <$> sequence
119− [ return $ mapNS <> "::make(\n"
122+ [ return $ dictNS <> "::make(\n"
120 , withIndent $ do
123 , withIndent $ do
121 cpps <-
124 cpps <-
122 forM ps $ \(key, value) -> do
125 forM ps $ \(key, value) -> do
@@ -129,8 +132,8 @@ literals = mkPattern' match
129 , currentIndent
132 , currentIndent
130 , return ")"
133 , return ")"
131 ]
134 ]
132− match (CppMapLiteral _ ps) = mconcat <$> sequence
135+ match (CppDictLiteral ps) = mconcat <$> sequence
133− [ return $ runType (mapType $ length ps + 1) <> "{{\n"
136+ [ return $ runType (dictType $ length ps + 1) <> "{\n"
134 , withIndent $ do
137 , withIndent $ do
135 let ps' = ps ++ [(CppVar "nullptr", CppVar "nullptr")]
138 let ps' = ps ++ [(CppVar "nullptr", CppVar "nullptr")]
136 cpps <-
139 cpps <-
@@ -142,7 +145,22 @@ literals = mkPattern' match
142 return $ T.intercalate ", \n" $ map (indentString <>) cpps
145 return $ T.intercalate ", \n" $ map (indentString <>) cpps
143 , return "\n"
146 , return "\n"
144 , currentIndent
147 , currentIndent
145− , return "}}"
148+ , return "}"
149+ ]
150+ match (CppRecordLiteral []) = return "nullptr"
151+ match (CppRecordLiteral ps) = mconcat <$> sequence
152+ [ return $ runType recordType <> "{\n"
153+ , withIndent $ do
154+ cpps <-
155+ forM ps $ \(key, value) -> do
156+ value' <- prettyPrintCpp' value
157+ key' <- prettyPrintCpp' key
158+ return $ "{ " <> key' <> ", " <> value' <> " }"
159+ indentString <- currentIndent
160+ return $ T.intercalate ", \n" $ map (indentString <>) cpps
161+ , return "\n"
162+ , currentIndent
163+ , return "}"
146 ]
164 ]
147 match (CppFunction name args rty qs ret) = mconcat <$> sequence
165 match (CppFunction name args rty qs ret) = mconcat <$> sequence
148 [ return . T.concat . fmap (<> " ") . filter (not . T.null) $ runValueQual <$> qs
166 [ return . T.concat . fmap (<> " ") . filter (not . T.null) $ runValueQual <$> qs
@@ -255,12 +273,18 @@ literals = mkPattern' match
255 vstr = prettyPrintCpp1 val
273 vstr = prettyPrintCpp1 val
256 val' | "(" `T.isInfixOf` vstr || "[" `T.isInfixOf` vstr = parensT vstr
274 val' | "(" `T.isInfixOf` vstr || "[" `T.isInfixOf` vstr = parensT vstr
257 | otherwise = vstr
275 | otherwise = vstr
258− match (CppMapGet i@(CppSymbol _) val) =
276+ match (CppDictGet i@(CppSymbol _) val) =
259− return . prettyPrintCpp1 $ CppApp (CppVar $ mapNS <> "::get") [i, val]
277+ return . prettyPrintCpp1 $ CppApp (CppVar $ dictNS <> "::get") [i, val]
260− match (CppMapGet i val) =
278+ match (CppDictGet i val) =
261− return . prettyPrintCpp1 $ CppApp (CppVar $ mapNS <> "::get" <> angles (prettyPrintCpp1 i)) [val]
279+ return . prettyPrintCpp1 $ CppApp (CppVar $ dictNS <> "::get" <> angles (prettyPrintCpp1 i)) [val]
262 match (CppDataGet i val) =
280 match (CppDataGet i val) =
263 return . prettyPrintCpp1 $ CppApp (CppVar $ dataNS <> "::get" <> angles (prettyPrintCpp1 i)) [val]
281 return . prettyPrintCpp1 $ CppApp (CppVar $ dataNS <> "::get" <> angles (prettyPrintCpp1 i)) [val]
282+ match (CppRecordGet k val) =
283+ return $ parens' (prettyPrintCpp1 val) <> "." <> prettyPrintCpp1 (CppApp (CppVar "at") [CppStringLiteral k])
284+ where
285+ parens' | CppVar{} <- val = id
286+ | CppAccessor{} <- val = id
287+ | otherwise = parensT
264 match (CppUnary op val) = return $ s <> "." <> f <> "()"
288 match (CppUnary op val) = return $ s <> "." <> f <> "()"
265 where
289 where
266 v = prettyPrintCpp1 val
290 v = prettyPrintCpp1 val
@@ -270,8 +294,8 @@ literals = mkPattern' match
270 | Empty <- op = "empty"
294 | Empty <- op = "empty"
271 | otherwise = error $ "Incorrect match on unary " <> show op
295 | otherwise = error $ "Incorrect match on unary " <> show op
272 match (CppVar ident) = return $ renderName ident
296 match (CppVar ident) = return $ renderName ident
273− match (CppSymbol ident) = return $ "symbol" <> parensT (safeSymbol ident)
297+ match (CppSymbol ident) = return $ "SYM" <> parensT (safeSymbol ident)
274− match (CppDefineSymbol ident) = return $ "define_symbol" <> parensT (safeSymbol ident)
298+ match (CppDefineSymbol ident) = return $ "DEFINE_SYMBOL" <> parensT (safeSymbol ident) <> "#"
275 match (CppApp v [CppNoOp]) = return (prettyPrintCpp1 v)
299 match (CppApp v [CppNoOp]) = return (prettyPrintCpp1 v)
276 match (CppVariableIntroduction (ident, typ) qs value) =
300 match (CppVariableIntroduction (ident, typ) qs value) =
277 mconcat <$> sequence
301 mconcat <$> sequence