git.iko.soy/rowtype-yoga/purescript-native
on golang help sign in
C++: fix some issues with map accessors (introduce 'get' fns)
6e80b80Andy Arvanitis
pcc/runtime/purescript.cc+1−12
@@ -86,19 +86,8 @@ auto any::unthunkVariant(const any& a) -> const any& {
86 return *variant;
86 return *variant;
87}
87}
88
88
89−static const any invalid_key(nullptr);
90−
91auto any::operator[](const symbol_t key) const -> const any& {
89auto any::operator[](const symbol_t key) const -> const any& {
92− // TODO: assumes at least one element -- safe assumption?
93− const auto& m = cast<map<unknown_size>>(*this);
90+ return get(key, cast<map<unknown_size>>(*this));
94− std::remove_reference<decltype(m)>::type::size_type i = 0;
95− do {
96− if (m[i].first == key) {
97− return m[i].second;
98− }
99− } while (m[++i].first != nullptr);
100− assert(false && "map key not found");
101− return invalid_key;
102}
91}
103
92
104auto any::operator[](const size_t rhs) const -> const any& {
93auto any::operator[](const size_t rhs) const -> const any& {
pcc/runtime/purescript.hh+23
@@ -454,6 +454,29 @@ inline auto cast(const any& a) ->
454 return a.rawPointer();
454 return a.rawPointer();
455}
455}
456
456
457+template <size_t N>
458+inline auto get(const any& a) -> const any& {
459+ return cast<any::map<N+1>>(a)[N].second;
460+}
461+
462+template <size_t N>
463+inline auto get(const symbol_t key, const any::map<N>& a) -> const any& {
464+ static_assert(N > 0, "map size must be greater than zero"); // TODO: not safe
465+ typename std::remove_reference<decltype(a)>::type::size_type i = 0;
466+ do {
467+ if (a[i].first == key) {
468+ return a[i].second;
469+ }
470+ } while (a[++i].first != nullptr);
471+ assert(false && "map key not found");
472+ static const any invalid_key(nullptr);
473+ return invalid_key;
474+}
475+
476+inline auto get(const symbol_t key, const any& a) -> const any& {
477+ return get(key, cast<any::map<unknown_size>>(a));
478+}
479+
457} // namespace PureScript
480} // namespace PureScript
458
481
459#undef WITH_ALLOCATOR
482#undef WITH_ALLOCATOR
src/Language/PureScript/CodeGen/Cpp.hs+10−12
@@ -210,7 +210,7 @@ moduleToCpp otherOpts env (Module _ mn imps _ foreigns decls) = do
210 [arg']
210 [arg']
211 rty
211 rty
212 (vqs ++
212 (vqs ++
213− if isIndexer body'
213+ if isGet body'
214 then [Inline]
214 then [Inline]
215 else [])
215 else [])
216 (returnBlock body')
216 (returnBlock body')
@@ -231,9 +231,9 @@ moduleToCpp otherOpts env (Module _ mn imps _ foreigns decls) = do
231 isAccessor :: Expr Ann -> Bool
231 isAccessor :: Expr Ann -> Bool
232 isAccessor Accessor {} = True
232 isAccessor Accessor {} = True
233 isAccessor _ = False
233 isAccessor _ = False
234− isIndexer :: Cpp -> Bool
234+ isGet :: Cpp -> Bool
235− isIndexer (CppIndexer (CppSymbol _) (CppVar _)) = True
235+ isGet (CppGet (CppSymbol _) (CppVar _)) = True
236− isIndexer _ = False
236+ isGet _ = False
237 classes =
237 classes =
238 zip
238 zip
239 (CppVar . fst <$> arg' : args')
239 (CppVar . fst <$> arg' : args')
@@ -441,13 +441,13 @@ moduleToCpp otherOpts env (Module _ mn imps _ foreigns decls) = do
441 valueToCpp (Literal _ (ObjectLiteral ps)) =
441 valueToCpp (Literal _ (ObjectLiteral ps)) =
442 CppMapLiteral Record <$>
442 CppMapLiteral Record <$>
443 mapM (sndM valueToCpp) ((\(k, v) -> (CppSymbol k, v)) <$> sortBy (compare `on` fst) ps)
443 mapM (sndM valueToCpp) ((\(k, v) -> (CppSymbol k, v)) <$> sortBy (compare `on` fst) ps)
444− valueToCpp (Accessor _ prop val) = CppIndexer <$> pure (CppSymbol prop) <*> valueToCpp val
444+ valueToCpp (Accessor _ prop val) = CppGet <$> pure (CppSymbol prop) <*> valueToCpp val
445 -- TODO: use a more efficient way of copying/updating the map?
445 -- TODO: use a more efficient way of copying/updating the map?
446 valueToCpp (ObjectUpdate (_, _, Just ty, _) obj ps) = do
446 valueToCpp (ObjectUpdate (_, _, Just ty, _) obj ps) = do
447 obj' <- valueToCpp obj
447 obj' <- valueToCpp obj
448 updatedFields <- mapM (sndM valueToCpp) ps
448 updatedFields <- mapM (sndM valueToCpp) ps
449 let origKeys = (allKeys ty) \\ (fst <$> updatedFields)
449 let origKeys = (allKeys ty) \\ (fst <$> updatedFields)
450− origFields = (\key -> (key, CppIndexer (CppSymbol key) obj')) <$> origKeys
450+ origFields = (\key -> (key, CppGet (CppSymbol key) obj')) <$> origKeys
451 return $
451 return $
452 CppMapLiteral Record $
452 CppMapLiteral Record $
453 (\(k, v) -> (CppSymbol k, v)) <$> sortBy (compare `on` fst) (origFields ++ updatedFields)
453 (\(k, v) -> (CppSymbol k, v)) <$> sortBy (compare `on` fst) (origFields ++ updatedFields)
@@ -675,7 +675,7 @@ moduleToCpp otherOpts env (Module _ mn imps _ foreigns decls) = do
675 CppVariableIntroduction
675 CppVariableIntroduction
676 (propVar, Nothing)
676 (propVar, Nothing)
677 []
677 []
678− (Just $ CppIndexer (CppSymbol prop) (CppVar varName)) :
678+ (Just $ CppGet (CppSymbol prop) (CppVar varName)) :
679 cpp
679 cpp
680 literalToBinderCpp varName done (ArrayLiteral bs) = do
680 literalToBinderCpp varName done (ArrayLiteral bs) = do
681 cpp <- go done 0 bs
681 cpp <- go done 0 bs
@@ -837,12 +837,10 @@ optIndexers :: [(Cpp, Cpp)] -> Cpp -> Cpp
837optIndexers classes = everywhereOnCpp dictIndexerToEnum
837optIndexers classes = everywhereOnCpp dictIndexerToEnum
838 where
838 where
839 dictIndexerToEnum :: Cpp -> Cpp
839 dictIndexerToEnum :: Cpp -> Cpp
840− dictIndexerToEnum (CppIndexer (CppSymbol prop) dict)
840+ dictIndexerToEnum (CppGet (CppSymbol prop) dict)
841 | Just cls <- lookup dict classes =
841 | Just cls <- lookup dict classes =
842− CppBinary
843− Dot
844− (CppIndexer (CppAccessor (CppVar . identToCpp $ Ident prop) cls) (CppCast (mapType 0) dict))
842+ let index = CppAccessor (CppVar . identToCpp $ Ident prop) cls
845− (CppVar "second")
843+ in CppGet index dict
846 dictIndexerToEnum cpp = cpp
844 dictIndexerToEnum cpp = cpp
847
845
848---------------------------------------------------------------------------------------------------
846---------------------------------------------------------------------------------------------------
src/Language/PureScript/CodeGen/Cpp/AST.hs+7
@@ -203,6 +203,10 @@ data Cpp
203 --
203 --
204 | CppCast CppType Cpp
204 | CppCast CppType Cpp
205 -- |
205 -- |
206+ -- Call to getter from templated type
207+ --
208+ | CppGet Cpp Cpp
209+ -- |
206 -- Function application
210 -- Function application
207 --
211 --
208 | CppApp Cpp [Cpp]
212 | CppApp Cpp [Cpp]
@@ -307,6 +311,7 @@ everywhereOnCpp f = go
307 go (CppFunction name args rty qs j) = f (CppFunction name args rty qs (go j))
311 go (CppFunction name args rty qs j) = f (CppFunction name args rty qs (go j))
308 go (CppLambda cps args rty j) = f (CppLambda cps args rty (go j))
312 go (CppLambda cps args rty j) = f (CppLambda cps args rty (go j))
309 go (CppCast t cpp) = f (CppCast t (go cpp))
313 go (CppCast t cpp) = f (CppCast t (go cpp))
314+ go (CppGet j1 j2) = f (CppGet (go j1) (go j2))
310 go (CppApp j cpp) = f (CppApp (go j) (map go cpp))
315 go (CppApp j cpp) = f (CppApp (go j) (map go cpp))
311 go (CppBlock cpp) = f (CppBlock (map go cpp))
316 go (CppBlock cpp) = f (CppBlock (map go cpp))
312 go (CppNamespace name cpp) = f (CppNamespace name (map go cpp))
317 go (CppNamespace name cpp) = f (CppNamespace name (map go cpp))
@@ -338,6 +343,7 @@ everywhereOnCppTopDownM f = f >=> go
338 go (CppFunction name args rty qs j) = CppFunction name args rty qs <$> f' j
343 go (CppFunction name args rty qs j) = CppFunction name args rty qs <$> f' j
339 go (CppLambda cps args rty j) = CppLambda cps args rty <$> f' j
344 go (CppLambda cps args rty j) = CppLambda cps args rty <$> f' j
340 go (CppCast t cpp) = CppCast t <$> f' cpp
345 go (CppCast t cpp) = CppCast t <$> f' cpp
346+ go (CppGet j1 j2) = CppGet <$> f' j1 <*> f' j2
341 go (CppApp j cpp) = CppApp <$> f' j <*> traverse f' cpp
347 go (CppApp j cpp) = CppApp <$> f' j <*> traverse f' cpp
342 go (CppBlock cpp) = CppBlock <$> traverse f' cpp
348 go (CppBlock cpp) = CppBlock <$> traverse f' cpp
343 go (CppNamespace name cpp) = CppNamespace name <$> traverse f' cpp
349 go (CppNamespace name cpp) = CppNamespace name <$> traverse f' cpp
@@ -365,6 +371,7 @@ everythingOnCpp (<>) f = go
365 go j@(CppFunction _ _ _ _ j1) = f j <> go j1
371 go j@(CppFunction _ _ _ _ j1) = f j <> go j1
366 go j@(CppLambda _ _ _ j1) = f j <> go j1
372 go j@(CppLambda _ _ _ j1) = f j <> go j1
367 go j@(CppCast _ cpp) = f j <> go cpp
373 go j@(CppCast _ cpp) = f j <> go cpp
374+ go j@(CppGet j1 j2) = f j <> go j1 <> go j2
368 go j@(CppApp j1 cpp) = foldl (<>) (f j <> go j1) (map go cpp)
375 go j@(CppApp j1 cpp) = foldl (<>) (f j <> go j1) (map go cpp)
369 go j@(CppBlock cpp) = foldl (<>) (f j) (map go cpp)
376 go j@(CppBlock cpp) = foldl (<>) (f j) (map go cpp)
370 go j@(CppNamespace _ cpp) = foldl (<>) (f j) (map go cpp)
377 go j@(CppNamespace _ cpp) = foldl (<>) (f j) (map go cpp)
src/Language/PureScript/CodeGen/Cpp/Common.hs+1
@@ -105,6 +105,7 @@ nameIsCppReserved name =
105 , "float"
105 , "float"
106 , "for"
106 , "for"
107 , "friend"
107 , "friend"
108+ , "get"
108 , "goto"
109 , "goto"
109 , "if"
110 , "if"
110 , "import"
111 , "import"
src/Language/PureScript/CodeGen/Cpp/Optimizer/Common.hs+1
@@ -63,6 +63,7 @@ targetVariable :: Cpp -> String
63targetVariable (CppVar var) = var
63targetVariable (CppVar var) = var
64targetVariable (CppAccessor _ tgt) = targetVariable tgt
64targetVariable (CppAccessor _ tgt) = targetVariable tgt
65targetVariable (CppIndexer _ tgt) = targetVariable tgt
65targetVariable (CppIndexer _ tgt) = targetVariable tgt
66+targetVariable (CppGet _ tgt) = targetVariable tgt
66targetVariable _ = error "Invalid argument to targetVariable"
67targetVariable _ = error "Invalid argument to targetVariable"
67
68
68isUpdated :: String -> Cpp -> Bool
69isUpdated :: String -> Cpp -> Bool
src/Language/PureScript/CodeGen/Cpp/Optimizer/Inliner.hs+1
@@ -46,6 +46,7 @@ shouldInline (CppStringLiteral _) = True
46shouldInline (CppBooleanLiteral _) = True
46shouldInline (CppBooleanLiteral _) = True
47shouldInline (CppAccessor _ val) = shouldInline val
47shouldInline (CppAccessor _ val) = shouldInline val
48shouldInline (CppIndexer index val) = shouldInline index && shouldInline val
48shouldInline (CppIndexer index val) = shouldInline index && shouldInline val
49+shouldInline (CppGet index val) = shouldInline index && shouldInline val
49shouldInline (CppCast _ val) = shouldInline val
50shouldInline (CppCast _ val) = shouldInline val
50shouldInline _ = False
51shouldInline _ = False
51
52
src/Language/PureScript/Pretty/Cpp.hs+5
@@ -40,6 +40,7 @@ import Language.PureScript.CodeGen.Cpp.Types
40import Language.PureScript.Comments
40import Language.PureScript.Comments
41import qualified Language.PureScript.Constants as C
41import qualified Language.PureScript.Constants as C
42import Numeric
42import Numeric
43+import Text.Printf (printf)
43
44
44-- import Debug.Trace
45-- import Debug.Trace
45---------------------------------------------------------------------------------------------------
46---------------------------------------------------------------------------------------------------
@@ -242,6 +243,10 @@ literals = mkPattern' match
242 vstr = prettyPrintCpp1 val
243 vstr = prettyPrintCpp1 val
243 val' | '(' `elem` vstr || '[' `elem` vstr = parens vstr
244 val' | '(' `elem` vstr || '[' `elem` vstr = parens vstr
244 | otherwise = vstr
245 | otherwise = vstr
246+ match (CppGet i@(CppSymbol _) val) =
247+ return $ printf "get(%s, %s)" (prettyPrintCpp1 i) (prettyPrintCpp1 val)
248+ match (CppGet i val) =
249+ return $ printf "get<%s>(%s)" (prettyPrintCpp1 i) (prettyPrintCpp1 val)
245 match (CppVar ident)
250 match (CppVar ident)
246 | ident == C.__unused = match (CppVar $ '$' : ident)
251 | ident == C.__unused = match (CppVar $ '$' : ident)
247 match (CppVar ident) = return ident
252 match (CppVar ident) = return ident