git.iko.soy/rowtype-yoga/purescript-native
on golang help sign in
C++: fix some issues with map accessors (introduce 'get' fns)
commit6e80b809589ac7b26afdd11c7bf275b2cb8fc90d authorAndy Arvanitis <andyarvanitis@gmail.com> dateWed 14 Dec 2016, 19:29 (10 years ago) parent149c8ce
8 files changed+49−24
pcc/runtime/purescript.cc+1−12 pcc/runtime/purescript.hh+23 src/Language/PureScript/CodeGen/Cpp.hs+10−12 src/Language/PureScript/CodeGen/Cpp/AST.hs+7 src/Language/PureScript/CodeGen/Cpp/Common.hs+1 src/Language/PureScript/CodeGen/Cpp/Optimizer/Common.hs+1 src/Language/PureScript/CodeGen/Cpp/Optimizer/Inliner.hs+1 src/Language/PureScript/Pretty/Cpp.hs+5
pcc/runtime/purescript.cc+1−12
@@ -86,19 +86,8 @@ auto any::unthunkVariant(const any& a) -> const any& {
8686 return *variant;
8787}
8888
89−static const any invalid_key(nullptr);
90−
9189auto 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);
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;
90+ return get(key, cast<map<unknown_size>>(*this));
10291}
10392
10493auto any::operator[](const size_t rhs) const -> const any& {
pcc/runtime/purescript.hh+23
@@ -454,6 +454,29 @@ inline auto cast(const any& a) ->
454454 return a.rawPointer();
455455}
456456
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+
457480} // namespace PureScript
458481
459482#undef WITH_ALLOCATOR
src/Language/PureScript/CodeGen/Cpp.hs+10−12
@@ -210,7 +210,7 @@ moduleToCpp otherOpts env (Module _ mn imps _ foreigns decls) = do
210210 [arg']
211211 rty
212212 (vqs ++
213− if isIndexer body'
213+ if isGet body'
214214 then [Inline]
215215 else [])
216216 (returnBlock body')
@@ -231,9 +231,9 @@ moduleToCpp otherOpts env (Module _ mn imps _ foreigns decls) = do
231231 isAccessor :: Expr Ann -> Bool
232232 isAccessor Accessor {} = True
233233 isAccessor _ = False
234− isIndexer :: Cpp -> Bool
235− isIndexer (CppIndexer (CppSymbol _) (CppVar _)) = True
236− isIndexer _ = False
234+ isGet :: Cpp -> Bool
235+ isGet (CppGet (CppSymbol _) (CppVar _)) = True
236+ isGet _ = False
237237 classes =
238238 zip
239239 (CppVar . fst <$> arg' : args')
@@ -441,13 +441,13 @@ moduleToCpp otherOpts env (Module _ mn imps _ foreigns decls) = do
441441 valueToCpp (Literal _ (ObjectLiteral ps)) =
442442 CppMapLiteral Record <$>
443443 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
445445 -- TODO: use a more efficient way of copying/updating the map?
446446 valueToCpp (ObjectUpdate (_, _, Just ty, _) obj ps) = do
447447 obj' <- valueToCpp obj
448448 updatedFields <- mapM (sndM valueToCpp) ps
449449 let origKeys = (allKeys ty) \\ (fst <$> updatedFields)
450− origFields = (\key -> (key, CppIndexer (CppSymbol key) obj')) <$> origKeys
450+ origFields = (\key -> (key, CppGet (CppSymbol key) obj')) <$> origKeys
451451 return $
452452 CppMapLiteral Record $
453453 (\(k, v) -> (CppSymbol k, v)) <$> sortBy (compare `on` fst) (origFields ++ updatedFields)
@@ -675,7 +675,7 @@ moduleToCpp otherOpts env (Module _ mn imps _ foreigns decls) = do
675675 CppVariableIntroduction
676676 (propVar, Nothing)
677677 []
678− (Just $ CppIndexer (CppSymbol prop) (CppVar varName)) :
678+ (Just $ CppGet (CppSymbol prop) (CppVar varName)) :
679679 cpp
680680 literalToBinderCpp varName done (ArrayLiteral bs) = do
681681 cpp <- go done 0 bs
@@ -837,12 +837,10 @@ optIndexers :: [(Cpp, Cpp)] -> Cpp -> Cpp
837837optIndexers classes = everywhereOnCpp dictIndexerToEnum
838838 where
839839 dictIndexerToEnum :: Cpp -> Cpp
840− dictIndexerToEnum (CppIndexer (CppSymbol prop) dict)
840+ dictIndexerToEnum (CppGet (CppSymbol prop) dict)
841841 | Just cls <- lookup dict classes =
842− CppBinary
843− Dot
844− (CppIndexer (CppAccessor (CppVar . identToCpp $ Ident prop) cls) (CppCast (mapType 0) dict))
845− (CppVar "second")
842+ let index = CppAccessor (CppVar . identToCpp $ Ident prop) cls
843+ in CppGet index dict
846844 dictIndexerToEnum cpp = cpp
847845
848846---------------------------------------------------------------------------------------------------
src/Language/PureScript/CodeGen/Cpp/AST.hs+7
@@ -203,6 +203,10 @@ data Cpp
203203 --
204204 | CppCast CppType Cpp
205205 -- |
206+ -- Call to getter from templated type
207+ --
208+ | CppGet Cpp Cpp
209+ -- |
206210 -- Function application
207211 --
208212 | CppApp Cpp [Cpp]
@@ -307,6 +311,7 @@ everywhereOnCpp f = go
307311 go (CppFunction name args rty qs j) = f (CppFunction name args rty qs (go j))
308312 go (CppLambda cps args rty j) = f (CppLambda cps args rty (go j))
309313 go (CppCast t cpp) = f (CppCast t (go cpp))
314+ go (CppGet j1 j2) = f (CppGet (go j1) (go j2))
310315 go (CppApp j cpp) = f (CppApp (go j) (map go cpp))
311316 go (CppBlock cpp) = f (CppBlock (map go cpp))
312317 go (CppNamespace name cpp) = f (CppNamespace name (map go cpp))
@@ -338,6 +343,7 @@ everywhereOnCppTopDownM f = f >=> go
338343 go (CppFunction name args rty qs j) = CppFunction name args rty qs <$> f' j
339344 go (CppLambda cps args rty j) = CppLambda cps args rty <$> f' j
340345 go (CppCast t cpp) = CppCast t <$> f' cpp
346+ go (CppGet j1 j2) = CppGet <$> f' j1 <*> f' j2
341347 go (CppApp j cpp) = CppApp <$> f' j <*> traverse f' cpp
342348 go (CppBlock cpp) = CppBlock <$> traverse f' cpp
343349 go (CppNamespace name cpp) = CppNamespace name <$> traverse f' cpp
@@ -365,6 +371,7 @@ everythingOnCpp (<>) f = go
365371 go j@(CppFunction _ _ _ _ j1) = f j <> go j1
366372 go j@(CppLambda _ _ _ j1) = f j <> go j1
367373 go j@(CppCast _ cpp) = f j <> go cpp
374+ go j@(CppGet j1 j2) = f j <> go j1 <> go j2
368375 go j@(CppApp j1 cpp) = foldl (<>) (f j <> go j1) (map go cpp)
369376 go j@(CppBlock cpp) = foldl (<>) (f j) (map go cpp)
370377 go j@(CppNamespace _ cpp) = foldl (<>) (f j) (map go cpp)
src/Language/PureScript/CodeGen/Cpp/Common.hs+1
@@ -105,6 +105,7 @@ nameIsCppReserved name =
105105 , "float"
106106 , "for"
107107 , "friend"
108+ , "get"
108109 , "goto"
109110 , "if"
110111 , "import"
src/Language/PureScript/CodeGen/Cpp/Optimizer/Common.hs+1
@@ -63,6 +63,7 @@ targetVariable :: Cpp -> String
6363targetVariable (CppVar var) = var
6464targetVariable (CppAccessor _ tgt) = targetVariable tgt
6565targetVariable (CppIndexer _ tgt) = targetVariable tgt
66+targetVariable (CppGet _ tgt) = targetVariable tgt
6667targetVariable _ = error "Invalid argument to targetVariable"
6768
6869isUpdated :: String -> Cpp -> Bool
src/Language/PureScript/CodeGen/Cpp/Optimizer/Inliner.hs+1
@@ -46,6 +46,7 @@ shouldInline (CppStringLiteral _) = True
4646shouldInline (CppBooleanLiteral _) = True
4747shouldInline (CppAccessor _ val) = shouldInline val
4848shouldInline (CppIndexer index val) = shouldInline index && shouldInline val
49+shouldInline (CppGet index val) = shouldInline index && shouldInline val
4950shouldInline (CppCast _ val) = shouldInline val
5051shouldInline _ = False
5152
src/Language/PureScript/Pretty/Cpp.hs+5
@@ -40,6 +40,7 @@ import Language.PureScript.CodeGen.Cpp.Types
4040import Language.PureScript.Comments
4141import qualified Language.PureScript.Constants as C
4242import Numeric
43+import Text.Printf (printf)
4344
4445-- import Debug.Trace
4546---------------------------------------------------------------------------------------------------
@@ -242,6 +243,10 @@ literals = mkPattern' match
242243 vstr = prettyPrintCpp1 val
243244 val' | '(' `elem` vstr || '[' `elem` vstr = parens vstr
244245 | 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)
245250 match (CppVar ident)
246251 | ident == C.__unused = match (CppVar $ '$' : ident)
247252 match (CppVar ident) = return ident