@@ -32,23 +32,22 @@ import Data.Char (isLetter)
32import Data.Function (on)
32import Data.Function (on)
33import Data.List
33import Data.List
34import qualified Data.Map as M
34import qualified Data.Map as M
35−import Data.Maybe (catMaybes, fromJust)
35+import Data.Maybe (catMaybes)
36import Data.Monoid ((<>))
36import Data.Monoid ((<>))
37import Data.Text (Text, unpack)
37import Data.Text (Text, unpack)
38import qualified Data.Text as Text
38import qualified Data.Text as Text
40import Control.Monad (forM, replicateM)
40import Control.Monad (forM, replicateM)
41−import Control.Monad.Reader (MonadReader, ask)
41+import Control.Monad.Reader (MonadReader)
42import Control.Monad.Supply.Class
42import Control.Monad.Supply.Class
43import Language.PureScript.AST.SourcePos
43import Language.PureScript.AST.SourcePos
44import Language.PureScript.CodeGen.Cpp.AST as AST
44import Language.PureScript.CodeGen.Cpp.AST as AST
45import Language.PureScript.CodeGen.Cpp.Common as Common
45import Language.PureScript.CodeGen.Cpp.Common as Common
46import Language.PureScript.CodeGen.Cpp.File
46import Language.PureScript.CodeGen.Cpp.File
47import Language.PureScript.CodeGen.Cpp.Optimizer
47import Language.PureScript.CodeGen.Cpp.Optimizer
48−import Language.PureScript.CodeGen.Cpp.Optimizer.TCO
48+import Language.PureScript.CodeGen.Cpp.Recursion
49import Language.PureScript.CodeGen.Cpp.Types
49import Language.PureScript.CodeGen.Cpp.Types
50import Language.PureScript.CodeGen.Cpp.Unicode
50import Language.PureScript.CodeGen.Cpp.Unicode
51−import Language.PureScript.Comments
52import Language.PureScript.CoreFn
51import Language.PureScript.CoreFn
53import Language.PureScript.Names
52import Language.PureScript.Names
54import Language.PureScript.Options
53import Language.PureScript.Options
@@ -93,7 +92,7 @@ moduleToCpp otherOpts env (Module _ mn imps _ foreigns decls) = do
93 E.dataConstructors env
92 E.dataConstructors env
94 cpps' <- traverse (optimize $ namesmap ++ datamap) cpps
93 cpps' <- traverse (optimize $ namesmap ++ datamap) cpps
95 foreignWrappers <- curriedForeigns
94 foreignWrappers <- curriedForeigns
96− let optimized = (otherTransforms otherOpts <$> cpps') ++ foreignWrappers
95+ let optimized = (otherTransforms otherOpts . convertRecursiveRefs <$> cpps') ++ foreignWrappers
97 let moduleHeader =
96 let moduleHeader =
98 fileBegin mn "HH" ++
97 fileBegin mn "HH" ++
99 P.linebreak ++
98 P.linebreak ++
@@ -333,7 +332,7 @@ moduleToCpp otherOpts env (Module _ mn imps _ foreigns decls) = do
333 fnToLambda (CppFunction name args _ qs body) =
332 fnToLambda (CppFunction name args _ qs body) =
334 CppVariableIntroduction
333 CppVariableIntroduction
335 (name, Just $ Any [Const])
334 (name, Just $ Any [Const])
336− (filter (== Static) qs)
335+ qs -- (filter (== Static) qs)
337 (Just $ CppLambda cs args (Just $ Any []) body)
336 (Just $ CppLambda cs args (Just $ Any []) body)
@@ -350,82 +349,6 @@ moduleToCpp otherOpts env (Module _ mn imps _ foreigns decls) = do
350 go f@(CppFunction {}) = maybeRemCaps $ fnToLambda f
349 go f@(CppFunction {}) = maybeRemCaps $ fnToLambda f
351 go (CppLambda _ args rtyp body) = maybeRemCaps $ CppLambda [CaptureAll] args rtyp body
350 go (CppLambda _ args rtyp body) = maybeRemCaps $ CppLambda [CaptureAll] args rtyp body
352 go cpp = cpp
351 go cpp = cpp
353− -------------------------------------------------------------------------------------------------
354− convertRecursiveFns :: [Cpp] -> Cpp -> [Cpp]
355− -------------------------------------------------------------------------------------------------
356− convertRecursiveFns cpps otherCpp
357− | not $ null fns = dict : (accessor topdict <$> filteredFns allCpps) ++ cpps'
359− cpps' = everywhereOnCpp removeRec <$> cpps
360− allCpps = CppBlock $ otherCpp : cpps'
361− fns :: [(Text, Cpp)]
362− fns = toelem <$> concatMap (everythingOnCpp (++) recursive) cpps
363− filteredFns :: Cpp -> [(Text, Cpp)]
364− filteredFns cpp = filter (\(f, _) -> everythingOnCpp (||) (== CppVar f) cpp) fns
365− recursive :: Cpp -> [Cpp]
366− recursive cpp'@(CppFunction _ _ _ qs _)
367− | Recursive `elem` qs = [cpp']
368− recursive cpp'@(CppVariableIntroduction _ qs _)
369− | Recursive `elem` qs = [cpp']
371− removeRec :: Cpp -> Cpp
372− removeRec (CppFunction _ _ _ qs _)
373− | Recursive `elem` qs = CppNoOp
374− removeRec (CppVariableIntroduction _ qs _)
375− | Recursive `elem` qs = CppNoOp
376− removeRec cpp' = cpp'
377− replaceVar :: [(Text, Cpp)] -> Cpp -> Cpp
381− | Just var' <- lookup var rs = var'
385− CppVariableIntroduction
386− (topdict, Just $ Any [Const])
388− (Just $ CppDataLiteral ((\(f, cpp) -> CppComment [LineComment f] cpp) <$> fns))
389− accessed :: Text -> Text -> (Text, Cpp)
390− accessed dictname name =
394− (CppNumericLiteral . Left . fromIntegral . fromJust $ findIndex ((== name) . fst) fns)
398− dict' = CppVar dictname
399− accessor :: Text -> (Text, Cpp) -> Cpp
400− accessor dictname (name, _) =
401− CppVariableIntroduction (name, Just $ Any [Const]) [] (Just . snd $ accessed dictname name)
402− toelem :: Cpp -> (Text, Cpp)
403− toelem (CppFunction name args rtyp _ body'@(CppBlock body)) =
405− , withdict . maybeRemCaps $
410− (CppBlock $ (accessor localdict <$> filteredFns body') ++ body))
411− toelem (CppVariableIntroduction (name, _) _ (Just body')) =
412− let replacements = accessed localdict . fst <$> filteredFns body'
413− replaced = everywhereOnCpp (replaceVar replacements) body'
414− in (name, withdict . maybeRemCaps $ CppBlock [CppReturn replaced])
415− toelem _ = error "not a function"
416− withdict :: Cpp -> Cpp
421− [(localdict, Just $ Any [Const, Ref])]
425− topdict = "_$dict$_"
427− localdict = "$dict$"
428− convertRecursiveFns cpps _ = cpps
431 -- Generate code in the simplified C++1x intermediate representation for a value or expression.
354 -- Generate code in the simplified C++1x intermediate representation for a value or expression.
@@ -437,6 +360,9 @@ moduleToCpp otherOpts env (Module _ mn imps _ foreigns decls) = do
437 valueToCpp (Var (_, _, _, Just (IsConstructor _ [])) ident) = return $ CppApp (varToCpp ident) []
360 valueToCpp (Var (_, _, _, Just (IsConstructor _ [])) ident) = return $ CppApp (varToCpp ident) []
438 valueToCpp (Var (_, _, Just ty, _) ident@(Qualified (Just _) _))
361 valueToCpp (Var (_, _, Just ty, _) ident@(Qualified (Just _) _))
439 | arity ty > 0 = return . curriedName' $ varToCpp ident
362 | arity ty > 0 = return . curriedName' $ varToCpp ident
363+ valueToCpp (Var (_, _, Nothing, _) ident@(Qualified (Just _) _))
364+ | Just (ty, _, _) <- M.lookup ident (E.names env)
365+ , arity ty > 0 = return . curriedName' $ varToCpp ident
440 valueToCpp (Var _ ident) = return $ varToCpp ident
366 valueToCpp (Var _ ident) = return $ varToCpp ident
441 valueToCpp (Literal _ (NumericLiteral n)) = return (CppNumericLiteral n)
367 valueToCpp (Literal _ (NumericLiteral n)) = return (CppNumericLiteral n)
442 valueToCpp (Literal _ (StringLiteral s)) = return (CppStringLiteral s)
368 valueToCpp (Literal _ (StringLiteral s)) = return (CppStringLiteral s)
@@ -500,32 +426,8 @@ moduleToCpp otherOpts env (Module _ mn imps _ foreigns decls) = do
500 valueToCpp (Let _ ds val) = do
426 valueToCpp (Let _ ds val) = do
501 ds' <- concat <$> mapM (bindToCpp []) ds
427 ds' <- concat <$> mapM (bindToCpp []) ds
502 ret <- valueToCpp val
428 ret <- valueToCpp val
504− let ds'' = tco opts <$> ds'
506− if hasRecursion ds''
507− then convertRecursiveFns ds'' ret
509− let cpps = innerLambdas <$> rs
429+ let cpps = (innerLambdas <$> ds') ++ [CppReturn ret]
510− return $ CppApp (CppLambda [] [] Nothing (CppBlock (cpps ++ [CppReturn ret]))) []
430+ return $ CppApp (CppLambda [] [] Nothing (CppBlock cpps)) []
512− hasRecursion :: [Cpp] -> Bool
513− hasRecursion cpps' = any (everythingOnCpp (||) hasRecursiveRef) cpps'
516− valnames = concatMap (everythingOnCpp (++) valname) cpps'
517− valname :: Cpp -> [Text]
518− valname (CppFunction name _ _ _ _) = [name]
519− valname (CppVariableIntroduction (name, _) _ _) = [name]
521− hasRecursiveRef :: Cpp -> Bool
522− hasRecursiveRef (CppFunction _ _ _ _ body) = everythingOnCpp (||) ref body
523− hasRecursiveRef (CppVariableIntroduction _ _ (Just value)) = everythingOnCpp (||) ref value
524− hasRecursiveRef _ = False
527− | name `elem` valnames = True
529 valueToCpp Constructor {} = return CppNoOp
431 valueToCpp Constructor {} = return CppNoOp