git.iko.soy/rowtype-yoga/purescript-native
on golang help sign in
C++: rework records
commit5be20b7bea88022ca8f87f7a320ca31be1ce866c authorAndy Arvanitis <andyarvanitis@gmail.com> dateSun 29 Jan 2017, 18:31 (10 years ago) parent03eead3
13 files changed+145−97
pcc/runtime/purescript.cc+9−1 pcc/runtime/purescript.hh+31−20 pcc/support/Makefile+1−1 src/Language/PureScript/CodeGen/Cpp.hs+18−24 src/Language/PureScript/CodeGen/Cpp/AST.hs+24−10 src/Language/PureScript/CodeGen/Cpp/Common.hs+2−2 src/Language/PureScript/CodeGen/Cpp/File.hs+3−3 src/Language/PureScript/CodeGen/Cpp/Optimizer/Blocks.hs−1 src/Language/PureScript/CodeGen/Cpp/Optimizer/Common.hs+2−1 src/Language/PureScript/CodeGen/Cpp/Optimizer/Inliner.hs+1−1 src/Language/PureScript/CodeGen/Cpp/Optimizer/MagicDo.hs+4−4 src/Language/PureScript/CodeGen/Cpp/Types.hs+10−13 src/Language/PureScript/Pretty/Cpp.hs+40−16
pcc/runtime/purescript.cc+9−1
@@ -88,6 +88,10 @@ any::operator const array&() const {
8888 RETURN_VALUE(Tag::Array, a, *)
8989}
9090
91+any::operator const record&() const {
92+ RETURN_VALUE(Tag::Record, r, *)
93+}
94+
9195auto any::extractPointer(IF_DEBUG(const any::Tag t)) const -> void* {
9296 RETURN_VALUE(t, POINTER_FROM_MEMBER(p),)
9397}
@@ -115,7 +119,7 @@ auto any::empty() const -> bool {
115119
116120auto any::contains(const Private::Symbol key) const -> bool {
117121 // 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);
119123 std::remove_reference<decltype(m)>::type::size_type i = 0;
120124 do {
121125 if (m[i].first == key) {
@@ -125,6 +129,10 @@ auto any::contains(const Private::Symbol key) const -> bool {
125129 return false;
126130}
127131
132+auto any::at(const std::string& key) const -> const any& {
133+ return static_cast<const record&>(*this).at(key);
134+}
135+
128136//-----------------------------------------------------------------------------
129137// Operator helper macros
130138//-----------------------------------------------------------------------------
pcc/runtime/purescript.hh+31−20
@@ -36,6 +36,7 @@
3636#include <string>
3737#include <array>
3838#include <deque>
39+#include <unordered_map>
3940#include <utility>
4041#include <stdexcept>
4142#include <iso646.h> // mostly for MS Visual Studio compiler
@@ -61,14 +62,14 @@ namespace Private {
6162 using Symbol = const SymbolGeneratorAnchor *;
6263}
6364
64−#define define_symbol(S) namespace PureScript { \
65+#define DEFINE_SYMBOL(S) namespace PureScript { \
6566 namespace Private { \
6667 namespace Symbols { \
6768 struct S_ ## S {}; \
6869 } \
6970 } \
7071 }
71−#define symbol(S) (&Private::SymbolGenerator<::PureScript::Private::Symbols::S_ ## S>::anchor)
72+#define SYM(S) (&Private::SymbolGenerator<::PureScript::Private::Symbols::S_ ## S>::anchor)
7273
7374constexpr bool undefined = false;
7475
@@ -93,6 +94,7 @@ class any {
9394 Map,
9495 Data,
9596 Array,
97+ Record,
9698 Closure,
9799 EffClosure,
98100 Pointer
@@ -106,15 +108,17 @@ class any {
106108 };
107109 static constexpr as_thunk unthunk = as_thunk{};
108110
109− using map_pair = std::pair<const Private::Symbol, const any>;
111+ using dict_pair = std::pair<const Private::Symbol, const any>;
110112
111113 template <size_t N>
112− using map = std::array<const map_pair, N>;
114+ using dict = std::array<const dict_pair, N>;
113115
114116 template <size_t N>
115117 using data = std::array<const any, N>;
116118
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(any)>;
121+
118122 using fn = auto (*)(const any&) -> any;
119123 using eff_fn = auto (*)() -> any;
120124 using thunk = auto (*)(const as_thunk) -> const any&;
@@ -164,6 +168,7 @@ class any {
164168 mutable void * v;
165169 mutable managed<string> s;
166170 mutable managed<array> a;
171+ mutable managed<record> r;
167172 mutable managed<Closure> l;
168173 mutable managed<EffClosure> k;
169174 mutable managed<void> p;
@@ -191,7 +196,7 @@ class any {
191196 any(managed<string>&& val) noexcept : tag(Tag::String), s(std::move(val)) {}
192197
193198 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))) {}
195200
196201 template <size_t N>
197202 any(data<N>&& val) noexcept : tag(Tag::Data), p(make_managed<data<N>>(std::move(val))) {}
@@ -199,6 +204,9 @@ class any {
199204 any(const array& val) : tag(Tag::Array), a(make_managed<array>(val)) {}
200205 any(array&& val) noexcept : tag(Tag::Array), a(make_managed<array>(std::move(val))) {}
201206
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+
202210 template <typename T>
203211 any(const T& val, typename std::enable_if<std::is_convertible<T,fn>::value>::type* = 0) noexcept
204212 : tag(Tag::Function), f(val) {}
@@ -269,6 +277,7 @@ class any {
269277
270278 case Tag::String: new (&s) managed<string>(move_if_rvalue<T>(other.s)); break;
271279 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;
272281 case Tag::Closure: new (&l) managed<Closure>(move_if_rvalue<T>(other.l)); break;
273282 case Tag::EffClosure: new (&k) managed<EffClosure>(move_if_rvalue<T>(other.k)); break;
274283 case Tag::Map:
@@ -283,6 +292,7 @@ class any {
283292 switch (tag) {
284293 case Tag::String: s.~managed<string>(); break;
285294 case Tag::Array: a.~managed<array>(); break;
295+ case Tag::Record: r.~managed<record>(); break;
286296 case Tag::Closure: l.~managed<Closure>(); break;
287297 case Tag::EffClosure: k.~managed<EffClosure>(); break;
288298 case Tag::Map:
@@ -337,9 +347,10 @@ class any {
337347 operator const string&() const;
338348 operator const char *() const;
339349 operator const array&() const;
350+ operator const record&() const;
340351
341352 auto operator[](const size_t) const -> const any&;
342−
353+ auto at(const std::string&) const -> const any&;
343354 auto size() const -> size_t;
344355 auto empty() const -> bool;
345356 auto contains(const Private::Symbol) const -> bool;
@@ -419,7 +430,7 @@ namespace Private {
419430 struct TagHelper {};
420431
421432 template <size_t N>
422− struct TagHelper<any::map<N>> {
433+ struct TagHelper<any::dict<N>> {
423434 static constexpr any::Tag tag = any::Tag::Map;
424435 };
425436
@@ -450,14 +461,16 @@ inline auto cast(const any& a) ->
450461template <typename T>
451462inline auto cast(const any& a) ->
452463 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 {
454466 return a;
455467}
456468
457469template <typename T,
458470 typename = typename std::enable_if<std::is_class<T>::value &&
459471 !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>
461474inline auto cast(const any& a) -> T& {
462475 return *static_cast<T*>(a.extractPointer(IF_DEBUG(Private::TagHelper<T>::tag)));
463476}
@@ -476,7 +489,7 @@ inline auto cast(const any& a) ->
476489 return a.rawPointer();
477490}
478491
479−namespace map {
492+namespace dict {
480493 template <size_t N, typename T>
481494 inline auto get(const T& a) ->
482495 typename std::enable_if<!std::is_same<any, T>::value, const any&>::type {
@@ -485,29 +498,29 @@ namespace map {
485498
486499 template <size_t N>
487500 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;
489502 }
490503
491504 template <size_t N>
492− inline auto get(const Private::Symbol key, const any::map<N>& a) -> const any& {
493− static_assert(N > 0, "map size must be greater than zero");
505+ inline auto get(const Private::Symbol key, const any::dict<N>& a) -> const any& {
506+ static_assert(N > 0, "dict size must be greater than zero");
494507 typename std::remove_reference<decltype(a)>::type::size_type i = 0;
495508 do {
496509 if (a[i].first == key) {
497510 return a[i].second;
498511 }
499512 } while (a[++i].first != nullptr);
500− assert(false && "map key not found");
513+ assert(false && "dict key not found");
501514 static const any invalid_key(nullptr);
502515 return invalid_key;
503516 }
504517
505518 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));
507520 }
508521
509− #define P(N) any::map_pair&& arg ## N
510− #define T(N) any::map<N+1>
522+ #define P(N) any::dict_pair&& arg ## N
523+ #define T(N) any::dict<N+1>
511524 #define E(N) std::forward<decltype(arg ## N)>(arg ## N)
512525 #define M(...) {{ __VA_ARGS__, { nullptr, nullptr } }}
513526
@@ -542,8 +555,6 @@ namespace map {
542555 #undef M
543556}
544557
545−namespace record = map;
546−
547558namespace data {
548559 template <size_t N, typename T>
549560 inline auto get(const T& a) ->
pcc/support/Makefile+1−1
@@ -20,7 +20,7 @@ OUTPUT := output
2020BIN := main
2121
2222override 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
2424override LDFLAGS +=
2525
2626ifeq ($(GC),yes)
src/Language/PureScript/CodeGen/Cpp.hs+18−24
@@ -57,7 +57,6 @@ import Language.PureScript.Traversals (sndM)
5757
5858import qualified Language.PureScript.Constants as C
5959import qualified Language.PureScript.Environment as E
60−import Language.PureScript.Label (runLabel)
6160import qualified Language.PureScript.Pretty.Cpp as P
6261import qualified Language.PureScript.Types as T
6362
@@ -237,7 +236,7 @@ moduleToCpp otherOpts env (Module _ mn imps _ foreigns decls) = do
237236 isAccessor Accessor {} = True
238237 isAccessor _ = False
239238 isGet :: Cpp -> Bool
240− isGet (CppMapGet (CppSymbol _) (CppVar _)) = True
239+ isGet (CppDictGet (CppSymbol _) (CppVar _)) = True
241240 isGet _ = False
242241 classes =
243242 zip
@@ -370,24 +369,19 @@ moduleToCpp otherOpts env (Module _ mn imps _ foreigns decls) = do
370369 valueToCpp (Literal _ (BooleanLiteral b)) = return (CppBooleanLiteral b)
371370 valueToCpp (Literal _ (ArrayLiteral xs)) = CppArrayLiteral <$> mapM valueToCpp xs
372371 valueToCpp (Literal _ (ObjectLiteral ps)) =
373− CppMapLiteral Record <$>
374− mapM (sndM valueToCpp) ((\(k, v) -> (CppSymbol k, v)) <$> sortBy (compare `on` fst) ps)
375− valueToCpp (Accessor _ prop val) = CppMapGet <$> pure (CppSymbol prop) <*> valueToCpp val
376− -- TODO: use a more efficient way of copying/updating the map?
377− valueToCpp (ObjectUpdate (_, _, Just ty, _) obj ps) = do
378− obj' <- valueToCpp obj
379− updatedFields <- mapM (sndM valueToCpp) ps
380− let origKeys = (allKeys ty) \\ (fst <$> updatedFields)
381− origFields = (\key -> (key, CppMapGet (CppSymbol key) obj')) <$> origKeys
382− return $
383− CppMapLiteral Record $
384− (\(k, v) -> (CppSymbol k, v)) <$> sortBy (compare `on` fst) (origFields ++ updatedFields)
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!"
372+ CppRecordLiteral <$>
373+ mapM (sndM valueToCpp) ((\(k, v) -> (CppStringLiteral k, v)) <$> ps)
374+ valueToCpp (Accessor (_, _, Just _, _) prop val) = CppRecordGet <$> pure prop <*> valueToCpp val
375+ valueToCpp (Accessor _ prop val) = CppDictGet <$> pure (CppSymbol prop) <*> valueToCpp val
376+
377+ valueToCpp (ObjectUpdate _ o ps) = do
378+ obj <- valueToCpp o
379+ updates <- mapM (sndM valueToCpp) ps
380+ obj' <- freshName
381+ let copy = CppVariableIntroduction (obj', Just recordType) [] (Just obj)
382+ assign (k, v) = CppAssignment (CppRecordGet k (CppVar obj')) v
383+ sts = copy : (assign <$> updates) ++ [CppReturn (CppVar obj')]
384+ return $ CppApp (CppLambda [CaptureAll] [] Nothing (CppBlock sts)) []
391385 valueToCpp (Abs (_, _, ty, _) arg body) = do
392386 cpp <- valueToCpp body
393387 let cpp' = innerLambdas cpp
@@ -412,7 +406,7 @@ moduleToCpp otherOpts env (Module _ mn imps _ foreigns decls) = do
412406 Var (_, _, _, Just IsNewtype) _ -> return (head args')
413407 Var (_, _, _, Just IsTypeClassConstructor) (Qualified mn' (Ident classname)) ->
414408 let Just (_, constraints, fns) = findClass (Qualified mn' (ProperName classname))
415− in return . CppMapLiteral Instance $
409+ in return . CppDictLiteral $
416410 zip
417411 (CppSymbol . mkString <$> (sort $ superClassDictionaryNames constraints) ++ (fst <$> fns))
418412 args'
@@ -584,7 +578,7 @@ moduleToCpp otherOpts env (Module _ mn imps _ foreigns decls) = do
584578 CppVariableIntroduction
585579 (propVar, Nothing)
586580 []
587− (Just $ CppMapGet (CppSymbol prop) (CppVar varName)) :
581+ (Just $ CppRecordGet prop (CppVar varName)) :
588582 cpp
589583 literalToBinderCpp varName done (ArrayLiteral bs) = do
590584 cpp <- go done 0 bs
@@ -744,10 +738,10 @@ optIndexers :: [(Cpp, Cpp)] -> Cpp -> Cpp
744738optIndexers classes = everywhereOnCpp dictIndexerToEnum
745739 where
746740 dictIndexerToEnum :: Cpp -> Cpp
747− dictIndexerToEnum (CppMapGet (CppSymbol prop) dict)
741+ dictIndexerToEnum (CppDictGet (CppSymbol prop) dict)
748742 | Just cls <- lookup dict classes =
749743 let index = CppAccessor (CppVar . safeName $ P.utf16Text prop) cls
750− in CppMapGet index dict
744+ in CppDictGet index dict
751745 dictIndexerToEnum cpp = cpp
752746
753747---------------------------------------------------------------------------------------------------
src/Language/PureScript/CodeGen/Cpp/AST.hs+24−10
@@ -185,9 +185,13 @@ data Cpp
185185 --
186186 | CppIndexer Cpp Cpp
187187 -- |
188− -- An object literal
188+ -- An instance dictionary literal
189189 --
190− | CppMapLiteral MapType [(Cpp, Cpp)]
190+ | CppDictLiteral [(Cpp, Cpp)]
191+ -- |
192+ -- An record literal
193+ --
194+ | CppRecordLiteral [(Cpp, Cpp)]
191195 -- |
192196 -- An general property accessor expression (property, expr)
193197 --
@@ -205,14 +209,18 @@ data Cpp
205209 --
206210 | CppCast CppType Cpp
207211 -- |
208− -- Call to getter from templated map type
212+ -- Call to getter from templated dict type
209213 --
210− | CppMapGet Cpp Cpp
214+ | CppDictGet Cpp Cpp
211215 -- |
212216 -- Call to getter from templated data type
213217 --
214218 | CppDataGet Cpp Cpp
215219 -- |
220+ -- Call to getter from record type
221+ --
222+ | CppRecordGet PSString Cpp
223+ -- |
216224 -- Function application
217225 --
218226 | CppApp Cpp [Cpp]
@@ -315,13 +323,15 @@ everywhereOnCpp f = go
315323 go (CppArrayLiteral cpp) = f (CppArrayLiteral (map go cpp))
316324 go (CppDataLiteral cpp) = f (CppDataLiteral (map go cpp))
317325 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))
319328 go (CppAccessor prop j) = f (CppAccessor (go prop) (go j))
320329 go (CppFunction name args rty qs j) = f (CppFunction name args rty qs (go j))
321330 go (CppLambda cps args rty j) = f (CppLambda cps args rty (go j))
322331 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))
324333 go (CppDataGet j1 j2) = f (CppDataGet (go j1) (go j2))
334+ go (CppRecordGet k j) = f (CppRecordGet k (go j))
325335 go (CppApp j cpp) = f (CppApp (go j) (map go cpp))
326336 go (CppBlock cpp) = f (CppBlock (map go cpp))
327337 go (CppNamespace name cpp) = f (CppNamespace name (map go cpp))
@@ -348,13 +358,15 @@ everywhereOnCppTopDownM f = f >=> go
348358 go (CppArrayLiteral cpp) = CppArrayLiteral <$> traverse f' cpp
349359 go (CppDataLiteral cpp) = CppDataLiteral <$> traverse f' cpp
350360 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
352363 go (CppAccessor prop j) = CppAccessor prop <$> f' j
353364 go (CppFunction name args rty qs j) = CppFunction name args rty qs <$> f' j
354365 go (CppLambda cps args rty j) = CppLambda cps args rty <$> f' j
355366 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
357368 go (CppDataGet j1 j2) = CppDataGet <$> f' j1 <*> f' j2
369+ go (CppRecordGet k j) = CppRecordGet k <$> f' j
358370 go (CppApp j cpp) = CppApp <$> f' j <*> traverse f' cpp
359371 go (CppBlock cpp) = CppBlock <$> traverse f' cpp
360372 go (CppNamespace name cpp) = CppNamespace name <$> traverse f' cpp
@@ -377,13 +389,15 @@ everythingOnCpp (<>) f = go
377389 go j@(CppArrayLiteral cpp) = foldl (<>) (f j) (map go cpp)
378390 go j@(CppDataLiteral cpp) = foldl (<>) (f j) (map go cpp)
379391 go j@(CppIndexer j1 j2) = f j <> go j1 <> go j2
380− go j@(CppMapLiteral _ cpps) = foldl (<>) (f j) ((map (go . fst) cpps) ++ (map (go . snd) cpps))
392+ go j@(CppDictLiteral 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))
381394 go j@(CppAccessor j1 j2) = f j <> go j1 <> go j2
382395 go j@(CppFunction _ _ _ _ j1) = f j <> go j1
383396 go j@(CppLambda _ _ _ j1) = f j <> go j1
384397 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
386399 go j@(CppDataGet j1 j2) = f j <> go j1 <> go j2
400+ go j@(CppRecordGet _ j1) = f j <> go j1
387401 go j@(CppApp j1 cpp) = foldl (<>) (f j <> go j1) (map go cpp)
388402 go j@(CppBlock cpp) = foldl (<>) (f j) (map go cpp)
389403 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 =
154154 , "ctor"
155155 , "decltype"
156156 , "default"
157− , "define_symbol"
158157 , "delete"
159158 , "do"
160159 , "double"
@@ -213,7 +212,6 @@ nameIsCppReserved name =
213212 , "string"
214213 , "struct"
215214 , "switch"
216− , "symbol"
217215 , "synchronized"
218216 , "template"
219217 , "the_value"
@@ -267,4 +265,6 @@ properNameIsCppReserved :: Text -> Bool
267265properNameIsCppReserved name =
268266 name `elem` [ "Private"
269267 , "PureScript"
268+ , "SYM"
269+ , "DEFINE_SYMBOL"
270270 ]
src/Language/PureScript/CodeGen/Cpp/File.hs+3−3
@@ -54,7 +54,7 @@ toHeader = catMaybes . map go
5454 -- Generate thunks for top-level values
5555 go (CppVariableIntroduction (name, _) _ (Just cpp)) =
5656 case cpp of
57− CppMapLiteral Instance _ ->
57+ CppDictLiteral _ ->
5858 Just $ CppFunction name [("", Just thunkMarkerType)] (Just $ Any [Const, Ref]) [] CppNoOp
5959 _ -> Just $ CppVariableIntroduction (name, Just $ Any [Const]) [Extern] Nothing
6060 go cpp@(CppStruct {}) = Just cpp
@@ -119,7 +119,7 @@ toBody = catMaybes . map go
119119 -- Generate thunks for top-level values
120120 go (CppVariableIntroduction (name, _) _ (Just cpp)) =
121121 case cpp of
122− CppMapLiteral Instance _ ->
122+ CppDictLiteral _ ->
123123 Just $ CppFunction name [("", Just thunkMarkerType)] (Just $ Any [Const, Ref]) [] block
124124 _ -> Just $ CppVariableIntroduction (name, Just $ Any [Const]) [] (Just lambda)
125125 where
@@ -127,7 +127,7 @@ toBody = catMaybes . map go
127127 block = CppBlock [val, CppReturn (CppVar "the_value")]
128128 lambda = CppLambda [] [("", Just $ thunkMarkerType)] (Just $ Any [Const, Ref]) block
129129 addCaptures :: Cpp -> Cpp
130− addCaptures (CppMapLiteral t objs) = CppMapLiteral t (objlam <$> objs)
130+ addCaptures (CppDictLiteral objs) = CppDictLiteral (objlam <$> objs)
131131 where
132132 objlam :: (Cpp, Cpp) -> (Cpp, Cpp)
133133 objlam (name', (CppLambda _ args rty body)) =
src/Language/PureScript/CodeGen/Cpp/Optimizer/Blocks.hs−1
@@ -25,7 +25,6 @@ import Data.Maybe
2525
2626import Language.PureScript.CodeGen.Cpp.AST
2727import Language.PureScript.CodeGen.Cpp.Types
28−import qualified Language.PureScript.Constants as C
2928
3029-- |
3130-- 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
6565targetVariable (CppVar var) = var
6666targetVariable (CppAccessor _ tgt) = targetVariable tgt
6767targetVariable (CppIndexer _ tgt) = targetVariable tgt
68−targetVariable (CppMapGet _ tgt) = targetVariable tgt
68+targetVariable (CppDictGet _ tgt) = targetVariable tgt
69+targetVariable (CppRecordGet _ tgt) = targetVariable tgt
6970targetVariable _ = error "Invalid argument to targetVariable"
7071
7172isUpdated :: Text -> Cpp -> Bool
src/Language/PureScript/CodeGen/Cpp/Optimizer/Inliner.hs+1−1
@@ -50,7 +50,7 @@ shouldInline (CppStringLiteral _) = True
5050shouldInline (CppBooleanLiteral _) = True
5151shouldInline (CppAccessor _ val) = shouldInline val
5252shouldInline (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
5454shouldInline (CppDataGet index val) = shouldInline index && shouldInline val
5555shouldInline (CppCast _ val) = shouldInline val
5656shouldInline _ = False
src/Language/PureScript/CodeGen/Cpp/Optimizer/MagicDo.hs+4−4
@@ -13,7 +13,7 @@
1313-- and bind for the Eff monad, as well as some of its actions.
1414--
1515-----------------------------------------------------------------------------
16−module Language.PureScript.CodeGen.Cpp.Optimizer.MagicDo (magicDo) where
16+module Language.PureScript.CodeGen.Cpp.Optimizer.MagicDo (magicDo, inlineST) where
1717
1818import Prelude.Compat
1919
@@ -26,7 +26,7 @@ import Language.PureScript.CodeGen.Cpp.Optimizer.Common
2626import Language.PureScript.CodeGen.Cpp.Types
2727import Language.PureScript.Options
2828import qualified Language.PureScript.Constants as C
29−import Language.PureScript.PSString (mkString)
29+-- import Language.PureScript.PSString (mkString)
3030
3131magicDo :: Options -> Cpp -> Cpp
3232magicDo opts | optionsNoMagicDo opts = id
@@ -121,8 +121,8 @@ inlineST = everywhereOnCpp convertBlock
121121 -- Convert a block in a safe way, preserving object wrappers of references,
122122 -- or in a more aggressive way, turning wrappers into local variables depending on the
123123 -- agg(ressive) parameter.
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)]])
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)]])
126126 convert agg (CppApp (CppApp f [ref]) []) | isSTFunc C.readSTRef f =
127127 if agg then ref else CppAccessor (CppVar C.stRefValue) ref
128128 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
6666data CaptureType = CaptureAll
6767 deriving (Show, Read, Eq)
6868
69−-- |
70−-- C++ object/map literal type
71−--
72−data MapType = Instance | Record
73− deriving (Show, Eq)
74−
7569runType :: CppType -> Text
7670runType (Primitive t) = t
7771runType (Auto []) = "auto"
@@ -116,12 +110,12 @@ charType = Primitive "char"
116110voidType :: CppType
117111voidType = Primitive "void"
118112
119−mapType :: Int -> CppType
120−mapType = maptype
113+dictType :: Int -> CppType
114+dictType = typ
121115 where
122− maptype 0 = mapprim "unknown_size"
123− maptype n = mapprim . pack $ show n
124− mapprim s = Primitive $ "any::map<" <> s <> ">"
116+ typ 0 = prim "unknown_size"
117+ typ n = prim . pack $ show n
118+ prim s = Primitive $ "any::dict<" <> s <> ">"
125119
126120dataType :: Int -> CppType
127121dataType n = Primitive $ "any::data<" <> pack (show n) <> ">"
@@ -129,11 +123,14 @@ dataType n = Primitive $ "any::data<" <> pack (show n) <> ">"
129123arrayType :: CppType
130124arrayType = Primitive "any::array"
131125
126+recordType :: CppType
127+recordType = Primitive "any::record"
128+
132129thunkMarkerType :: CppType
133130thunkMarkerType = Primitive "any::as_thunk"
134131
135−mapNS :: Text
136−mapNS = "map"
132+dictNS :: Text
133+dictNS = "dict"
137134
138135dataNS :: Text
139136dataNS = "data"
src/Language/PureScript/Pretty/Cpp.hs+40−16
@@ -93,17 +93,21 @@ literals = mkPattern' match
9393 match (CppBooleanLiteral True) = return "true"
9494 match (CppBooleanLiteral False) = return "false"
9595 match (CppArrayLiteral []) = return $ runType arrayType <> "{}"
96+ match (CppArrayLiteral [x]) =
97+ return $ runType arrayType <> "{ { " <> prettyPrintCpp1 x <> " } }"
9698 match (CppArrayLiteral xs) = mconcat <$> sequence
9799 [ return $ runType arrayType
98− , return "{{ "
100+ , return "{ "
99101 , fmap (T.intercalate ", ") $ forM xs prettyPrintCpp'
100− , return " }}"
102+ , return " }"
101103 ]
104+ match (CppDataLiteral [x]) =
105+ return $ runType (dataType 1) <> "{ { " <> prettyPrintCpp1 x <> " } }"
102106 match (CppDataLiteral xs) = mconcat <$> sequence
103107 [ return $ runType (dataType $ length xs)
104− , return "{{ "
108+ , return "{ "
105109 , fmap (T.intercalate ", ") $ forM xs prettyPrintCpp'
106− , return " }}"
110+ , return " }"
107111 ]
108112 match (CppEnum name ty es) = mconcat <$> sequence
109113 [ return "enum"
@@ -113,10 +117,9 @@ literals = mkPattern' match
113117 , return $ T.intercalate ", " es
114118 , return " }"
115119 ]
116− match (CppMapLiteral Record []) = return "nullptr"
117− match (CppMapLiteral _ ps)
120+ match (CppDictLiteral ps)
118121 | length ps <= 8 = mconcat <$> sequence
119− [ return $ mapNS <> "::make(\n"
122+ [ return $ dictNS <> "::make(\n"
120123 , withIndent $ do
121124 cpps <-
122125 forM ps $ \(key, value) -> do
@@ -129,8 +132,8 @@ literals = mkPattern' match
129132 , currentIndent
130133 , return ")"
131134 ]
132− match (CppMapLiteral _ ps) = mconcat <$> sequence
133− [ return $ runType (mapType $ length ps + 1) <> "{{\n"
135+ match (CppDictLiteral ps) = mconcat <$> sequence
136+ [ return $ runType (dictType $ length ps + 1) <> "{\n"
134137 , withIndent $ do
135138 let ps' = ps ++ [(CppVar "nullptr", CppVar "nullptr")]
136139 cpps <-
@@ -142,7 +145,22 @@ literals = mkPattern' match
142145 return $ T.intercalate ", \n" $ map (indentString <>) cpps
143146 , return "\n"
144147 , 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 "}"
146164 ]
147165 match (CppFunction name args rty qs ret) = mconcat <$> sequence
148166 [ return . T.concat . fmap (<> " ") . filter (not . T.null) $ runValueQual <$> qs
@@ -255,12 +273,18 @@ literals = mkPattern' match
255273 vstr = prettyPrintCpp1 val
256274 val' | "(" `T.isInfixOf` vstr || "[" `T.isInfixOf` vstr = parensT vstr
257275 | otherwise = vstr
258− match (CppMapGet i@(CppSymbol _) val) =
259− return . prettyPrintCpp1 $ CppApp (CppVar $ mapNS <> "::get") [i, val]
260− match (CppMapGet i val) =
261− return . prettyPrintCpp1 $ CppApp (CppVar $ mapNS <> "::get" <> angles (prettyPrintCpp1 i)) [val]
276+ match (CppDictGet i@(CppSymbol _) val) =
277+ return . prettyPrintCpp1 $ CppApp (CppVar $ dictNS <> "::get") [i, val]
278+ match (CppDictGet i val) =
279+ return . prettyPrintCpp1 $ CppApp (CppVar $ dictNS <> "::get" <> angles (prettyPrintCpp1 i)) [val]
262280 match (CppDataGet i val) =
263281 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
264288 match (CppUnary op val) = return $ s <> "." <> f <> "()"
265289 where
266290 v = prettyPrintCpp1 val
@@ -270,8 +294,8 @@ literals = mkPattern' match
270294 | Empty <- op = "empty"
271295 | otherwise = error $ "Incorrect match on unary " <> show op
272296 match (CppVar ident) = return $ renderName ident
273− match (CppSymbol ident) = return $ "symbol" <> parensT (safeSymbol ident)
274− match (CppDefineSymbol ident) = return $ "define_symbol" <> parensT (safeSymbol ident)
297+ match (CppSymbol ident) = return $ "SYM" <> parensT (safeSymbol ident)
298+ match (CppDefineSymbol ident) = return $ "DEFINE_SYMBOL" <> parensT (safeSymbol ident) <> "#"
275299 match (CppApp v [CppNoOp]) = return (prettyPrintCpp1 v)
276300 match (CppVariableIntroduction (ident, typ) qs value) =
277301 mconcat <$> sequence