@@ -13,127 +13,115 @@
13{-# LANGUAGE PatternGuards #-}
13{-# LANGUAGE PatternGuards #-}
15module Language.PureScript.CodeGen.Cpp.Recursion
15module Language.PureScript.CodeGen.Cpp.Recursion
16− ( convertRecursiveRefs
16+ ( convertRecursiveLets
19import Prelude.Compat
19import Prelude.Compat
20import Data.List
20import Data.List
21import Data.Maybe (fromJust)
21import Data.Maybe (fromJust)
22+import Data.Monoid ((<>))
22import Data.Text (Text)
23import Data.Text (Text)
24import Language.PureScript.CodeGen.Cpp.AST as AST
25import Language.PureScript.CodeGen.Cpp.AST as AST
25import Language.PureScript.CodeGen.Cpp.File
26import Language.PureScript.CodeGen.Cpp.File
26import Language.PureScript.CodeGen.Cpp.Types
27import Language.PureScript.CodeGen.Cpp.Types
27import Language.PureScript.Comments (Comment(..))
28import Language.PureScript.Comments (Comment(..))
29+import qualified Language.PureScript.Pretty.Cpp as P
29-------------------------------------------------------------------------------------------------
31-------------------------------------------------------------------------------------------------
30−convertRecursiveRefs :: Cpp -> Cpp
32+convertRecursiveLets :: Cpp -> Cpp
31-------------------------------------------------------------------------------------------------
33-------------------------------------------------------------------------------------------------
32−convertRecursiveRefs = everywhereOnCpp go
34+convertRecursiveLets = everywhereOnCpp go
34 go :: Cpp -> Cpp
36 go :: Cpp -> Cpp
35 go (CppFunction name args rty qs (CppBlock cpps)) =
37 go (CppFunction name args rty qs (CppBlock cpps)) =
36− CppFunction name args rty qs (CppBlock (convertRecursive cpps))
38+ CppFunction name args rty qs (CppBlock (convertIfRecursive cpps))
37 go (CppLambda cs args rty (CppBlock cpps)) =
39 go (CppLambda cs args rty (CppBlock cpps)) =
38− CppLambda cs args rty (CppBlock (convertRecursive cpps))
40+ CppLambda cs args rty (CppBlock (convertIfRecursive cpps))
39 go cpp = cpp
41 go cpp = cpp
40− convertRecursive :: [Cpp] -> [Cpp]
42+ convertIfRecursive :: [Cpp] -> [Cpp]
41− convertRecursive cpps
43+ convertIfRecursive cpps
42− | hasRecursion cpps
44+ | names@(_:_) <- recNames cpps = convertRecursive names cpps
43− = convertRecursiveRefs' cpps
45− hasRecursion :: [Cpp] -> Bool
46+ recNames :: [Cpp] -> [Text]
46− hasRecursion cpps' = any (everythingOnCpp (||) hasRecursiveRef) cpps'
47+ recNames cpps' = nub $ concatMap (everythingOnCpp (++) recRefs) cpps'
48− valnames :: [Text]
49+ recRefs :: Cpp -> [Text]
50+ recRefs (CppVariableIntroduction _ qs (Just cpp))
51+ | Recursive `elem` qs = everythingOnCpp (++) recRef cpp
54+ recRef :: Cpp -> [Text]
55+ recRef (CppVar name') | name' `elem` possiblyRecNames = [name']
58+ possiblyRecNames :: [Text]
49− valnames = concatMap (everythingOnCpp (++) valname) cpps'
59+ possiblyRecNames = concatMap (everythingOnCpp (++) possiblyRecName) cpps'
50− valname :: Cpp -> [Text]
60+ where
51− valname (CppFunction name' _ _ _ _) = [name']
61+ possiblyRecName :: Cpp -> [Text]
52− valname (CppVariableIntroduction (name', _) _ _) = [name']
62+ possiblyRecName (CppVariableIntroduction (name', _) qs (Just _))
53− valname _ = []
63+ | Recursive `elem` qs = [name']
54− hasRecursiveRef :: Cpp -> Bool
64+ possiblyRecName _ = []
55− hasRecursiveRef (CppFunction _ _ _ _ body) = everythingOnCpp (||) ref body
65+ convertIfRecursive cpp = cpp
56− hasRecursiveRef (CppVariableIntroduction _ _ (Just value)) = everythingOnCpp (||) ref value
57− hasRecursiveRef _ = False
60− | name' `elem` valnames = True
62− convertRecursive cpp = cpp
64-------------------------------------------------------------------------------------------------
67-------------------------------------------------------------------------------------------------
65−convertRecursiveRefs' :: [Cpp] -> [Cpp]
68+convertRecursive :: [Text] -> [Cpp] -> [Cpp]
66-------------------------------------------------------------------------------------------------
69-------------------------------------------------------------------------------------------------
67−convertRecursiveRefs' cpps
70+convertRecursive names cpps
68− | not $ null fns = dict : (accessor topdict <$> filteredFns allCpps) ++ cpps'
71+ | not $ null lets
74+ (everywhereOnCpp remRecLet <$> cpps) ++
70− cpps' = everywhereOnCpp removeRec <$> cpps
77+ tableName :: Text
71− allCpps = CppBlock cpps'
78+ tableName = "let"
72− fns :: [(Text, Cpp)]
79+ --
73− fns = toelem <$> concatMap (everythingOnCpp (++) recursive) cpps
80+ letTable :: Cpp
74− filteredFns :: Cpp -> [(Text, Cpp)]
81+ letTable =
75− filteredFns cpp = filter (\(f, _) -> everythingOnCpp (||) (== CppVar f) cpp) fns
76− recursive :: Cpp -> [Cpp]
77− recursive cpp'@(CppFunction _ _ _ qs _)
78− | Recursive `elem` qs = [cpp']
79− recursive cpp'@(CppVariableIntroduction _ qs _)
80− | Recursive `elem` qs = [cpp']
82− removeRec :: Cpp -> Cpp
83− removeRec (CppFunction _ _ _ qs _)
84− | Recursive `elem` qs = CppNoOp
85− removeRec (CppVariableIntroduction _ qs _)
86− | Recursive `elem` qs = CppNoOp
87− removeRec cpp' = cpp'
88− replaceVar :: [(Text, Cpp)] -> Cpp -> Cpp
92− | Just var' <- lookup var rs = var'
96 CppVariableIntroduction
82 CppVariableIntroduction
97− (topdict, Just $ Any [Const])
83+ (tableName, Just $ Any [Const])
99− (Just $ CppDataLiteral ((\(f, cpp) -> CppComment [LineComment f] cpp) <$> fns))
85+ (Just $ CppDataLiteral ((\(f, cpp) -> CppComment [LineComment f] cpp) <$> lets))
100− accessed :: Text -> Text -> (Text, Cpp)
86+ --
101− accessed dictname name =
87+ lets :: [(Text, Cpp)]
88+ lets = tableItem <$> concatMap (everythingOnCpp (++) recLet) cpps
90+ recLet :: Cpp -> [Cpp]
91+ recLet cpp@(CppVariableIntroduction (name, _) _ (Just _))
92+ | name `elem` names = [cpp]
95+ remRecLet :: Cpp -> Cpp
96+ remRecLet (CppVariableIntroduction (name, _) _ (Just _))
97+ | name `elem` names = CppNoOp
100+ tableItem :: Cpp -> (Text, Cpp)
101+ tableItem (CppVariableIntroduction (name, _) _ (Just body)) =
102+ (name, maybeRemCaps . addItemArg $ CppBlock [CppReturn body])
104+ addItemArg :: Cpp -> Cpp
105+ addItemArg cpp = CppLambda [CaptureAll] [(tableName, constAnyRef)] (Just $ Any []) (CppBlock [CppReturn cpp])
106+ tableItem _ = error "not a variable introduction"
108+ tableAccessor :: Text -> (Text, Cpp)
109+ tableAccessor name =
104 (CppDataGet
112 (CppDataGet
105− (CppNumericLiteral . Left . fromIntegral . fromJust $ findIndex ((== name) . fst) fns)
113+ (CppNumericLiteral . Left . fromIntegral . fromJust $ findIndex ((== name) . fst) lets)
106− dict')
114+ (CppVar tableName))
107− [dict'])
115+ [CppVar tableName])
118+ defines = def . tableAccessor . fst <$> lets
109− dict' = CppVar dictname
120+ def (name, cpp) = CppRaw $ "#define " <> name <> " " <> P.prettyPrintCpp1 cpp <> "#"
110− accessor :: Text -> (Text, Cpp) -> Cpp
121+ --
111− accessor dictname (name, _) =
122+ undefines :: [Cpp]
112− CppVariableIntroduction (name, Just $ Any [Const]) [] (Just . snd $ accessed dictname name)
123+ undefines = undef . tableAccessor . fst <$> lets
113− toelem :: Cpp -> (Text, Cpp)
124+ where
114− toelem (CppFunction name args rtyp _ body'@(CppBlock body)) =
125+ undef (name, _) = CppRaw $ "#undef " <> name <> "#"
116− , withdict . maybeRemCaps $
127+convertRecursive _ cpps = cpps
121− (CppBlock $ (accessor localdict <$> filteredFns body') ++ body))
122− toelem (CppVariableIntroduction (name, _) _ (Just body')) =
123− let replacements = accessed localdict . fst <$> filteredFns body'
124− replaced = everywhereOnCpp (replaceVar replacements) body'
125− in (name, withdict . maybeRemCaps $ CppBlock [CppReturn replaced])
126− toelem _ = error "not a function"
127− withdict :: Cpp -> Cpp
132− [(localdict, Just $ Any [Const, Ref])]
134− (CppBlock [CppReturn cpp'])
136− topdict = "_$dict$_"
138− localdict = "$dict$"
139−convertRecursiveRefs' cpps = cpps