git.iko.soy/rowtype-yoga/purescript-native
on golang help sign in
C++: update to 0.10.3 and use Text instead of String
commit51e6b26a3963b20d9b5b64bc227e37ce918e575f authorAndy Arvanitis <andyarvanitis@gmail.com> dateThu 15 Dec 2016, 20:39 (10 years ago) parent4d7a3c2
13 files changed+419−396
pcc/Main.hs+3−3 pcc/Make.hs+32−30 src/Language/PureScript/CodeGen/Cpp.hs+46−38 src/Language/PureScript/CodeGen/Cpp/AST.hs+14−13 src/Language/PureScript/CodeGen/Cpp/Common.hs+26−18 src/Language/PureScript/CodeGen/Cpp/File.hs+10−7 src/Language/PureScript/CodeGen/Cpp/Optimizer/Common.hs+11−10 src/Language/PureScript/CodeGen/Cpp/Optimizer/Inliner.hs+51−47 src/Language/PureScript/CodeGen/Cpp/Optimizer/TCO.hs+14−10 src/Language/PureScript/CodeGen/Cpp/Optimizer/Uncurry.hs+3−1 src/Language/PureScript/CodeGen/Cpp/Types.hs+16−13 src/Language/PureScript/CodeGen/Cpp/Unicode.hs+10−6 src/Language/PureScript/Pretty/Cpp.hs+183−200
pcc/Main.hs+3−3
@@ -32,7 +32,7 @@ import qualified Data.ByteString.UTF8 as BU8
3232import Data.Char (isSpace)
3333import qualified Data.Map as M
3434import Data.Maybe (maybe)
35−import Data.Text (Text)
35+import Data.Text (Text, unpack)
3636import Data.Version (showVersion)
3737
3838import qualified Language.PureScript as P
@@ -109,13 +109,13 @@ briefFormat (JSONResult warnings errors) =
109109 (startLine pos)
110110 (startColumn pos)
111111 (show t)
112− (combine msg lnk)
112+ (combine msg (unpack lnk))
113113 renderError t (JSONError _ msg _ lnk _ module' _) =
114114 printf
115115 "%s: in module %s - %s"
116116 (show t)
117117 (maybe "?" (printf "\"%s\"") module')
118− (combine msg lnk)
118+ (combine msg (unpack lnk))
119119 combine :: String -> String -> String
120120 combine msg lnk
121121 | null lnk = msg'
pcc/Make.hs+32−30
@@ -15,6 +15,7 @@
1515{-# LANGUAGE DataKinds #-}
1616{-# LANGUAGE FlexibleContexts #-}
1717{-# LANGUAGE GeneralizedNewtypeDeriving #-}
18+{-# LANGUAGE OverloadedStrings #-}
1819{-# LANGUAGE PatternGuards #-}
1920{-# LANGUAGE TupleSections #-}
2021{-# LANGUAGE TemplateHaskell #-}
@@ -27,33 +28,32 @@ module Make
2728 ) where
2829
2930import Control.Monad
30−import Control.Monad.Error.Class (MonadError(..))
3131import Control.Monad.Reader
3232
3333import Data.FileEmbed (embedFile)
3434import Data.Maybe (fromMaybe)
35+import Data.Monoid ((<>))
36+import qualified Data.Text as T
37+import qualified Data.Text.Encoding as TE
3538import Data.Time.Clock
3639import Data.Version (showVersion)
3740import qualified Data.Map as M
38−import qualified Data.ByteString.Char8 as B
41+import qualified Data.ByteString.Lazy as B
3942
4043import System.Directory (copyFile, doesDirectoryExist, doesFileExist, getModificationTime, createDirectoryIfMissing)
4144import System.FilePath ((</>), takeDirectory, addExtension, dropExtension)
4245import System.IO.Error (tryIOError)
43−import System.IO.UTF8
4446
4547import Language.PureScript.Errors
46−import Language.PureScript (Make, runMake)
48+import Language.PureScript (Make, makeIO, readTextFile, runMake)
4749
4850import qualified Language.PureScript as P
4951import qualified Language.PureScript.CodeGen.Cpp as CPP
5052import qualified Language.PureScript.CoreFn as CF
5153import qualified Paths_purescript as Paths
5254
53−makeIO :: (IOError -> P.ErrorMessage) -> IO a -> Make a
54−makeIO f io = do
55− e <- liftIO $ tryIOError io
56− either (throwError . P.singleError . f) return e
55+runModuleName' :: P.ModuleName -> String
56+runModuleName' = T.unpack . P.runModuleName
5757
5858buildMakeActions :: FilePath
5959 -> M.Map P.ModuleName (Either P.RebuildPolicy FilePath)
@@ -75,7 +75,7 @@ buildMakeActions outputDir filePathMap usePrefix otherOpts =
7575 getInputTimestamp mn = do
7676 let path = fromMaybe (error "Module has no filename in 'make'") $ M.lookup mn filePathMap
7777 let filePath = either (const []) takeDirectory path
78− fileBase = filePath </> (last . words . dotsTo ' ' $ P.runModuleName mn)
78+ fileBase = filePath </> (last . words . dotsTo ' ' $ runModuleName' mn)
7979 ffis = addExtension fileBase <$> [sourceExt, headerExt] ++ otherExts
8080 e1 <- traverse getTimestamp path
8181 ffimax <- foldl1 max <$> mapM getTimestamp ffis
@@ -83,8 +83,8 @@ buildMakeActions outputDir filePathMap usePrefix otherOpts =
8383
8484 getOutputTimestamp :: P.ModuleName -> Make (Maybe UTCTime)
8585 getOutputTimestamp mn = do
86− let filePath = P.runModuleName mn
87− fileBase = outputDir </> filePath </> (last . words . dotsTo ' ' $ P.runModuleName mn)
86+ let filePath = runModuleName' mn
87+ fileBase = outputDir </> filePath </> (last . words . dotsTo ' ' $ runModuleName' mn)
8888 sourceFile = addExtension fileBase sourceExt
8989 headerFile = addExtension fileBase headerExt
9090 externsFile = outputDir </> filePath </> "externs.json"
@@ -92,36 +92,36 @@ buildMakeActions outputDir filePathMap usePrefix otherOpts =
9292
9393 readExterns :: P.ModuleName -> Make (FilePath, P.Externs)
9494 readExterns mn = do
95− let path = outputDir </> (P.runModuleName mn) </> "externs.json"
95+ let path = outputDir </> (runModuleName' mn) </> "externs.json"
9696 (path, ) <$> readTextFile path
9797
9898 codegen :: CF.Module CF.Ann -> P.Environment -> P.Externs -> P.SupplyT Make ()
9999 codegen m env exts = do
100100 let mn = CF.moduleName m
101− let filePath = P.runModuleName mn
102− fileBase = outputDir </> filePath </> (last . words . dotsTo ' ' $ P.runModuleName mn)
101+ let filePath = runModuleName' mn
102+ fileBase = outputDir </> filePath </> (last . words . dotsTo ' ' $ runModuleName' mn)
103103 sourceFile = addExtension fileBase sourceExt
104104 headerFile = addExtension fileBase headerExt
105105 externsFile = outputDir </> filePath </> "externs.json"
106− prefix = ["Generated by pcc version " ++ showVersion Paths.version | usePrefix]
106+ prefix = ["Generated by pcc version " <> T.pack (showVersion Paths.version) | usePrefix]
107107 cpps <- CPP.moduleToCpp otherOpts env m
108108 let (hdrs,srcs) = span (/= CPP.CppEndOfHeader) cpps
109109 psrcs <- CPP.prettyPrintCpp <$> pure srcs
110110 phdrs <- CPP.prettyPrintCpp <$> pure hdrs
111− let src = unlines $ map ("// " ++) prefix ++ [psrcs]
112− hdr = unlines $ map ("// " ++) prefix ++ [phdrs]
111+ let src = T.unlines $ map ("// " <>) prefix ++ [psrcs]
112+ hdr = T.unlines $ map ("// " <>) prefix ++ [phdrs]
113113
114114 lift $ do
115− writeTextFile sourceFile src
116− writeTextFile headerFile hdr
115+ writeTextFile' sourceFile src
116+ writeTextFile' headerFile hdr
117117 writeTextFile externsFile exts
118118
119119 let supportDir = outputDir </> "PureScript"
120120 supportFilesExist <- dirExists supportDir
121121 when (not supportFilesExist) $ do
122− writeTextFile (supportDir </> "PureScript.hh") $ B.unpack $(embedFile "pcc/runtime/purescript.hh")
123− writeTextFile (supportDir </> "PureScript.cc") $ B.unpack $(embedFile "pcc/runtime/purescript.cc")
124− writeTextFile (supportDir </> "purescript_memory.hh") $ B.unpack $(embedFile "pcc/runtime/purescript_memory.hh")
122+ writeTextFile (supportDir </> "PureScript.hh") $ B.fromStrict $(embedFile "pcc/runtime/purescript.hh")
123+ writeTextFile (supportDir </> "PureScript.cc") $ B.fromStrict $(embedFile "pcc/runtime/purescript.cc")
124+ writeTextFile (supportDir </> "purescript_memory.hh") $ B.fromStrict $(embedFile "pcc/runtime/purescript_memory.hh")
125125
126126 let inputPath = dropExtension $ getInputFile mn
127127 hfile = addExtension inputPath headerExt
@@ -131,7 +131,7 @@ buildMakeActions outputDir filePathMap usePrefix otherOpts =
131131 let dstFile = addExtension (fileBase ++ ffiMangle) headerExt
132132 if hfileExists
133133 then copyTextFile dstFile hfile
134− else writeTextFile dstFile []
134+ else writeTextFile dstFile ""
135135 sfileExists <- textFileExists sfile
136136 when (sfileExists) $ do
137137 copyTextFile (addExtension (fileBase ++ ffiMangle) sourceExt) sfile
@@ -154,9 +154,6 @@ buildMakeActions outputDir filePathMap usePrefix otherOpts =
154154 exists <- doesFileExist path
155155 traverse (const $ getModificationTime path) $ guard exists
156156
157− readTextFile :: FilePath -> Make String
158− readTextFile path = makeIO (const (ErrorMessage [] $ CannotReadFile path)) $ readUTF8File path
159−
160157 copyTextFile :: FilePath -> FilePath -> Make ()
161158 copyTextFile to from = makeIO (const (ErrorMessage [] $ CannotWriteFile to)) $ do
162159 createDirectoryIfMissing True (takeDirectory to)
@@ -168,15 +165,20 @@ buildMakeActions outputDir filePathMap usePrefix otherOpts =
168165 _ <- tryIOError $ copyFile (addExtension from ext) (addExtension to ext)
169166 return ()
170167
171− writeTextFile :: FilePath -> String -> Make ()
168+ writeTextFile :: FilePath -> B.ByteString -> Make ()
172169 writeTextFile path text = makeIO (const (ErrorMessage [] $ CannotWriteFile path)) $ do
173− createDirectoryIfMissing True (takeDirectory path)
174− _ <- tryIOError $ writeFile path text -- TODO: intended to ignore "file busy", fix properly asap
170+ mkdirp path
171+ _ <- tryIOError $ B.writeFile path text -- TODO: intended to ignore "file busy", fix properly asap
175172 return ()
173+ where
174+ mkdirp :: FilePath -> IO ()
175+ mkdirp = createDirectoryIfMissing True . takeDirectory
176+
177+ writeTextFile' path = writeTextFile path . B.fromStrict . TE.encodeUtf8
176178
177179 -- | Render a progress message
178180 renderProgressMessage :: P.ProgressMessage -> String
179− renderProgressMessage (P.CompilingModule mn) = "Compiling " ++ P.runModuleName mn
181+ renderProgressMessage (P.CompilingModule mn) = "Compiling " ++ runModuleName' mn
180182
181183 progress :: P.ProgressMessage -> Make ()
182184 progress = liftIO . putStrLn . renderProgressMessage
src/Language/PureScript/CodeGen/Cpp.hs+46−38
@@ -34,6 +34,9 @@ import Data.Function (on)
3434import Data.List
3535import qualified Data.Map as M
3636import Data.Maybe (catMaybes, fromJust)
37+import Data.Monoid ((<>))
38+import Data.Text (Text, unpack)
39+import qualified Data.Text as Text
3740
3841import Control.Monad (forM, replicateM)
3942import Control.Monad.Reader (MonadReader, ask)
@@ -95,7 +98,7 @@ moduleToCpp otherOpts env (Module _ mn imps _ foreigns decls) = do
9598 P.linebreak ++
9699 ((\i -> CppInclude i i) <$> cppImports') ++
97100 (if not (null foreigns)
98− then [CppInclude [] (runModuleName mn ++ "_ffi")]
101+ then [CppInclude "" (runModuleName mn <> "_ffi")]
99102 else []) ++
100103 P.linebreak ++
101104 [ CppNamespace (runModuleName mn) $
@@ -135,8 +138,8 @@ moduleToCpp otherOpts env (Module _ mn imps _ foreigns decls) = do
135138 -------------------------------------------------------------------------------------------------
136139 declToCpp _ (_, ident) e@(Abs (_, _, _, Just IsTypeClassConstructor) _ _) =
137140 let className = identToCpp ident
138− (supers, members) = span (C.__superclass_ `isPrefixOf`) (identToCpp <$> (fst $ unAbs e []))
139− in return $ CppStruct className [CppEnum Nothing Nothing (sort supers ++ members)]
141+ (supers, members) = span (C.__superclass_ `Text.isPrefixOf`) (identToCpp <$> (fst $ unAbs e []))
142+ in return $ CppStruct className [CppEnum Nothing Nothing (sort supers <> members)]
140143 declToCpp vqs (_, ident) (Abs (_, com, ty, _) arg body) = do
141144 fn <-
142145 if TopLevel `elem` vqs
@@ -352,9 +355,9 @@ moduleToCpp otherOpts env (Module _ mn imps _ foreigns decls) = do
352355 where
353356 cpps' = everywhereOnCpp removeRec <$> cpps
354357 allCpps = CppBlock $ otherCpp : cpps'
355− fns :: [(String, Cpp)]
358+ fns :: [(Text, Cpp)]
356359 fns = toelem <$> concatMap (everythingOnCpp (++) recursive) cpps
357− filteredFns :: Cpp -> [(String, Cpp)]
360+ filteredFns :: Cpp -> [(Text, Cpp)]
358361 filteredFns cpp = filter (\(f, _) -> everythingOnCpp (||) (== CppVar f) cpp) fns
359362 recursive :: Cpp -> [Cpp]
360363 recursive cpp'@(CppFunction _ _ _ qs _)
@@ -368,7 +371,7 @@ moduleToCpp otherOpts env (Module _ mn imps _ foreigns decls) = do
368371 removeRec (CppVariableIntroduction _ qs _)
369372 | Recursive `elem` qs = CppNoOp
370373 removeRec cpp' = cpp'
371− replaceVar :: [(String, Cpp)] -> Cpp -> Cpp
374+ replaceVar :: [(Text, Cpp)] -> Cpp -> Cpp
372375 replaceVar rs = go
373376 where
374377 go (CppVar var)
@@ -380,7 +383,7 @@ moduleToCpp otherOpts env (Module _ mn imps _ foreigns decls) = do
380383 (topdict, Just $ Any [Const])
381384 []
382385 (Just $ CppDataLiteral ((\(f, cpp) -> CppComment [LineComment f] cpp) <$> fns))
383− accessed :: String -> String -> (String, Cpp)
386+ accessed :: Text -> Text -> (Text, Cpp)
384387 accessed dictname name =
385388 ( name
386389 , CppApp
@@ -391,10 +394,10 @@ moduleToCpp otherOpts env (Module _ mn imps _ foreigns decls) = do
391394 where
392395 dict' = CppVar dictname
393396 dict'' = CppCast (dataType 1) dict'
394− accessor :: String -> (String, Cpp) -> Cpp
397+ accessor :: Text -> (Text, Cpp) -> Cpp
395398 accessor dictname (name, _) =
396399 CppVariableIntroduction (name, Just $ Any [Const]) [] (Just . snd $ accessed dictname name)
397− toelem :: Cpp -> (String, Cpp)
400+ toelem :: Cpp -> (Text, Cpp)
398401 toelem (CppFunction name args rtyp _ body'@(CppBlock body)) =
399402 ( name
400403 , withdict . maybeRemCaps $
@@ -416,9 +419,9 @@ moduleToCpp otherOpts env (Module _ mn imps _ foreigns decls) = do
416419 [(localdict, Just $ Any [Const, Ref])]
417420 (Just $ Any [])
418421 (returnBlock cpp')
419− topdict :: String
422+ topdict :: Text
420423 topdict = "_$dict$_"
421− localdict :: String
424+ localdict :: Text
422425 localdict = "$dict$"
423426 convertRecursiveFns cpps _ = cpps
424427
@@ -452,10 +455,10 @@ moduleToCpp otherOpts env (Module _ mn imps _ foreigns decls) = do
452455 CppMapLiteral Record $
453456 (\(k, v) -> (CppSymbol k, v)) <$> sortBy (compare `on` fst) (origFields ++ updatedFields)
454457 where
455− allKeys :: T.Type -> [String]
458+ allKeys :: T.Type -> [Text]
456459 allKeys (T.TypeApp (T.TypeConstructor _) r@(T.RCons {})) = fst <$> (fst $ T.rowToList r)
457460 allKeys (T.ForAll _ t _) = allKeys t
458− allKeys _ = error $ show "Not a recognized row type"
461+ allKeys _ = error "Not a recognized row type"
459462 valueToCpp (ObjectUpdate _ _ _) = error $ "Bad Type in object update!"
460463 valueToCpp (Abs (_, _, ty, _) arg body) = do
461464 cpp <- valueToCpp body
@@ -505,9 +508,9 @@ moduleToCpp otherOpts env (Module _ mn imps _ foreigns decls) = do
505508 hasRecursion :: [Cpp] -> Bool
506509 hasRecursion cpps' = any (everythingOnCpp (||) hasRecursiveRef) cpps'
507510 where
508− valnames :: [String]
511+ valnames :: [Text]
509512 valnames = concatMap (everythingOnCpp (++) valname) cpps'
510− valname :: Cpp -> [String]
513+ valname :: Cpp -> [Text]
511514 valname (CppFunction name _ _ _ _) = [name]
512515 valname (CppVariableIntroduction (name, _) _ _) = [name]
513516 valname _ = []
@@ -554,21 +557,21 @@ moduleToCpp otherOpts env (Module _ mn imps _ foreigns decls) = do
554557 (CppBlock (assignments ++ concat cpps ++ [failedPatternError valNames])))
555558 []
556559 where
557− mkVarDecl :: String -> Maybe Cpp -> Cpp
560+ mkVarDecl :: Text -> Maybe Cpp -> Cpp
558561 mkVarDecl name = CppVariableIntroduction (name, Nothing) []
559− go :: [String] -> [Cpp] -> [Binder Ann] -> m [Cpp]
562+ go :: [Text] -> [Cpp] -> [Binder Ann] -> m [Cpp]
560563 go _ done [] = return done
561564 go (v:vs) done' (b:bs) = do
562565 done'' <- go vs done' bs
563566 binderToCpp v done'' b
564567 go _ _ _ = error "Invalid arguments to bindersToCpp"
565− failedPatternError :: [String] -> Cpp
568+ failedPatternError :: [Text] -> Cpp
566569 failedPatternError _ =
567570 CppThrow $ CppApp (CppVar "runtime_error") [CppStringLiteral errorMessage]
568− errorMessage :: String
571+ errorMessage :: Text
569572 errorMessage =
570− "Failed pattern match" ++
571− maybe "" (((" at " ++ runModuleName mn ++ " ") ++) . displayStartEndPos) maybeSpan ++ ": "
573+ "Failed pattern match" <>
574+ maybe "" (((" at " <> runModuleName mn <> " ") <>) . displayStartEndPos) maybeSpan <> ": "
572575 guardsToCpp :: Either [(Guard Ann, Expr Ann)] (Expr Ann) -> m [Cpp]
573576 guardsToCpp (Left gs) =
574577 forM gs $ \(cond, val) -> do
@@ -582,7 +585,7 @@ moduleToCpp otherOpts env (Module _ mn imps _ foreigns decls) = do
582585 -- binder.
583586 --
584587 -------------------------------------------------------------------------------------------------
585− binderToCpp :: String -> [Cpp] -> Binder Ann -> m [Cpp]
588+ binderToCpp :: Text -> [Cpp] -> Binder Ann -> m [Cpp]
586589 -------------------------------------------------------------------------------------------------
587590 binderToCpp _ done (NullBinder {}) = return done
588591 binderToCpp varName done (LiteralBinder _ l) = literalToBinderCpp varName done l
@@ -622,7 +625,7 @@ moduleToCpp otherOpts env (Module _ mn imps _ foreigns decls) = do
622625 (CppCast (dataType $ fieldToIndex field + 1) $ CppVar varName)) :
623626 cpps
624627 fieldToIndex :: Ident -> Int
625− fieldToIndex = (+ 1) . read . dropWhile isLetter . runIdent
628+ fieldToIndex = (+ 1) . read . dropWhile isLetter . unpack . runIdent
626629 fieldToIndex' :: Ident -> Cpp
627630 fieldToIndex' = CppNumericLiteral . Left . toInteger . fieldToIndex
628631 ctor' :: Cpp
@@ -633,14 +636,14 @@ moduleToCpp otherOpts env (Module _ mn imps _ foreigns decls) = do
633636 , mn'' /= mn = CppAccessor ctor' (CppVar $ moduleNameToCpp mn'')
634637 | otherwise = ctor'
635638 binderToCpp _ _ b@(ConstructorBinder {}) =
636− error $ "Invalid ConstructorBinder in binderToCpp: " ++ show b
639+ error $ "Invalid ConstructorBinder in binderToCpp: " <> show b
637640 binderToCpp varName done (NamedBinder _ ident binder) = do
638641 cpp <- binderToCpp varName done binder
639642 return $
640643 CppVariableIntroduction (identToCpp ident, Just $ Any [Const]) [] (Just $ CppVar varName) :
641644 cpp
642645 -------------------------------------------------------------------------------------------------
643− literalToBinderCpp :: String -> [Cpp] -> Literal (Binder Ann) -> m [Cpp]
646+ literalToBinderCpp :: Text -> [Cpp] -> Literal (Binder Ann) -> m [Cpp]
644647 -------------------------------------------------------------------------------------------------
645648 literalToBinderCpp varName done (NumericLiteral num) =
646649 return
@@ -665,7 +668,7 @@ moduleToCpp otherOpts env (Module _ mn imps _ foreigns decls) = do
665668 return [CppIfElse (CppUnary Not (CppVar varName)) (CppBlock done) Nothing]
666669 literalToBinderCpp varName done (ObjectLiteral bs) = go done bs
667670 where
668− go :: [Cpp] -> [(String, Binder Ann)] -> m [Cpp]
671+ go :: [Cpp] -> [(Text, Binder Ann)] -> m [Cpp]
669672 go done' [] = return done'
670673 go done' ((prop, binder):bs') = do
671674 propVar <- freshName
@@ -726,7 +729,7 @@ moduleToCpp otherOpts env (Module _ mn imps _ foreigns decls) = do
726729 --
727730 -------------------------------------------------------------------------------------------------
728731 findClass :: Qualified (ProperName 'ClassName)
729− -> Maybe ([String], [T.Constraint], [(String, T.Type)])
732+ -> Maybe ([Text], [T.Constraint], [(Text, T.Type)])
730733 -------------------------------------------------------------------------------------------------
731734 findClass name
732735 | Just tcd <- M.lookup name (E.typeClasses env)
@@ -756,7 +759,7 @@ moduleToCpp otherOpts env (Module _ mn imps _ foreigns decls) = do
756759 ]
757760 ]
758761 where
759− modCtor :: Qualified (ProperName a) -> Maybe String
762+ modCtor :: Qualified (ProperName a) -> Maybe Text
760763 modCtor (Qualified (Just mn') (ProperName name))
761764 | mn' == mn = Just $ identToCpp (Ident name)
762765 modCtor _ = Nothing
@@ -794,7 +797,7 @@ returnBlock :: Cpp -> Cpp
794797returnBlock cpp = CppBlock [CppReturn cpp]
795798
796799---------------------------------------------------------------------------------------------------
797−curriedLambda :: [String] -> Cpp -> Cpp
800+curriedLambda :: [Text] -> Cpp -> Cpp
798801---------------------------------------------------------------------------------------------------
799802curriedLambda args ret =
800803 foldr
@@ -804,7 +807,7 @@ curriedLambda args ret =
804807 args
805808
806809---------------------------------------------------------------------------------------------------
807−curriedApp :: [String] -> Expr Ann -> Expr Ann
810+curriedApp :: [Text] -> Expr Ann -> Expr Ann
808811---------------------------------------------------------------------------------------------------
809812curriedApp args vals =
810813 foldl (\val arg -> App nullAnn val (Var nullAnn . Qualified Nothing $ Ident arg)) vals args
@@ -844,10 +847,13 @@ optIndexers classes = everywhereOnCpp dictIndexerToEnum
844847 dictIndexerToEnum cpp = cpp
845848
846849---------------------------------------------------------------------------------------------------
847−curriedName :: String -> String
850+curriedName :: Text -> Text
848851---------------------------------------------------------------------------------------------------
849−curriedName name@('$':_) = name
850−curriedName name = '$' : name
852+curriedName name
853+ | Text.null name = name
854+curriedName name
855+ | Text.head name == '$' = name
856+ | otherwise = '$' `Text.cons` name
851857
852858---------------------------------------------------------------------------------------------------
853859curriedName' :: Cpp -> Cpp
@@ -881,28 +887,30 @@ primFn = go []
881887convertIfPrimFn :: Maybe T.Type -> Cpp -> Cpp
882888---------------------------------------------------------------------------------------------------
883889convertIfPrimFn ty@(Just _) (CppNamespace ns fs) = CppNamespace ns (convertIfPrimFn ty <$> fs)
884−convertIfPrimFn (Just _) cpp@(CppFunction ('$':_) _ _ _ _) = cpp
890+convertIfPrimFn (Just _) cpp@(CppFunction name _ _ _ _)
891+ | not $ Text.null name
892+ , Text.head name == '$' = cpp
885893convertIfPrimFn (Just ty) (CppFunction name params _ qs body)
886894 | (tys', Just rty') <- primFn ty =
887895 CppFunction name (zipWith (\(p, _) t -> (p, Just t)) params tys') (Just rty') qs body
888896convertIfPrimFn _ cpp = cpp
889897
890898---------------------------------------------------------------------------------------------------
891−allSymbols :: [Cpp] -> [String]
899+allSymbols :: [Cpp] -> [Text]
892900---------------------------------------------------------------------------------------------------
893901allSymbols cpps = nub $ concatMap (everythingOnCpp (++) symbols) cpps
894902 where
895− symbols :: Cpp -> [String]
903+ symbols :: Cpp -> [Text]
896904 symbols (CppSymbol s) = [symbolname s]
897905 symbols _ = []
898906
899907---------------------------------------------------------------------------------------------------
900−symbolDefs :: [String] -> Cpp
908+symbolDefs :: [Text] -> Cpp
901909---------------------------------------------------------------------------------------------------
902910symbolDefs [] = CppNoOp
903911symbolDefs syms = CppNamespace "PureScript" [CppNamespace "symbol" (asStruct <$> syms)]
904912 where
905− asStruct :: String -> Cpp
913+ asStruct :: Text -> Cpp
906914 asStruct s = CppStruct s []
907915
908916---------------------------------------------------------------------------------------------------
src/Language/PureScript/CodeGen/Cpp/AST.hs+14−13
@@ -25,6 +25,7 @@ import Control.Applicative (Applicative, (<$>), (<*>))
2525import Data.Traversable (traverse)
2626#endif
2727import Control.Monad.Identity
28+import Data.Text (Text)
2829import Language.PureScript.Comments
2930import Language.PureScript.CodeGen.Cpp.Types
3031import Language.PureScript.Traversals
@@ -149,7 +150,7 @@ data Cpp
149150 -- |
150151 -- A string literal
151152 --
152− | CppStringLiteral String
153+ | CppStringLiteral Text
153154 -- |
154155 -- A character literal
155156 --
@@ -177,7 +178,7 @@ data Cpp
177178 -- |
178179 -- An enum definition (optional name, optional type)
179180 --
180− | CppEnum (Maybe String) (Maybe CppType) [String]
181+ | CppEnum (Maybe Text) (Maybe CppType) [Text]
181182 -- |
182183 -- An array indexer expression
183184 --
@@ -193,11 +194,11 @@ data Cpp
193194 -- |
194195 -- A function introduction (name, arguments, return type, qualifiers, body)
195196 --
196− | CppFunction String [(String, Maybe CppType)] (Maybe CppType) [ValueQual] Cpp
197+ | CppFunction Text [(Text, Maybe CppType)] (Maybe CppType) [ValueQual] Cpp
197198 -- |
198199 -- A lambda introduction (arguments, return type, body)
199200 --
200− | CppLambda [CaptureType] [(String, Maybe CppType)] (Maybe CppType) Cpp
201+ | CppLambda [CaptureType] [(Text, Maybe CppType)] (Maybe CppType) Cpp
201202 -- |
202203 -- Value type cast
203204 --
@@ -213,11 +214,11 @@ data Cpp
213214 -- |
214215 -- Variable
215216 --
216− | CppVar String
217+ | CppVar Text
217218 -- |
218219 -- Unique system-wide name/constant
219220 --
220− | CppSymbol String
221+ | CppSymbol Text
221222 -- |
222223 -- |
223224 -- A block of expressions in braces
@@ -226,27 +227,27 @@ data Cpp
226227 -- |
227228 -- A C++ namespace
228229 --
229− | CppNamespace String [Cpp]
230+ | CppNamespace Text [Cpp]
230231 -- |
231232 -- An C++ struct declaration (name, members)
232233 --
233− | CppStruct String [Cpp]
234+ | CppStruct Text [Cpp]
234235 -- |
235236 -- A C++ #include
236237 --
237− | CppInclude String String
238+ | CppInclude Text Text
238239 -- |
239240 -- A C++ using namespace declaration
240241 --
241− | CppUseNamespace String
242+ | CppUseNamespace Text
242243 -- |
243244 -- Type alias, e.g. "using T = U" (new name and template types, original type)
244245 --
245− | CppTypeAlias (String,[(String, Int)]) CppType String
246+ | CppTypeAlias (Text,[(Text, Int)]) CppType Text
246247 -- |
247248 -- A variable introduction and optional initialization
248249 --
249− | CppVariableIntroduction (String, Maybe CppType) [ValueQual] (Maybe Cpp)
250+ | CppVariableIntroduction (Text, Maybe CppType) [ValueQual] (Maybe Cpp)
250251 -- |
251252 -- A variable assignment
252253 --
@@ -286,7 +287,7 @@ data Cpp
286287 -- |
287288 -- Raw C++11 (generated when parsing fails for an inline foreign import declaration)
288289 --
289− | CppRaw String
290+ | CppRaw Text
290291 -- |
291292 -- Commented C++11
292293 --
src/Language/PureScript/CodeGen/Cpp/Common.hs+26−18
@@ -14,14 +14,16 @@
1414-----------------------------------------------------------------------------
1515
1616{-# LANGUAGE PatternGuards #-}
17+{-# LANGUAGE OverloadedStrings #-}
1718
1819module Language.PureScript.CodeGen.Cpp.Common where
1920
20−import Prelude.Compat
21+import Prelude.Compat hiding (all, concatMap, last, init)
2122
2223import Data.Char
23−import Data.List (intercalate)
24−
24+import Data.Text hiding (map)
25+import Data.Monoid ((<>))
26+import qualified Data.Text as T
2527import Language.PureScript.Crash
2628import Language.PureScript.Names
2729
@@ -34,33 +36,35 @@ import Language.PureScript.Names
3436--
3537-- * Symbols are wrapped with '_' between a symbol name or their ordinal value.
3638--
37−identToCpp :: Ident -> String
38−identToCpp (Ident name) | nameIsCppReserved name = '_' : name ++ "_"
39−identToCpp (Ident name@('$' : s)) | all isDigit s = name
39+identToCpp :: Ident -> Text
40+identToCpp (Ident name) | nameIsCppReserved name = "_" <> name <> "_"
41+identToCpp (Ident name)
42+ | Just ('$', s) <- uncons name
43+ , all isDigit s = name
4044identToCpp (Ident name) = concatMap identCharToString name
41−identToCpp (GenIdent _ _) = internalError "GenIdent in identToJs"
45+identToCpp (GenIdent _ _) = internalError "GenIdent in identToCpp"
4246
4347-- |
4448-- Test if a string is a valid Cpp identifier without escaping.
4549--
46−identNeedsEscaping :: String -> Bool
50+identNeedsEscaping :: Text -> Bool
4751identNeedsEscaping s = s /= identToCpp (Ident s)
4852
4953-- |
5054-- Attempts to find a human-readable name for a symbol, if none has been specified returns the
5155-- ordinal value.
5256--
53−identCharToString :: Char -> String
54−identCharToString c | isAlphaNum c = [c]
57+identCharToString :: Char -> Text
58+identCharToString c | isAlphaNum c = singleton c
5559identCharToString '_' = "_"
5660identCharToString '.' = "_"
5761identCharToString '\'' = "_prime"
58−identCharToString c = "$0" ++ show (ord c)
62+identCharToString c = "$0" <> (pack . show $ ord c)
5963
6064-- |
6165-- Checks whether an identifier name is reserved in C++11.
6266--
63−nameIsCppReserved :: String -> Bool
67+nameIsCppReserved :: Text -> Bool
6468nameIsCppReserved name =
6569 name `elem` [ "alignas"
6670 , "alignof"
@@ -172,19 +176,23 @@ nameIsCppReserved name =
172176 , "xor"
173177 , "xor_eq" ] || properNameIsCppReserved name
174178
175−normalizedName :: String -> String
176−normalizedName ('_' : s) | last s == '_', s' <- init s, nameIsCppReserved s' = s'
179+normalizedName :: Text -> Text
180+normalizedName name
181+ | Just ('_', s) <- uncons name
182+ , last s == '_'
183+ , s' <- init s
184+ , nameIsCppReserved s' = s'
177185normalizedName s = s
178186
179−moduleNameToCpp :: ModuleName -> String
187+moduleNameToCpp :: ModuleName -> Text
180188moduleNameToCpp (ModuleName pns) =
181− let name = intercalate "_" (runProperName `map` pns)
182− in if properNameIsCppReserved name then '_' : name ++ "_" else name
189+ let name = T.intercalate "_" (runProperName `map` pns)
190+ in if properNameIsCppReserved name then "_" <> name <> "_" else name
183191
184192-- |
185193-- Checks whether a proper name is reserved in C++11.
186194--
187−properNameIsCppReserved :: String -> Bool
195+properNameIsCppReserved :: Text -> Bool
188196properNameIsCppReserved name =
189197 name `elem` [ "Private"
190198 , "PureScript" ]
src/Language/PureScript/CodeGen/Cpp/File.hs+10−7
@@ -13,12 +13,15 @@
1313--
1414-----------------------------------------------------------------------------
1515{-# LANGUAGE PatternGuards #-}
16+{-# LANGUAGE OverloadedStrings #-}
1617
1718module Language.PureScript.CodeGen.Cpp.File where
1819
1920import Prelude.Compat
2021
2122import Data.Maybe
23+import Data.Monoid ((<>))
24+import Data.Text (Text)
2225
2326import Language.PureScript.CodeGen.Cpp.AST
2427import Language.PureScript.CodeGen.Cpp.Types
@@ -160,15 +163,15 @@ maybeRemCaps (CppLambda [CaptureAll] args rtyp body@(CppBlock [CppReturn (CppVar
160163maybeRemCaps cpp = cpp
161164
162165---------------------------------------------------------------------------------------------------
163−fileBegin :: ModuleName -> String -> [Cpp]
166+fileBegin :: ModuleName -> Text -> [Cpp]
164167fileBegin mn suffix =
165− [CppRaw ("#ifndef " ++ fileModName mn suffix), CppRaw ("#define " ++ fileModName mn suffix)]
168+ [CppRaw ("#ifndef " <> fileModName mn suffix), CppRaw ("#define " <> fileModName mn suffix)]
166169
167−fileEnd :: ModuleName -> String -> [Cpp]
168−fileEnd mn suffix = [CppRaw ("#endif // " ++ fileModName mn suffix)]
170+fileEnd :: ModuleName -> Text -> [Cpp]
171+fileEnd mn suffix = [CppRaw ("#endif // " <> fileModName mn suffix)]
169172
170−fileModName :: ModuleName -> String -> String
171−fileModName mn suffix = P.dotsTo '_' (runModuleName mn ++ '_' : suffix)
173+fileModName :: ModuleName -> Text -> Text
174+fileModName mn suffix = P.dotsTo '_' (runModuleName mn <> "_" <> suffix)
172175
173176isMain :: ModuleName -> Bool
174177isMain (ModuleName [ProperName "Main"]) = True
@@ -178,7 +181,7 @@ nativeMain :: Cpp
178181nativeMain =
179182 CppFunction
180183 "main"
181− [([], Just $ Primitive "int"), ([], Just $ Primitive "char *[]")]
184+ [("", Just $ Primitive "int"), ("", Just $ Primitive "char *[]")]
182185 (Just $ Primitive "int")
183186 []
184187 (CppBlock
src/Language/PureScript/CodeGen/Cpp/Optimizer/Common.hs+11−10
@@ -18,25 +18,26 @@ module Language.PureScript.CodeGen.Cpp.Optimizer.Common where
1818import Prelude.Compat
1919
2020import Data.Maybe (fromMaybe)
21+import Data.Text (Text, cons)
2122
2223import Language.PureScript.CodeGen.Cpp.AST
2324
2425applyAll :: [a -> a] -> a -> a
2526applyAll = foldl1 (.)
2627
27−replaceIdent :: String -> Cpp -> Cpp -> Cpp
28+replaceIdent :: Text -> Cpp -> Cpp -> Cpp
2829replaceIdent var1 cpp = everywhereOnCpp replace
2930 where
3031 replace (CppVar var2) | var1 == var2 = cpp
3132 replace other = other
3233
33−replaceIdents :: [(String, Cpp)] -> Cpp -> Cpp
34+replaceIdents :: [(Text, Cpp)] -> Cpp -> Cpp
3435replaceIdents vars = everywhereOnCpp replace
3536 where
3637 replace v@(CppVar var) = fromMaybe v $ lookup var vars
3738 replace other = other
3839
39−isReassigned :: String -> Cpp -> Bool
40+isReassigned :: Text -> Cpp -> Bool
4041isReassigned var1 = everythingOnCpp (||) check
4142 where
4243 check :: Cpp -> Bool
@@ -51,7 +52,7 @@ isRebound cpp d = any (\v -> isReassigned v d || isUpdated v d) (everythingOnCpp
5152 variablesOf (CppVar var) = [var]
5253 variablesOf _ = []
5354
54−isUsed :: String -> Cpp -> Bool
55+isUsed :: Text -> Cpp -> Bool
5556isUsed var1 = everythingOnCpp (||) check
5657 where
5758 check :: Cpp -> Bool
@@ -59,14 +60,14 @@ isUsed var1 = everythingOnCpp (||) check
5960 check (CppAssignment target _) | var1 == targetVariable target = True
6061 check _ = False
6162
62−targetVariable :: Cpp -> String
63+targetVariable :: Cpp -> Text
6364targetVariable (CppVar var) = var
6465targetVariable (CppAccessor _ tgt) = targetVariable tgt
6566targetVariable (CppIndexer _ tgt) = targetVariable tgt
6667targetVariable (CppGet _ tgt) = targetVariable tgt
6768targetVariable _ = error "Invalid argument to targetVariable"
6869
69−isUpdated :: String -> Cpp -> Bool
70+isUpdated :: Text -> Cpp -> Bool
7071isUpdated var1 = everythingOnCpp (||) check
7172 where
7273 check :: Cpp -> Bool
@@ -77,16 +78,16 @@ removeFromBlock :: ([Cpp] -> [Cpp]) -> Cpp -> Cpp
7778removeFromBlock go (CppBlock sts) = CppBlock (go sts)
7879removeFromBlock _ cpp = cpp
7980
80−isFn :: (String, String) -> Cpp -> Bool
81+isFn :: (Text, Text) -> Cpp -> Bool
8182isFn (moduleName, fnName) (CppAccessor (CppVar x) (CppVar y)) =
82− (x == fnName || x == ('$':fnName)) && y == moduleName
83+ (x == fnName || x == ('$' `cons` fnName)) && y == moduleName
8384isFn (moduleName, fnName) (CppIndexer (CppStringLiteral x) (CppVar y)) =
8485 x == fnName && y == moduleName
8586isFn _ _ = False
8687
87−isDict :: (String, String) -> Cpp -> Bool
88+isDict :: (Text, Text) -> Cpp -> Bool
8889isDict (moduleName, dictName) (CppAccessor (CppVar x) (CppVar y)) = x == dictName && y == moduleName
8990isDict _ _ = False
9091
91−isDict' :: [(String, String)] -> Cpp -> Bool
92+isDict' :: [(Text, Text)] -> Cpp -> Bool
9293isDict' xs cpp = any (`isDict` cpp) xs
src/Language/PureScript/CodeGen/Cpp/Optimizer/Inliner.hs+51−47
@@ -12,6 +12,9 @@
1212-- This module provides basic inlining capabilities
1313--
1414-----------------------------------------------------------------------------
15+{-# LANGUAGE PatternGuards #-}
16+{-# LANGUAGE OverloadedStrings #-}
17+
1518module Language.PureScript.CodeGen.Cpp.Optimizer.Inliner
1619 ( inlineVariables
1720 , inlineCommonValues
@@ -25,6 +28,7 @@ module Language.PureScript.CodeGen.Cpp.Optimizer.Inliner
2528 ) where
2629
2730import Prelude.Compat
31+import Data.Text (Text)
2832
2933import Control.Monad.Supply.Class (MonadSupply, freshName)
3034
@@ -127,7 +131,7 @@ inlineCommonValues = everywhereOnCpp convert
127131 fnMultiply = (C.dataSemiring, C.mul)
128132 fnSubtract = (C.dataRing, C.sub)
129133
130−inlineOperator :: (String, String) -> (Cpp -> Cpp -> Cpp) -> Cpp -> Cpp
134+inlineOperator :: (Text, Text) -> (Cpp -> Cpp -> Cpp) -> Cpp -> Cpp
131135inlineOperator (m, op) f = everywhereOnCpp convert
132136 where
133137 convert :: Cpp -> Cpp
@@ -200,28 +204,28 @@ inlineCommonOperators = applyAll $
200204 []
201205 -- [ fn | i <- [0..10], fn <- [ mkFn i, runFn i ] ]
202206 where
203− binary :: (String, String) -> (String, String) -> BinaryOperator -> Cpp -> Cpp
207+ binary :: (Text, Text) -> (Text, Text) -> BinaryOperator -> Cpp -> Cpp
204208 binary dict fns op = everywhereOnCpp convert
205209 where
206210 convert :: Cpp -> Cpp
207211 convert (CppApp fn [dict', x, y]) | isDict dict dict' && isFn fns fn = CppBinary op x y
208212 convert (CppApp (CppApp (CppApp fn [dict']) [x]) [y]) | isDict dict dict' && isFn fns fn = CppBinary op x y
209213 convert other = other
210− binary' :: String -> String -> BinaryOperator -> Cpp -> Cpp
214+ binary' :: Text -> Text -> BinaryOperator -> Cpp -> Cpp
211215 binary' moduleName opString op = everywhereOnCpp convert
212216 where
213217 convert :: Cpp -> Cpp
214218 convert (CppApp fn [x, y]) | isFn (moduleName, opString) fn = CppBinary op x y
215219 convert (CppApp (CppApp fn [x]) [y]) | isFn (moduleName, opString) fn = CppBinary op x y
216220 convert other = other
217− unary :: (String, String) -> (String, String) -> UnaryOperator -> Cpp -> Cpp
221+ unary :: (Text, Text) -> (Text, Text) -> UnaryOperator -> Cpp -> Cpp
218222 unary dicts fns op = everywhereOnCpp convert
219223 where
220224 convert :: Cpp -> Cpp
221225 convert (CppApp fn [dict', x]) | isDict dicts dict' && isFn fns fn = CppUnary op x
222226 convert (CppApp (CppApp fn [dict']) [x]) | isDict dicts dict' && isFn fns fn = CppUnary op x
223227 convert other = other
224− unary' :: String -> String -> UnaryOperator -> Cpp -> Cpp
228+ unary' :: Text -> Text -> UnaryOperator -> Cpp -> Cpp
225229 unary' moduleName fnName op = everywhereOnCpp convert
226230 where
227231 convert :: Cpp -> Cpp
@@ -242,14 +246,14 @@ inlineCommonOperators = applyAll $
242246 -- Just (args, cpp) -> CppLambda [CaptureAll] args Nothing (CppBlock cpp)
243247 -- Nothing -> orig
244248 -- convert other = other
245− -- collectArgs :: Int -> [String] -> Cpp -> Maybe ([String], [Cpp])
249+ -- collectArgs :: Int -> [Text] -> Cpp -> Maybe ([Text], [Cpp])
246250 -- collectArgs 1 acc (CppLambda _ [oneArg] _ (CppBlock cpp)) | length acc == n - 1 = Just (reverse (oneArg : acc), cpp)
247251 -- collectArgs m acc (CppLambda _ [oneArg] _ (CppBlock [CppReturn ret])) = collectArgs (m - 1) (oneArg : acc) ret
248252 -- collectArgs _ _ _ = Nothing
249253 --
250− -- isNFn :: String -> Int -> Cpp -> Bool
251− -- isNFn prefix n (CppVar name) = name == (prefix ++ show n)
252− -- isNFn prefix n (CppAccessor _ name (CppVar dataFunction)) | dataFunction == C.dataFunction = name == (prefix ++ show n)
254+ -- isNFn :: Text -> Int -> Cpp -> Bool
255+ -- isNFn prefix n (CppVar name) = name == (prefix <> show n)
256+ -- isNFn prefix n (CppAccessor _ name (CppVar dataFunction)) | dataFunction == C.dataFunction = name == (prefix <> show n)
253257 -- isNFn _ _ _ = False
254258 --
255259 -- runFn :: Int -> Cpp -> Cpp
@@ -294,9 +298,9 @@ inlineFnComposition = everywhereOnCppTopDownM convert
294298 isFnCompose dict' fn = isDict semigroupoidFn dict' && isFn fnCompose fn
295299 isFnComposeFlipped :: Cpp -> Cpp -> Bool
296300 isFnComposeFlipped dict' fn = isDict semigroupoidFn dict' && isFn fnComposeFlipped fn
297− fnCompose :: (String, String)
301+ fnCompose :: (Text, Text)
298302 fnCompose = (C.controlSemigroupoid, C.compose)
299− fnComposeFlipped :: (String, String)
303+ fnComposeFlipped :: (Text, Text)
300304 fnComposeFlipped = (C.controlSemigroupoid, C.composeFlipped)
301305
302306toAutoVars :: Cpp -> Cpp
@@ -322,110 +326,110 @@ toAutoVars = everywhereOnCpp convert
322326 var t = CppVariableIntroduction (ident, (Just t)) qs (Just value)
323327 convert cpp = cpp
324328
325−semiringNumber :: (String, String)
329+semiringNumber :: (Text, Text)
326330semiringNumber = (C.dataSemiring, C.semiringNumber)
327331
328−semiringInt :: (String, String)
332+semiringInt :: (Text, Text)
329333semiringInt = (C.dataSemiring, C.semiringInt)
330334
331−ringNumber :: (String, String)
335+ringNumber :: (Text, Text)
332336ringNumber = (C.dataRing, C.ringNumber)
333337
334−ringInt :: (String, String)
338+ringInt :: (Text, Text)
335339ringInt = (C.dataRing, C.ringInt)
336340
337−euclideanRingNumber :: (String, String)
341+euclideanRingNumber :: (Text, Text)
338342euclideanRingNumber = (C.dataEuclideanRing, C.euclideanRingNumber)
339343
340−euclideanRingInt :: (String, String)
344+euclideanRingInt :: (Text, Text)
341345euclideanRingInt = (C.dataEuclideanRing, C.euclideanRingInt)
342346
343−eqNumber :: (String, String)
347+eqNumber :: (Text, Text)
344348eqNumber = (C.dataEq, C.eqNumber)
345349
346−eqInt :: (String, String)
350+eqInt :: (Text, Text)
347351eqInt = (C.dataEq, C.eqInt)
348352
349−eqString :: (String, String)
353+eqString :: (Text, Text)
350354eqString = (C.dataEq, C.eqString)
351355
352−eqChar :: (String, String)
356+eqChar :: (Text, Text)
353357eqChar = (C.dataEq, C.eqChar)
354358
355−eqBoolean :: (String, String)
359+eqBoolean :: (Text, Text)
356360eqBoolean = (C.dataEq, C.eqBoolean)
357361
358−ordBoolean :: (String, String)
362+ordBoolean :: (Text, Text)
359363ordBoolean = (C.dataOrd, C.ordBoolean)
360364
361−ordNumber :: (String, String)
365+ordNumber :: (Text, Text)
362366ordNumber = (C.dataOrd, C.ordNumber)
363367
364−ordInt :: (String, String)
368+ordInt :: (Text, Text)
365369ordInt = (C.dataOrd, C.ordInt)
366370
367−ordString :: (String, String)
371+ordString :: (Text, Text)
368372ordString = (C.dataOrd, C.ordString)
369373
370−ordChar :: (String, String)
374+ordChar :: (Text, Text)
371375ordChar = (C.dataOrd, C.ordChar)
372376
373−semigroupString :: (String, String)
377+semigroupString :: (Text, Text)
374378semigroupString = (C.dataSemigroup, C.semigroupString)
375379
376−boundedBoolean :: (String, String)
380+boundedBoolean :: (Text, Text)
377381boundedBoolean = (C.dataBounded, C.boundedBoolean)
378382
379−heytingAlgebraBoolean :: (String, String)
383+heytingAlgebraBoolean :: (Text, Text)
380384heytingAlgebraBoolean = (C.dataHeytingAlgebra, C.heytingAlgebraBoolean)
381385
382−semigroupoidFn :: (String, String)
386+semigroupoidFn :: (Text, Text)
383387semigroupoidFn = (C.controlSemigroupoid, C.semigroupoidFn)
384388
385−opAdd :: (String, String)
389+opAdd :: (Text, Text)
386390opAdd = (C.dataSemiring, C.add)
387391
388−opMul :: (String, String)
392+opMul :: (Text, Text)
389393opMul = (C.dataSemiring, C.mul)
390394
391−opEq :: (String, String)
395+opEq :: (Text, Text)
392396opEq = (C.dataEq, C.eq)
393397
394−opNotEq :: (String, String)
398+opNotEq :: (Text, Text)
395399opNotEq = (C.dataEq, C.notEq)
396400
397−opLessThan :: (String, String)
401+opLessThan :: (Text, Text)
398402opLessThan = (C.dataOrd, C.lessThan)
399403
400−opLessThanOrEq :: (String, String)
404+opLessThanOrEq :: (Text, Text)
401405opLessThanOrEq = (C.dataOrd, C.lessThanOrEq)
402406
403−opGreaterThan :: (String, String)
407+opGreaterThan :: (Text, Text)
404408opGreaterThan = (C.dataOrd, C.greaterThan)
405409
406−opGreaterThanOrEq :: (String, String)
410+opGreaterThanOrEq :: (Text, Text)
407411opGreaterThanOrEq = (C.dataOrd, C.greaterThanOrEq)
408412
409−opAppend :: (String, String)
413+opAppend :: (Text, Text)
410414opAppend = (C.dataSemigroup, C.append)
411415
412−opSub :: (String, String)
416+opSub :: (Text, Text)
413417opSub = (C.dataRing, C.sub)
414418
415−opNegate :: (String, String)
419+opNegate :: (Text, Text)
416420opNegate = (C.dataRing, C.negate)
417421
418−opDiv :: (String, String)
422+opDiv :: (Text, Text)
419423opDiv = (C.dataEuclideanRing, C.div)
420424
421−opMod :: (String, String)
425+opMod :: (Text, Text)
422426opMod = (C.dataEuclideanRing, C.mod)
423427
424−opConj :: (String, String)
428+opConj :: (Text, Text)
425429opConj = (C.dataHeytingAlgebra, C.conj)
426430
427−opDisj :: (String, String)
431+opDisj :: (Text, Text)
428432opDisj = (C.dataHeytingAlgebra, C.disj)
429433
430−opNot :: (String, String)
434+opNot :: (Text, Text)
431435opNot = (C.dataHeytingAlgebra, C.not)
src/Language/PureScript/CodeGen/Cpp/Optimizer/TCO.hs+14−10
@@ -12,13 +12,17 @@
1212-- This module implements tail call elimination.
1313--
1414-----------------------------------------------------------------------------
15+{-# LANGUAGE PatternGuards #-}
16+{-# LANGUAGE OverloadedStrings #-}
1517
1618module Language.PureScript.CodeGen.Cpp.Optimizer.TCO (tco) where
1719
1820import Prelude.Compat
1921
2022import Data.List
23+import Data.Monoid ((<>))
2124import qualified Data.Monoid as Monoid
25+import Data.Text (Text)
2226
2327import Language.PureScript.Options
2428import Language.PureScript.CodeGen.Cpp.Types
@@ -34,13 +38,13 @@ tco opts | optionsNoTco opts = id
3438tco' :: Cpp -> Cpp
3539tco' = everywhereOnCpp convert
3640 where
37− tcoVar :: String -> String
38− tcoVar arg = "__tco_" ++ arg
41+ tcoVar :: Text -> Text
42+ tcoVar arg = "__tco_" <> arg
3943
40− copyVar :: String -> String
41− copyVar arg = "__copy_" ++ arg
44+ copyVar :: Text -> Text
45+ copyVar arg = "__copy_" <> arg
4246
43− copyVar' :: (String, Maybe CppType) -> (String, Maybe CppType)
47+ copyVar' :: (Text, Maybe CppType) -> (Text, Maybe CppType)
4448 copyVar' (arg, t) = (copyVar arg, t)
4549
4650 convert :: Cpp -> Cpp
@@ -69,7 +73,7 @@ tco' = everywhereOnCpp convert
6973
7074 convert cpp = cpp
7175
72− collectAllFunctionArgs :: [[(String, Maybe CppType)]] -> (Cpp -> Cpp) -> Cpp -> ([[(String, Maybe CppType)]], Cpp, Cpp -> Cpp)
76+ collectAllFunctionArgs :: [[(Text, Maybe CppType)]] -> (Cpp -> Cpp) -> Cpp -> ([[(Text, Maybe CppType)]], Cpp, Cpp -> Cpp)
7377 collectAllFunctionArgs allArgs f (CppFunction ident args rty qs (CppBlock (body@(CppReturn _):_))) =
7478 collectAllFunctionArgs (args : allArgs) (\b -> f (CppFunction ident (map copyVar' args) rty qs (CppBlock [b]))) body
7579 collectAllFunctionArgs allArgs f (CppFunction ident args rty qs body@(CppBlock _)) =
@@ -80,7 +84,7 @@ tco' = everywhereOnCpp convert
8084 (args : allArgs, body, f . CppReturn . CppLambda cs (map copyVar' args) rty)
8185 collectAllFunctionArgs allArgs f body = (allArgs, body, f)
8286
83− isTailCall :: String -> Cpp -> Bool
87+ isTailCall :: Text -> Cpp -> Bool
8488 isTailCall ident cpp =
8589 let
8690 numSelfCalls = everythingOnCpp (+) countSelfCalls cpp
@@ -109,7 +113,7 @@ tco' = everywhereOnCpp convert
109113 countSelfCallsWithFnArgs :: Cpp -> Int
110114 countSelfCallsWithFnArgs ret = if isSelfCallWithFnArgs ident ret [] then 1 else 0
111115
112− toLoop :: String -> [String] -> Cpp -> Cpp
116+ toLoop :: Text -> [Text] -> Cpp -> Cpp
113117 toLoop ident allArgs cpp = CppBlock $
114118 map (\arg -> CppVariableIntroduction (arg, Just $ Any []) [] (Just (CppVar (copyVar arg)))) allArgs ++
115119 [ CppWhile (CppBooleanLiteral True) (CppBlock loop) ]
@@ -134,12 +138,12 @@ tco' = everywhereOnCpp convert
134138 collectSelfCallArgs allArgumentValues (CppApp fn args') = collectSelfCallArgs (args' : allArgumentValues) fn
135139 collectSelfCallArgs allArgumentValues _ = allArgumentValues
136140
137− isSelfCall :: String -> Cpp -> Bool
141+ isSelfCall :: Text -> Cpp -> Bool
138142 isSelfCall ident (CppApp (CppVar ident') _) = ident == ident'
139143 isSelfCall ident (CppApp fn _) = isSelfCall ident fn
140144 isSelfCall _ _ = False
141145
142− isSelfCallWithFnArgs :: String -> Cpp -> [Cpp] -> Bool
146+ isSelfCallWithFnArgs :: Text -> Cpp -> [Cpp] -> Bool
143147 isSelfCallWithFnArgs ident (CppVar ident') args | ident == ident' && any hasFunction args = True
144148 isSelfCallWithFnArgs ident (CppApp fn args) acc = isSelfCallWithFnArgs ident fn (args ++ acc)
145149 isSelfCallWithFnArgs _ _ _ = False
src/Language/PureScript/CodeGen/Cpp/Optimizer/Uncurry.hs+3−1
@@ -16,6 +16,7 @@
1616module Language.PureScript.CodeGen.Cpp.Optimizer.Uncurry where
1717
1818import Prelude.Compat
19+import Data.Text (uncons)
1920
2021import Language.PureScript.CodeGen.Cpp.AST
2122
@@ -37,7 +38,8 @@ removeCurrying nm = everywhereOnCpp convert
3738 unCurried :: Cpp -> Maybe Cpp
3839 unCurried (CppAccessor var mn)
3940 | Just var' <- unCurried var = Just $ CppAccessor var' mn
40− unCurried (CppVar ('$':name)) = Just $ CppVar name
41+ unCurried (CppVar name)
42+ | Just ('$', name') <- uncons name = Just $ CppVar name'
4143 unCurried _ = Nothing
4244 convert cpp = cpp
4345
src/Language/PureScript/CodeGen/Cpp/Types.hs+16−13
@@ -14,12 +14,15 @@
1414-----------------------------------------------------------------------------
1515{-# LANGUAGE PatternGuards #-}
1616{-# LANGUAGE DeriveDataTypeable #-}
17+{-# LANGUAGE OverloadedStrings #-}
1718
1819module Language.PureScript.CodeGen.Cpp.Types where
1920
2021import Prelude.Compat
2122
2223import Data.List
24+import Data.Monoid ((<>))
25+import Data.Text
2326
2427import Language.PureScript.CodeGen.Cpp.Common
2528import Language.PureScript.Names
@@ -27,7 +30,7 @@ import qualified Language.PureScript.Constants as C
2730
2831-- import Debug.Trace
2932
30−data CppType = Primitive String | Auto [TypeQual] | Any [TypeQual]
33+data CppType = Primitive Text | Auto [TypeQual] | Any [TypeQual]
3134 deriving (Show, Read, Eq)
3235
3336data TypeQual = Const | Ref
@@ -75,7 +78,7 @@ data CaptureType = CaptureAll
7578data MapType = Instance | Record
7679 deriving (Show, Eq)
7780
78−runType :: CppType -> String
81+runType :: CppType -> Text
7982runType (Primitive t) = t
8083runType (Auto []) = "auto"
8184runType (Any []) = "any"
@@ -86,11 +89,11 @@ runType typ =
8689 _ -> rendered Any []
8790 where
8891 rendered t qs
89− | Const `elem` qs = "const " ++ (runType . t $ delete Const qs)
90− | Ref `elem` qs = runType (t $ delete Ref qs) ++ "&"
92+ | Const `elem` qs = "const " <> (runType . t $ delete Const qs)
93+ | Ref `elem` qs = runType (t $ delete Ref qs) <> "&"
9194 | otherwise = runType (t qs)
9295
93−runValueQual :: ValueQual -> String
96+runValueQual :: ValueQual -> Text
9497runValueQual Static = "static"
9598runValueQual Inline = "inline"
9699runValueQual ConstExpr = "constexpr"
@@ -98,16 +101,16 @@ runValueQual Extern = "extern"
98101runValueQual Recursive = ""
99102runValueQual TopLevel = ""
100103
101−runCaptureType :: CaptureType -> String
104+runCaptureType :: CaptureType -> Text
102105runCaptureType CaptureAll = "="
103106
104107-- TODO: move or remove this
105108--
106−qualifiedToStr :: ModuleName -> (a -> Ident) -> Qualified a -> String
109+qualifiedToStr :: ModuleName -> (a -> Ident) -> Qualified a -> Text
107110qualifiedToStr _ f (Qualified (Just (ModuleName [ProperName mn])) a)
108111 | mn == C.prim = runIdent $ f a
109112qualifiedToStr m f (Qualified (Just m') a)
110− | m /= m' = moduleNameToCpp m' ++ "::" ++ identToCpp (f a)
113+ | m /= m' = moduleNameToCpp m' <> "::" <> identToCpp (f a)
111114qualifiedToStr _ f (Qualified _ a) = identToCpp (f a)
112115
113116boolType :: CppType
@@ -132,11 +135,11 @@ mapType :: Int -> CppType
132135mapType = maptype
133136 where
134137 maptype 0 = mapprim "unknown_size"
135− maptype n = mapprim $ show n
136− mapprim s = Primitive $ "any::map<" ++ s ++ ">"
138+ maptype n = mapprim . pack $ show n
139+ mapprim s = Primitive $ "any::map<" <> s <> ">"
137140
138141dataType :: Int -> CppType
139−dataType n = Primitive $ "any::data<" ++ show n ++ ">"
142+dataType n = Primitive $ "any::data<" <> pack (show n) <> ">"
140143
141144arrayType :: CppType
142145arrayType = Primitive "any::array"
@@ -144,11 +147,11 @@ arrayType = Primitive "any::array"
144147thunkMarkerType :: CppType
145148thunkMarkerType = Primitive "any::as_thunk"
146149
147−ctorKey :: String
150+ctorKey :: Text
148151ctorKey = "constructor"
149152
150153constAnyRef :: Maybe CppType
151154constAnyRef = Just $ Any [Const, Ref]
152155
153−symbolname :: String -> String
156+symbolname :: Text -> Text
154157symbolname = identToCpp . Ident
src/Language/PureScript/CodeGen/Cpp/Unicode.hs+10−6
@@ -20,6 +20,7 @@ module Language.PureScript.CodeGen.Cpp.Unicode
2020
2121import Prelude.Compat
2222import Data.Char (isAscii, ord)
23+import Data.Text (Text, pack, unpack)
2324import Text.Printf (printf)
2425
2526import Language.PureScript.CodeGen.Cpp.AST
@@ -50,11 +51,14 @@ unicodeToUCNs (CppTypeAlias (s1,ss) t s2) =
5051unicodeToUCNs cpp = cpp
5152
5253---------------------------------------------------------------------------------------------------
53−toUcns :: String -> String
54+toUcns :: Text -> Text
5455---------------------------------------------------------------------------------------------------
55−toUcns s | any (not . isAscii) s = concatMap toUcn s
56+toUcns = pack . toUcns' . unpack
5657 where
57− toUcn :: Char -> String
58− toUcn c | isAscii c = [c]
59− toUcn c = printf "\\U%08x" $ ord c
60−toUcns s = s
58+ toUcns' :: String -> String
59+ toUcns' s | any (not . isAscii) s = concatMap toUcn s
60+ where
61+ toUcn :: Char -> String
62+ toUcn c | isAscii c = [c]
63+ toUcn c = printf "\\U%08x" $ ord c
64+ toUcns' s = s
src/Language/PureScript/Pretty/Cpp.hs+183−200
@@ -13,6 +13,7 @@
1313--
1414-----------------------------------------------------------------------------
1515{-# LANGUAGE PatternGuards #-}
16+{-# LANGUAGE OverloadedStrings #-}
1617{-# LANGUAGE CPP #-}
1718
1819module Language.PureScript.Pretty.Cpp
@@ -23,165 +24,158 @@ module Language.PureScript.Pretty.Cpp
2324
2425import Prelude.Compat
2526
26−import Data.Bits
2727import Data.Char
28−import Data.List
29−import Data.Maybe (catMaybes, fromMaybe)
28+import Data.Maybe (fromMaybe)
29+import Data.Text (Text)
30+import qualified Data.Text as T
31+import Data.Monoid ((<>))
32+
3033#if __GLASGOW_HASKELL__ < 710
3134import Control.Applicative
3235#endif
3336import Control.Arrow ((<+>))
3437import qualified Control.Arrow as A
3538import Control.Monad.State
39+import Numeric (showHex)
3640import Control.PatternArrows
3741
3842import Language.PureScript.CodeGen.Cpp.AST
3943import Language.PureScript.CodeGen.Cpp.Types
4044import Language.PureScript.Comments
4145import qualified Language.PureScript.Constants as C
42−import Numeric
43−import Text.Printf (printf)
44−
45−-- import Debug.Trace
46−---------------------------------------------------------------------------------------------------
47−-- TODO: Go back to using Pretty.Common? (will require some work)
48−--
49−newtype PrinterState = PrinterState
50− { indent :: Int
51− } deriving (Show, Read, Eq, Ord)
52−
53−-- |
54−-- Pretty print with a new indentation level
55−--
56−withIndent :: StateT PrinterState Maybe String -> StateT PrinterState Maybe String
57−withIndent action = do
58− modify $ \st -> st { indent = indent st + blockIndent }
59− result <- action
60− modify $ \st -> st { indent = indent st - blockIndent }
61− return result
46+import Language.PureScript.Pretty.Common (PrinterState(..), intercalate, parensT)
6247
6348-- |
6449-- Get the current indentation level
6550--
66−currentIndent :: StateT PrinterState Maybe String
51+currentIndent :: StateT PrinterState Maybe Text
6752currentIndent = do
6853 current <- get
69− return $ replicate (indent current) ' '
54+ return $ T.replicate (indent current) " "
7055
7156blockIndent :: Int
7257blockIndent = 2
7358
7459-- |
75−-- Wrap a string in parentheses
60+-- Pretty print with a new indentation level
7661--
77−parens :: String -> String
78−parens s = '(' : s ++ ")"
62+withIndent :: StateT PrinterState Maybe Text -> StateT PrinterState Maybe Text
63+withIndent action = do
64+ modify $ \st -> st { indent = indent st + blockIndent }
65+ result <- action
66+ modify $ \st -> st { indent = indent st - blockIndent }
67+ return result
7968
69+show' :: Show a => a -> Text
70+show' = T.pack . show
71+
72+---------------------------------------------------------------------------------------------------
73+literals :: Pattern PrinterState Cpp Text
8074---------------------------------------------------------------------------------------------------
81−literals :: Pattern PrinterState Cpp String
8275literals = mkPattern' match
8376 where
84− match :: Cpp -> StateT PrinterState Maybe String
85− match CppNoOp = return []
86− match CppEndOfHeader = return []
87− match (CppNumericLiteral (Left n)) = return $ show n
88− match (CppNumericLiteral n) = return $ either show show n
77+ match :: Cpp -> StateT PrinterState Maybe Text
78+ match CppNoOp = return ""
79+ match CppEndOfHeader = return ""
80+ match (CppNumericLiteral (Left n)) = return $ show' n
81+ match (CppNumericLiteral n) = return $ either show' show' n
8982 match (CppStringLiteral s)
90− | all isAscii s = return $ string s
91− match (CppStringLiteral s) = return $ "u8" ++ string s
92− match (CppCharLiteral c) = return $ show c
83+ | T.all isAscii s = return $ string s
84+ match (CppStringLiteral s) = return $ "u8" <> string s
85+ match (CppCharLiteral c) = return $ "'" <> T.singleton c <> "'"
9386 match (CppBooleanLiteral True) = return "true"
9487 match (CppBooleanLiteral False) = return "false"
9588 match (CppArrayLiteral [x@CppArrayLiteral {}]) = -- Works around what appears to be a recent clang bug
96− fmap concat $ sequence
89+ mconcat <$> sequence
9790 [ return $ runType arrayType
9891 , return "{ { "
9992 , prettyPrintCpp' x
10093 , return " } }"
10194 ]
102− match (CppArrayLiteral xs) = fmap concat $ sequence
95+ match (CppArrayLiteral xs) = mconcat <$> sequence
10396 [ return $ runType arrayType
10497 , return "{ "
105− , fmap (intercalate ", ") $ forM xs prettyPrintCpp'
98+ , fmap (T.intercalate ", ") $ forM xs prettyPrintCpp'
10699 , return " }"
107100 ]
108− match (CppDataLiteral xs) = fmap concat $ sequence
101+ match (CppDataLiteral xs) = mconcat <$> sequence
109102 [ return $ runType (dataType $ length xs)
110103 , return "{ "
111− , fmap (intercalate ", ") $ forM xs prettyPrintCpp'
104+ , fmap (T.intercalate ", ") $ forM xs prettyPrintCpp'
112105 , return " }"
113106 ]
114− match (CppEnum name ty es) = fmap concat $ sequence
107+ match (CppEnum name ty es) = mconcat <$> sequence
115108 [ return "enum"
116− , return $ maybe "" (" " ++) name
117− , return $ maybe "" ((" : " ++) . runType) ty
109+ , return $ maybe "" (" " <>) name
110+ , return $ maybe "" ((" : " <>) . runType) ty
118111 , return " { "
119− , return $ intercalate ", " es
112+ , return $ T.intercalate ", " es
120113 , return " }"
121114 ]
122− match (CppMapLiteral _ ps) = fmap concat $ sequence
123− [ return $ runType (mapType $ length ps + 1) ++ "{{\n"
115+ match (CppMapLiteral _ ps) = mconcat <$> sequence
116+ [ return $ runType (mapType $ length ps + 1) <> "{{\n"
124117 , withIndent $ do
125118 cpps <-
126119 forM ps $ \(key, value) -> do
127120 value' <- prettyPrintCpp' value
128121 key' <- prettyPrintCpp' key
129− return $ "{ " ++ key' ++ ", " ++ value' ++ " }"
122+ return $ "{ " <> key' <> ", " <> value' <> " }"
130123 indentString <- currentIndent
131− return $ intercalate ", \n" $ map (indentString ++) (cpps ++ ["{ nullptr, nullptr }"])
124+ return $ T.intercalate ", \n" $ map (indentString <>) (cpps ++ ["{ nullptr, nullptr }"])
132125 , return "\n"
133126 , currentIndent
134127 , return "}}"
135128 ]
136− match (CppFunction name args rty qs ret) =
137− fmap concat $ sequence
138− [ return . concatMap (++ " ") . filter (not . null) $ runValueQual <$> qs
129+ match (CppFunction name args rty qs ret) = mconcat <$> sequence
130+ [ return . T.concat . fmap (<> " ") . filter (not . T.null) $ runValueQual <$> qs
139131 , return "auto "
140132 , return name
141− , return $ parens (intercalate ", " $ argstr <$> args)
142− , return (maybe "" ((" -> " ++) . runType) rty)
133+ , return $ parensT (T.intercalate ", " $ argstr <$> args)
134+ , return (maybe "" ((" -> " <>) . runType) rty)
143135 , if ret /= CppNoOp
144136 then do
145137 cpps <- prettyPrintCpp' ret
146− return $ ' ' : cpps
138+ return $ ' ' `T.cons` cpps
147139 else return ""
148140 ]
149− match (CppBlock sts) = concat <$> sequence
141+ match (CppBlock sts) = mconcat <$> sequence
150142 [ return "{\n"
151143 , withIndent $ prettyStatements sts
152144 , return $ if null sts then "" else "\n"
153145 , currentIndent
154146 , return "}"
155147 ]
156− match (CppNamespace _ []) = return []
157− match (CppNamespace [] sts) = fmap concat $ sequence $
148+ match (CppNamespace _ []) = return ""
149+ match (CppNamespace name sts) | T.null name = mconcat <$> sequence
158150 [ return "\n"
159151 , prettyStatements sts
160152 , return "#"
161153 ]
162− match (CppNamespace (':':':':name) sts) = fmap concat $ sequence $
154+ match (CppNamespace name sts)
155+ | Just name' <- T.stripPrefix "::" name = mconcat <$> sequence
163156 [ return "\n"
164157 , currentIndent
165− , return $ "namespace " ++ (dotsTo '_' name) ++ " {\n"
158+ , return $ "namespace " <> (dotsTo '_' name') <> " {\n"
166159 , withIndent $ prettyStatements sts
167160 , return "\n"
168161 , currentIndent
169162 , return "}#"
170163 ]
171− match (CppNamespace name sts) = fmap concat $ sequence $
164+ match (CppNamespace name sts) = mconcat <$> sequence (
172165 [ return "\n"
173166 , currentIndent
174− , return $ "namespace " ++ (dotsTo '_' name) ++ " {\n"
167+ , return $ "namespace " <> (dotsTo '_' name) <> " {\n"
175168 , withIndent $ prettyStatements sts'
176169 , return "\n"
177170 , currentIndent
178171 , return "}#"
179− ] ++
172+ ] <>
180173 let (cpp', cpps') = fromNested nested'
181174 in map match cpp' ++
182175 if null cpps'
183176 then []
184− else [match (CppNamespace name (filter isUseNamespace sts ++ cpps'))]
177+ else [match (CppNamespace name (filter isUseNamespace sts <> cpps'))]
178+ )
185179 where
186180 (sts', nested') = break isNestedNamespace sts
187181 fromNested :: [Cpp] -> ([Cpp], [Cpp])
@@ -201,11 +195,11 @@ literals = mkPattern' match
201195 isUseNamespace :: Cpp -> Bool
202196 isUseNamespace (CppUseNamespace {}) = True
203197 isUseNamespace _ = False
204− match (CppStruct (name) []) = return $ "struct " ++ name ++ " {}"
205− match (CppStruct (name) mems) = fmap concat $ sequence $
198+ match (CppStruct (name) []) = return $ "struct " <> name <> " {}"
199+ match (CppStruct (name) mems) = mconcat <$> sequence
206200 [ return "\n"
207201 , currentIndent
208− , return $ "struct " ++ name ++ " {\n"
202+ , return $ "struct " <> name <> " {\n"
209203 , withIndent $ prettyStatements mems
210204 , return "\n"
211205 , currentIndent
@@ -213,60 +207,60 @@ literals = mkPattern' match
213207 ]
214208 match (CppInclude path name) =
215209 let fullpath
216− | null path = last . words . dotsTo ' ' $ name
217− | otherwise = path ++ '/' : (last . words . dotsTo ' ' $ name) in
218− fmap concat $ sequence
219− [ return $ "#include \"" ++ fullpath ++ ".hh\""
210+ | T.null path = last . T.words . dotsTo ' ' $ name
211+ | otherwise = path <> "/" <> (last . T.words . dotsTo ' ' $ name) in
212+ mconcat <$> sequence
213+ [ return $ "#include \"" <> fullpath <> ".hh\""
220214 ]
221− match (CppUseNamespace name) = fmap concat $ sequence
222− [ return $ "using namespace " ++ (dotsTo '_' name)
215+ match (CppUseNamespace name) = mconcat <$> sequence
216+ [ return $ "using namespace " <> (dotsTo '_' name)
223217 ]
224218 match (CppTypeAlias (newName, newTyps) typ spec) =
225219 let typ' = runType typ
226220 (tmps, name') = if null newTyps
227221 then ([], typ')
228222 else ([return (templDecl newTyps), return "\n", currentIndent], typ')
229− in fmap concat $ sequence $
223+ in mconcat <$> sequence (
230224 tmps ++
231− [ return $ "using "
225+ [ return "using "
232226 , return newName
233227 , return " = "
234− , return $ if null spec then name' else spec ++ angles name'
235− ]
228+ , return $ if T.null spec then name' else spec <> angles name'
229+ ])
236230 match (CppCast typ val) = return $
237231 case val of
238232 CppNumericLiteral {} -> vstr
239233 CppStringLiteral {} -> vstr
240234 CppBooleanLiteral {} -> vstr
241− _ -> "cast" ++ angles (runType typ) ++ parens val'
235+ _ -> "cast" <> angles (runType typ) <> parensT val'
242236 where
243237 vstr = prettyPrintCpp1 val
244− val' | '(' `elem` vstr || '[' `elem` vstr = parens vstr
238+ val' | "(" `T.isInfixOf` vstr || "[" `T.isInfixOf` vstr = parensT vstr
245239 | otherwise = vstr
246240 match (CppGet i@(CppSymbol _) val) =
247− return $ printf "get(%s, %s)" (prettyPrintCpp1 i) (prettyPrintCpp1 val)
241+ return . prettyPrintCpp1 $ CppApp (CppVar "get") [i, val]
248242 match (CppGet i val) =
249− return $ printf "get<%s>(%s)" (prettyPrintCpp1 i) (prettyPrintCpp1 val)
243+ return . prettyPrintCpp1 $ CppApp (CppVar $ "get" <> angles (prettyPrintCpp1 i)) [val]
250244 match (CppVar ident)
251− | ident == C.__unused = match (CppVar $ '$' : ident)
245+ | ident == C.__unused = match (CppVar $ '$' `T.cons` ident)
252246 match (CppVar ident) = return ident
253− match (CppSymbol ident) = return $ "SYMBOL" ++ parens (symbolname ident)
247+ match (CppSymbol ident) = return $ "SYMBOL" <> parensT (symbolname ident)
254248 match (CppApp v [CppNoOp]) = return (prettyPrintCpp1 v)
255249 match (CppVariableIntroduction (ident, typ) qs value)
256− | ident == C.__unused = match (CppVariableIntroduction ('$' : ident, typ) qs value)
250+ | ident == C.__unused = match (CppVariableIntroduction ('$' `T.cons` ident, typ) qs value)
257251 match (CppVariableIntroduction (ident, typ) qs value) =
258− fmap concat $ sequence
259− [ return . concatMap (++ " ") . filter (not . null) $ runValueQual <$> qs
260− , return $ runType (fromMaybe (Any [Const]) typ) ++ " "
252+ mconcat <$> sequence
253+ [ return . T.concat . fmap (<> " ") . filter (not . T.null) $ runValueQual <$> qs
254+ , return $ runType (fromMaybe (Any [Const]) typ) <> " "
261255 , return ident
262− , maybe (return "") (fmap (" = " ++) . prettyPrintCpp') value
256+ , maybe (return "") (fmap (" = " <>) . prettyPrintCpp') value
263257 ]
264− match (CppAssignment target value) = fmap concat $ sequence
258+ match (CppAssignment target value) = mconcat <$> sequence
265259 [ prettyPrintCpp' target
266260 , return " = "
267261 , prettyPrintCpp' value
268262 ]
269− match (CppWhile cond sts) = fmap concat $ sequence
263+ match (CppWhile cond sts) = mconcat <$> sequence
270264 [ return "while ("
271265 , prettyPrintCpp' cond
272266 , return ") "
@@ -276,24 +270,24 @@ literals = mkPattern' match
276270 sts' | CppBlock cpps'@(_:_) <- sts,
277271 last cpps' == CppContinue = CppBlock (init cpps')
278272 | otherwise = sts
279− match (CppIfElse cond thens elses) = fmap concat $ sequence
273+ match (CppIfElse cond thens elses) = mconcat <$> sequence
280274 [ return "if ("
281275 , prettyPrintCpp' cond
282276 , return ") "
283277 , prettyPrintCpp' thens
284− , maybe (return "") (fmap (" else " ++) . prettyPrintCpp') elses
278+ , maybe (return "") (fmap (" else " <>) . prettyPrintCpp') elses
285279 ]
286− match (CppSwitch cond cases@((case1,_):_:_)) = fmap concat $ sequence
280+ match (CppSwitch cond cases@((case1,_):_:_)) = mconcat <$> sequence
287281 [ return "switch "
288− , return . parens $ prettyPrintCpp1 (cast case1 cond)
282+ , return . parensT $ prettyPrintCpp1 (cast case1 cond)
289283 , return " {\n"
290284 , withIndent $ do
291285 cpps <- forM cases $ \(c, s) -> do
292286 c' <- prettyPrintCpp' c
293287 s' <- prettyPrintCpp' s
294− return $ "case " ++ c' ++ ": " ++ s' ++ ";"
288+ return $ "case " <> c' <> ": " <> s' <> ";"
295289 indentString <- currentIndent
296− return $ intercalate "\n" $ map (indentString ++) cpps
290+ return $ T.intercalate "\n" $ map (indentString <>) cpps
297291 , return "\n"
298292 , currentIndent
299293 , return "}"
@@ -304,71 +298,63 @@ literals = mkPattern' match
304298 cast CppBooleanLiteral {} cpp' = CppCast boolType cpp'
305299 cast CppCharLiteral {} cpp' = CppCast charType cpp'
306300 cast _ cpp' = cpp'
307− match (CppReturn (CppBlock (cpp:cpps))) = fmap concat $ sequence
301+ match (CppReturn (CppBlock (cpp:cpps))) = mconcat <$> sequence
308302 [ do s <- prettyPrintCpp' cpp
309− return $ dropWhile isSpace s
303+ return $ T.dropWhile isSpace s
310304 , return $ if null cpps then "" else "\n"
311305 , prettyStatements cpps
312306 ]
313− match (CppReturn value@(CppStringLiteral _)) = fmap concat $ sequence
307+ match (CppReturn value@(CppStringLiteral _)) = mconcat <$> sequence
314308 [ return "return "
315309 , return . runType $ Any []
316310 , return "("
317311 , prettyPrintCpp' value
318312 , return ")"
319313 ]
320− match (CppReturn value) = fmap concat $ sequence
314+ match (CppReturn value) = mconcat <$> sequence
321315 [ return "return "
322316 , prettyPrintCpp' value
323317 ]
324− match (CppThrow value) = fmap concat $ sequence
318+ match (CppThrow value) = mconcat <$> sequence
325319 [ return "throw "
326320 , prettyPrintCpp' value
327321 ]
328322 match CppContinue = return "continue"
329323 match (CppComment [] cpp) = match cpp
330− match (CppComment com cpp) = fmap concat $ sequence $
331− [ return "\n"
324+ match (CppComment com cpp) = mconcat <$> sequence
325+ ([ return "\n"
332326 , currentIndent
333327 , return "/**\n"
334− ] ++
335− map asLine (concatMap commentLines com) ++
328+ ] <>
329+ map asLine (concat $ commentLines <$> com) ++
336330 [ currentIndent
337331 , return " */\n"
338332 , currentIndent
339333 , prettyPrintCpp' cpp
340− ]
334+ ])
341335 where
342− commentLines :: Comment -> [String]
336+ commentLines :: Comment -> [Text]
343337 commentLines (LineComment s) = [s]
344− commentLines (BlockComment s) = lines s
345− asLine :: String -> StateT PrinterState Maybe String
338+ commentLines (BlockComment s) = T.lines s
339+ asLine :: Text -> StateT PrinterState Maybe Text
346340 asLine s = do
347341 i <- currentIndent
348− return $ i ++ " * " ++ removeComments s ++ "\n"
349− removeComments :: String -> String
350− removeComments ('*':'/':s) = removeComments s
351− removeComments (c:s) = c : removeComments s
352− removeComments [] = []
342+ return $ i <> " * " <> removeComments s <> "\n"
343+
344+ removeComments :: Text -> Text
345+ removeComments t =
346+ case T.stripPrefix "*/" t of
347+ Just rest -> removeComments rest
348+ Nothing -> case T.uncons t of
349+ Just (x, xs) -> x `T.cons` removeComments xs
350+ Nothing -> ""
353351 match (CppRaw cpp) = return cpp
354352 match _ = mzero
355353
356−string :: String -> String
357−string s = '"' : concatMap encodeChar (decodeSurrogates s) ++ "\""
354+string :: Text -> Text
355+string s = "\"" <> T.concatMap encodeChar s <> "\""
358356 where
359− decodeSurrogates :: String -> String
360− decodeSurrogates [c] = [c]
361− decodeSurrogates s' = catMaybes $ zipWith decodePair s' (tail s' ++ ['\0'])
362− where
363− decodePair :: Char -> Char -> Maybe Char
364− decodePair a b
365− | fromEnum a >= 0xD800 && fromEnum a <= 0xDFFF &&
366− fromEnum b >= 0xD800 && fromEnum b <= 0xDFFF
367− = Just . chr $ 0x10000 + shiftL (fromEnum a .&. 0x03FF) 10 + (fromEnum b .&. 0x03FF)
368− decodePair a _
369− | fromEnum a >= 0xD800 && fromEnum a <= 0xDFFF = Nothing
370− decodePair a _ = Just a
371− encodeChar :: Char -> String
357+ encodeChar :: Char -> Text
372358 encodeChar '\b' = "\\b"
373359 encodeChar '\t' = "\\t"
374360 encodeChar '\n' = "\\n"
@@ -377,73 +363,69 @@ string s = '"' : concatMap encodeChar (decodeSurrogates s) ++ "\""
377363 encodeChar '\r' = "\\r"
378364 encodeChar '"' = "\\\""
379365 encodeChar '\\' = "\\\\"
380− encodeChar c
381− | fromEnum c > 0xFFFF = "\\U" ++ leading ++ hex
382− where
383− hex = showHex (fromEnum c) ""
384− leading = replicate (8 - length hex) '0'
385− encodeChar c
386− | fromEnum c > 0xFFF = "\\u" ++ showHex (fromEnum c) ""
387− encodeChar c
388− | fromEnum c > 0xFF = "\\u0" ++ showHex (fromEnum c) ""
389− encodeChar c
390− | fromEnum c < 0x10 = "\\x0" ++ showHex (fromEnum c) ""
391− encodeChar c
392− | fromEnum c > 0x7E || fromEnum c < 0x20 = "\\x" ++ showHex (fromEnum c) ""
393− encodeChar c = [c]
394−
395−accessor :: Pattern PrinterState Cpp (String, Cpp)
366+ -- PureScript strings are sequences of UTF-16 code units, so this case should never be hit.
367+ -- If it is somehow hit, though, output the designated Unicode replacement character U+FFFD.
368+ encodeChar c | fromEnum c > 0xFFFF = "\\uFFFD"
369+ encodeChar c | fromEnum c > 0xFFF = "\\u" <> showHex' (fromEnum c) ""
370+ encodeChar c | fromEnum c > 0xFF = "\\u0" <> showHex' (fromEnum c) ""
371+ encodeChar c | fromEnum c < 0x10 = "\\x0" <> showHex' (fromEnum c) ""
372+ encodeChar c | fromEnum c > 0x7E || fromEnum c < 0x20 = "\\x" <> showHex' (fromEnum c) ""
373+ encodeChar c = T.singleton c
374+
375+ showHex' a b = T.pack (showHex a b)
376+
377+accessor :: Pattern PrinterState Cpp (Text, Cpp)
396378accessor = mkPattern match
397379 where
398380 match (CppAccessor prop val) = Just (prettyPrintCpp1 prop, val)
399381 match _ = Nothing
400382
401−indexer :: Pattern PrinterState Cpp (String, Cpp)
383+indexer :: Pattern PrinterState Cpp (Text, Cpp)
402384indexer = mkPattern' match
403385 where
404386 match (CppIndexer (CppNumericLiteral (Left 0)) val) = return ("0UL", val)
405− match (CppIndexer (CppNumericLiteral (Left index)) val) = return (show index, val)
387+ match (CppIndexer (CppNumericLiteral (Left index)) val) = return (show' index, val)
406388 match (CppIndexer index val) = do
407389 index' <- prettyPrintCpp' index
408390 return (index', val)
409391 match _ = mzero
410392
411−lam :: Pattern PrinterState Cpp ((String, [(String, Maybe CppType)], Maybe CppType), Cpp)
393+lam :: Pattern PrinterState Cpp ((Text, [(Text, Maybe CppType)], Maybe CppType), Cpp)
412394lam = mkPattern match
413395 where
414− match (CppLambda caps args rty ret) = Just ((concatMap runCaptureType caps, args, rty), ret)
396+ match (CppLambda caps args rty ret) = Just ((T.concat $ runCaptureType <$> caps, args, rty), ret)
415397 match _ = Nothing
416398
417−app :: Pattern PrinterState Cpp (String, Cpp)
399+app :: Pattern PrinterState Cpp (Text, Cpp)
418400app = mkPattern' match
419401 where
420402 match (CppApp _ [CppNoOp]) = mzero
421403 match (CppApp val args) = do
422404 cpps <- mapM prettyPrintCpp' args
423− return (intercalate ", " cpps, val)
405+ return (T.intercalate ", " cpps, val)
424406 match _ = mzero
425407
426−unary' :: UnaryOperator -> (Cpp -> String) -> Operator PrinterState Cpp String
427−unary' op mkStr = Wrap match (++)
408+unary' :: UnaryOperator -> (Cpp -> Text) -> Operator PrinterState Cpp Text
409+unary' op mkStr = Wrap match (<>)
428410 where
429− match :: Pattern PrinterState Cpp (String, Cpp)
411+ match :: Pattern PrinterState Cpp (Text, Cpp)
430412 match = mkPattern match'
431413 where
432414 match' (CppUnary op' val)
433415 | op' == op = Just (mkStr val, val)
434416 match' _ = Nothing
435417
436−unary :: UnaryOperator -> String -> Operator PrinterState Cpp String
418+unary :: UnaryOperator -> Text -> Operator PrinterState Cpp Text
437419unary op str = unary' op (const str)
438420
439−negateOperator :: Operator PrinterState Cpp String
421+negateOperator :: Operator PrinterState Cpp Text
440422negateOperator = unary' Negate (\v -> if isNegate v then "- " else "-")
441423 where
442424 isNegate (CppUnary Negate _) = True
443425 isNegate _ = False
444426
445−binary :: BinaryOperator -> String -> Operator PrinterState Cpp String
446−binary op str = AssocL match (\v1 v2 -> v1 ++ str ++ v2)
427+binary :: BinaryOperator -> Text -> Operator PrinterState Cpp Text
428+binary op str = AssocL match (\v1 v2 -> v1 <> str <> v2)
447429 where
448430 match :: Pattern PrinterState Cpp (Cpp, Cpp)
449431 match = mkPattern match'
@@ -454,53 +436,54 @@ binary op str = AssocL match (\v1 v2 -> v1 ++ str ++ v2)
454436 | op' == op = Just (v1, v2)
455437 match' _ = Nothing
456438
457−prettyStatements :: [Cpp] -> StateT PrinterState Maybe String
439+prettyStatements :: [Cpp] -> StateT PrinterState Maybe Text
458440prettyStatements sts = do
459441 cpps <- forM (filter (not . isNoOp) sts) prettyPrintCpp'
460442 indentString <- currentIndent
461− return $ intercalate "\n" $ map (addsemi . (indentString ++)) cpps
443+ return $ T.intercalate "\n" $ map (addsemi . (indentString <>)) cpps
462444 where
463− addsemi :: String -> String
464− addsemi [] = []
445+ addsemi :: Text -> Text
446+ addsemi s | T.null s = s
447+ addsemi s
448+ | T.all isSpace s = ""
465449 addsemi s
466− | all isSpace s = []
467− addsemi s@('#':_) = s
450+ | T.head s == '#' = s
468451 addsemi s
469− | last s == '#' = init s
470− addsemi s = s ++ ";"
452+ | T.last s == '#' = T.init s
453+ addsemi s = s <> ";"
471454
472455-- |
473456-- Generate a pretty-printed string representing a C++11 expression
474457--
475−prettyPrintCpp1 :: Cpp -> String
458+prettyPrintCpp1 :: Cpp -> Text
476459prettyPrintCpp1 = fromMaybe (error "Incomplete pattern") . flip evalStateT (PrinterState 0) . prettyPrintCpp'
477460
478461-- |
479462-- Generate a pretty-printed string representing a collection of C++11 expressions at the same indentation level
480463--
481−prettyPrintCpp :: [Cpp] -> String
464+prettyPrintCpp :: [Cpp] -> Text
482465prettyPrintCpp = fromMaybe (error "Incomplete pattern") . flip evalStateT (PrinterState 0) . prettyStatements
483466
484467-- |
485468-- Generate an indented, pretty-printed string representing a C++11 expression
486469--
487−prettyPrintCpp' :: Cpp -> StateT PrinterState Maybe String
470+prettyPrintCpp' :: Cpp -> StateT PrinterState Maybe Text
488471prettyPrintCpp' = A.runKleisli $ runPattern matchValue
489472 where
490− matchValue :: Pattern PrinterState Cpp String
491− matchValue = buildPrettyPrinter operators (literals <+> fmap parens matchValue)
492− operators :: OperatorTable PrinterState Cpp String
473+ matchValue :: Pattern PrinterState Cpp Text
474+ matchValue = buildPrettyPrinter operators (literals <+> fmap parensT matchValue)
475+ operators :: OperatorTable PrinterState Cpp Text
493476 operators =
494− OperatorTable [ [ Wrap accessor $ \prop val -> val ++ "::" ++ prop ]
495− , [ Wrap indexer $ \index val -> val ++ "[" ++ index ++ "]" ]
496− , [ Wrap app $ \args val -> val ++ parens args ]
477+ OperatorTable [ [ Wrap accessor $ \prop val -> val <> "::" <> prop ]
478+ , [ Wrap indexer $ \index val -> val <> "[" <> index <> "]" ]
479+ , [ Wrap app $ \args val -> val <> parensT args ]
497480 , [ unary New "new " ]
498− , [ Wrap lam $ \(caps, args, rty) ret -> '[' : caps ++ "]"
499− ++ let args' = argstr <$> args in
500− parens (intercalate ", " args')
501− ++ maybe "" ((" -> " ++) . runType) rty
502− ++ " "
503− ++ ret ]
481+ , [ Wrap lam $ \(caps, args, rty) ret -> '[' `T.cons` caps <> "]"
482+ <> let args' = argstr <$> args in
483+ parensT (T.intercalate ", " args')
484+ <> maybe "" ((" -> " <>) . runType) rty
485+ <> " "
486+ <> ret ]
504487 , [ unary Not "!"
505488 , unary BitwiseNot "~"
506489 , unary Positive "+"
@@ -526,35 +509,35 @@ prettyPrintCpp' = A.runKleisli $ runPattern matchValue
526509 , [ binary Or " || " ]
527510 ]
528511
529−dotsTo :: Char -> String -> String
530−dotsTo chr' = map (\c -> if c == '.' then chr' else c)
512+dotsTo :: Char -> Text -> Text
513+dotsTo chr' = T.map (\c -> if c == '.' then chr' else c)
531514
532−argstr :: (String, Maybe CppType) -> String
515+argstr :: (Text, Maybe CppType) -> Text
533516argstr (name, Nothing) = argStr name (Auto [])
534517argstr (name, Just typ)
535− | name == C.__unused = argStr [] typ
518+ | name == C.__unused = argStr "" typ
536519argstr (name, Just typ) = argStr name typ
537520
538−argStr :: String -> CppType -> String
539−argStr name typ =
540− runType typ ++
541− if null name
542− then []
543− else " " ++ name
521+argStr :: Text -> CppType -> Text
522+argStr name typ = runType typ <>
523+ if T.null name
524+ then ""
525+ else " " <> name
544526
545−templDecl :: [(String, Int)] -> String
546−templDecl ps = "template " ++ angles (intercalate ", " (go <$> ps))
527+templDecl :: [(Text, Int)] -> Text
528+templDecl ps = "template " <> angles (intercalate ", " (go <$> ps))
547529 where
548− go :: (String, Int) -> String
549− go (name, 0) = "typename " ++ name
550− go (name, n) = "typename" ++ parens (intercalate "," $ replicate n "typename") ++ ' ' : name
530+ go :: (Text, Int) -> Text
531+ go (name, 0) = "typename " <> name
532+ go (name, n) = "typename" <> parensT (intercalate "," $ replicate n "typename") <> (' ' `T.cons` name)
551533
552534isNestedNamespace :: Cpp -> Bool
553−isNestedNamespace (CppNamespace (':':':':_) _) = True
535+isNestedNamespace (CppNamespace name _)
536+ | "::" `T.isPrefixOf` name = True
554537isNestedNamespace _ = False
555538
556−angles :: String -> String
557−angles s = '<' : s ++ ">"
539+angles :: Text -> Text
540+angles s = "<" <> s <> ">"
558541
559542linebreak :: [Cpp]
560543linebreak = [CppRaw ""]