@@ -13,6 +13,7 @@
14-----------------------------------------------------------------------------
14-----------------------------------------------------------------------------
15{-# LANGUAGE PatternGuards #-}
15{-# LANGUAGE PatternGuards #-}
16+{-# LANGUAGE OverloadedStrings #-}
16{-# LANGUAGE CPP #-}
17{-# LANGUAGE CPP #-}
18module Language.PureScript.Pretty.Cpp
19module Language.PureScript.Pretty.Cpp
@@ -23,165 +24,158 @@ module Language.PureScript.Pretty.Cpp
24import Prelude.Compat
25import Prelude.Compat
27import Data.Char
27import Data.Char
28−import Data.List
28+import Data.Maybe (fromMaybe)
29−import Data.Maybe (catMaybes, fromMaybe)
29+import Data.Text (Text)
30+import qualified Data.Text as T
31+import Data.Monoid ((<>))
30#if __GLASGOW_HASKELL__ < 710
33#if __GLASGOW_HASKELL__ < 710
31import Control.Applicative
34import Control.Applicative
33import Control.Arrow ((<+>))
36import Control.Arrow ((<+>))
34import qualified Control.Arrow as A
37import qualified Control.Arrow as A
35import Control.Monad.State
38import Control.Monad.State
39+import Numeric (showHex)
36import Control.PatternArrows
40import Control.PatternArrows
38import Language.PureScript.CodeGen.Cpp.AST
42import Language.PureScript.CodeGen.Cpp.AST
39import Language.PureScript.CodeGen.Cpp.Types
43import Language.PureScript.CodeGen.Cpp.Types
40import Language.PureScript.Comments
44import Language.PureScript.Comments
41import qualified Language.PureScript.Constants as C
45import qualified Language.PureScript.Constants as C
42−import Numeric
46+import Language.PureScript.Pretty.Common (PrinterState(..), intercalate, parensT)
43−import Text.Printf (printf)
46−---------------------------------------------------------------------------------------------------
47−-- TODO: Go back to using Pretty.Common? (will require some work)
49−newtype PrinterState = PrinterState
51− } deriving (Show, Read, Eq, Ord)
54−-- Pretty print with a new indentation level
56−withIndent :: StateT PrinterState Maybe String -> StateT PrinterState Maybe String
57−withIndent action = do
58− modify $ \st -> st { indent = indent st + blockIndent }
60− modify $ \st -> st { indent = indent st - blockIndent }
64-- Get the current indentation level
49-- Get the current indentation level
66−currentIndent :: StateT PrinterState Maybe String
51+currentIndent :: StateT PrinterState Maybe Text
67currentIndent = do
52currentIndent = do
68 current <- get
53 current <- get
69− return $ replicate (indent current) ' '
54+ return $ T.replicate (indent current) " "
71blockIndent :: Int
56blockIndent :: Int
72blockIndent = 2
57blockIndent = 2
75−-- Wrap a string in parentheses
60+-- Pretty print with a new indentation level
77−parens :: String -> String
62+withIndent :: StateT PrinterState Maybe Text -> StateT PrinterState Maybe Text
78−parens s = '(' : s ++ ")"
63+withIndent action = do
64+ modify $ \st -> st { indent = indent st + blockIndent }
66+ modify $ \st -> st { indent = indent st - blockIndent }
69+show' :: Show a => a -> Text
72+---------------------------------------------------------------------------------------------------
73+literals :: Pattern PrinterState Cpp Text
80---------------------------------------------------------------------------------------------------
74---------------------------------------------------------------------------------------------------
81−literals :: Pattern PrinterState Cpp String
82literals = mkPattern' match
75literals = mkPattern' match
84− match :: Cpp -> StateT PrinterState Maybe String
77+ match :: Cpp -> StateT PrinterState Maybe Text
85− match CppNoOp = return []
78+ match CppNoOp = return ""
86− match CppEndOfHeader = return []
79+ match CppEndOfHeader = return ""
87− match (CppNumericLiteral (Left n)) = return $ show n
80+ match (CppNumericLiteral (Left n)) = return $ show' n
88− match (CppNumericLiteral n) = return $ either show show n
81+ match (CppNumericLiteral n) = return $ either show' show' n
89 match (CppStringLiteral s)
82 match (CppStringLiteral s)
90− | all isAscii s = return $ string s
83+ | T.all isAscii s = return $ string s
91− match (CppStringLiteral s) = return $ "u8" ++ string s
84+ match (CppStringLiteral s) = return $ "u8" <> string s
92− match (CppCharLiteral c) = return $ show c
85+ match (CppCharLiteral c) = return $ "'" <> T.singleton c <> "'"
93 match (CppBooleanLiteral True) = return "true"
86 match (CppBooleanLiteral True) = return "true"
94 match (CppBooleanLiteral False) = return "false"
87 match (CppBooleanLiteral False) = return "false"
95 match (CppArrayLiteral [x@CppArrayLiteral {}]) = -- Works around what appears to be a recent clang bug
88 match (CppArrayLiteral [x@CppArrayLiteral {}]) = -- Works around what appears to be a recent clang bug
96− fmap concat $ sequence
89+ mconcat <$> sequence
97 [ return $ runType arrayType
90 [ return $ runType arrayType
98 , return "{ { "
91 , return "{ { "
99 , prettyPrintCpp' x
92 , prettyPrintCpp' x
100 , return " } }"
93 , return " } }"
102− match (CppArrayLiteral xs) = fmap concat $ sequence
95+ match (CppArrayLiteral xs) = mconcat <$> sequence
103 [ return $ runType arrayType
96 [ return $ runType arrayType
104 , return "{ "
97 , return "{ "
105− , fmap (intercalate ", ") $ forM xs prettyPrintCpp'
98+ , fmap (T.intercalate ", ") $ forM xs prettyPrintCpp'
106 , return " }"
99 , return " }"
108− match (CppDataLiteral xs) = fmap concat $ sequence
101+ match (CppDataLiteral xs) = mconcat <$> sequence
109 [ return $ runType (dataType $ length xs)
102 [ return $ runType (dataType $ length xs)
110 , return "{ "
103 , return "{ "
111− , fmap (intercalate ", ") $ forM xs prettyPrintCpp'
104+ , fmap (T.intercalate ", ") $ forM xs prettyPrintCpp'
112 , return " }"
105 , return " }"
114− match (CppEnum name ty es) = fmap concat $ sequence
107+ match (CppEnum name ty es) = mconcat <$> sequence
115 [ return "enum"
108 [ return "enum"
116− , return $ maybe "" (" " ++) name
109+ , return $ maybe "" (" " <>) name
117− , return $ maybe "" ((" : " ++) . runType) ty
110+ , return $ maybe "" ((" : " <>) . runType) ty
118 , return " { "
111 , return " { "
119− , return $ intercalate ", " es
112+ , return $ T.intercalate ", " es
120 , return " }"
113 , return " }"
122− match (CppMapLiteral _ ps) = fmap concat $ sequence
115+ match (CppMapLiteral _ ps) = mconcat <$> sequence
123− [ return $ runType (mapType $ length ps + 1) ++ "{{\n"
116+ [ return $ runType (mapType $ length ps + 1) <> "{{\n"
124 , withIndent $ do
117 , withIndent $ do
126 forM ps $ \(key, value) -> do
119 forM ps $ \(key, value) -> do
127 value' <- prettyPrintCpp' value
120 value' <- prettyPrintCpp' value
128 key' <- prettyPrintCpp' key
121 key' <- prettyPrintCpp' key
129− return $ "{ " ++ key' ++ ", " ++ value' ++ " }"
122+ return $ "{ " <> key' <> ", " <> value' <> " }"
130 indentString <- currentIndent
123 indentString <- currentIndent
131− return $ intercalate ", \n" $ map (indentString ++) (cpps ++ ["{ nullptr, nullptr }"])
124+ return $ T.intercalate ", \n" $ map (indentString <>) (cpps ++ ["{ nullptr, nullptr }"])
132 , return "\n"
125 , return "\n"
133 , currentIndent
126 , currentIndent
134 , return "}}"
127 , return "}}"
136− match (CppFunction name args rty qs ret) =
129+ match (CppFunction name args rty qs ret) = mconcat <$> sequence
137− fmap concat $ sequence
138− [ return . concatMap (++ " ") . filter (not . null) $ runValueQual <$> qs
130+ [ return . T.concat . fmap (<> " ") . filter (not . T.null) $ runValueQual <$> qs
139 , return "auto "
131 , return "auto "
140 , return name
132 , return name
141− , return $ parens (intercalate ", " $ argstr <$> args)
133+ , return $ parensT (T.intercalate ", " $ argstr <$> args)
142− , return (maybe "" ((" -> " ++) . runType) rty)
134+ , return (maybe "" ((" -> " <>) . runType) rty)
143 , if ret /= CppNoOp
135 , if ret /= CppNoOp
145 cpps <- prettyPrintCpp' ret
137 cpps <- prettyPrintCpp' ret
146− return $ ' ' : cpps
138+ return $ ' ' `T.cons` cpps
147 else return ""
139 else return ""
149− match (CppBlock sts) = concat <$> sequence
141+ match (CppBlock sts) = mconcat <$> sequence
150 [ return "{\n"
142 [ return "{\n"
151 , withIndent $ prettyStatements sts
143 , withIndent $ prettyStatements sts
152 , return $ if null sts then "" else "\n"
144 , return $ if null sts then "" else "\n"
153 , currentIndent
145 , currentIndent
154 , return "}"
146 , return "}"
156− match (CppNamespace _ []) = return []
148+ match (CppNamespace _ []) = return ""
157− match (CppNamespace [] sts) = fmap concat $ sequence $
149+ match (CppNamespace name sts) | T.null name = mconcat <$> sequence
158 [ return "\n"
150 [ return "\n"
159 , prettyStatements sts
151 , prettyStatements sts
160 , return "#"
152 , return "#"
162− match (CppNamespace (':':':':name) sts) = fmap concat $ sequence $
154+ match (CppNamespace name sts)
155+ | Just name' <- T.stripPrefix "::" name = mconcat <$> sequence
163 [ return "\n"
156 [ return "\n"
164 , currentIndent
157 , currentIndent
165− , return $ "namespace " ++ (dotsTo '_' name) ++ " {\n"
158+ , return $ "namespace " <> (dotsTo '_' name') <> " {\n"
166 , withIndent $ prettyStatements sts
159 , withIndent $ prettyStatements sts
167 , return "\n"
160 , return "\n"
168 , currentIndent
161 , currentIndent
169 , return "}#"
162 , return "}#"
171− match (CppNamespace name sts) = fmap concat $ sequence $
164+ match (CppNamespace name sts) = mconcat <$> sequence (
172 [ return "\n"
165 [ return "\n"
173 , currentIndent
166 , currentIndent
174− , return $ "namespace " ++ (dotsTo '_' name) ++ " {\n"
167+ , return $ "namespace " <> (dotsTo '_' name) <> " {\n"
175 , withIndent $ prettyStatements sts'
168 , withIndent $ prettyStatements sts'
176 , return "\n"
169 , return "\n"
177 , currentIndent
170 , currentIndent
178 , return "}#"
171 , return "}#"
180 let (cpp', cpps') = fromNested nested'
173 let (cpp', cpps') = fromNested nested'
181 in map match cpp' ++
174 in map match cpp' ++
182 if null cpps'
175 if null cpps'
184− else [match (CppNamespace name (filter isUseNamespace sts ++ cpps'))]
177+ else [match (CppNamespace name (filter isUseNamespace sts <> cpps'))]
186 (sts', nested') = break isNestedNamespace sts
180 (sts', nested') = break isNestedNamespace sts
187 fromNested :: [Cpp] -> ([Cpp], [Cpp])
181 fromNested :: [Cpp] -> ([Cpp], [Cpp])
@@ -201,11 +195,11 @@ literals = mkPattern' match
201 isUseNamespace :: Cpp -> Bool
195 isUseNamespace :: Cpp -> Bool
202 isUseNamespace (CppUseNamespace {}) = True
196 isUseNamespace (CppUseNamespace {}) = True
203 isUseNamespace _ = False
197 isUseNamespace _ = False
204− match (CppStruct (name) []) = return $ "struct " ++ name ++ " {}"
198+ match (CppStruct (name) []) = return $ "struct " <> name <> " {}"
205− match (CppStruct (name) mems) = fmap concat $ sequence $
199+ match (CppStruct (name) mems) = mconcat <$> sequence
206 [ return "\n"
200 [ return "\n"
207 , currentIndent
201 , currentIndent
208− , return $ "struct " ++ name ++ " {\n"
202+ , return $ "struct " <> name <> " {\n"
209 , withIndent $ prettyStatements mems
203 , withIndent $ prettyStatements mems
210 , return "\n"
204 , return "\n"
211 , currentIndent
205 , currentIndent
@@ -213,60 +207,60 @@ literals = mkPattern' match
214 match (CppInclude path name) =
208 match (CppInclude path name) =
215 let fullpath
209 let fullpath
216− | null path = last . words . dotsTo ' ' $ name
210+ | T.null path = last . T.words . dotsTo ' ' $ name
217− | otherwise = path ++ '/' : (last . words . dotsTo ' ' $ name) in
211+ | otherwise = path <> "/" <> (last . T.words . dotsTo ' ' $ name) in
218− fmap concat $ sequence
212+ mconcat <$> sequence
219− [ return $ "#include \"" ++ fullpath ++ ".hh\""
213+ [ return $ "#include \"" <> fullpath <> ".hh\""
221− match (CppUseNamespace name) = fmap concat $ sequence
215+ match (CppUseNamespace name) = mconcat <$> sequence
222− [ return $ "using namespace " ++ (dotsTo '_' name)
216+ [ return $ "using namespace " <> (dotsTo '_' name)
224 match (CppTypeAlias (newName, newTyps) typ spec) =
218 match (CppTypeAlias (newName, newTyps) typ spec) =
225 let typ' = runType typ
219 let typ' = runType typ
226 (tmps, name') = if null newTyps
220 (tmps, name') = if null newTyps
227 then ([], typ')
221 then ([], typ')
228 else ([return (templDecl newTyps), return "\n", currentIndent], typ')
222 else ([return (templDecl newTyps), return "\n", currentIndent], typ')
229− in fmap concat $ sequence $
223+ in mconcat <$> sequence (
231− [ return $ "using "
225+ [ return "using "
232 , return newName
226 , return newName
233 , return " = "
227 , return " = "
234− , return $ if null spec then name' else spec ++ angles name'
228+ , return $ if T.null spec then name' else spec <> angles name'
236 match (CppCast typ val) = return $
230 match (CppCast typ val) = return $
237 case val of
231 case val of
238 CppNumericLiteral {} -> vstr
232 CppNumericLiteral {} -> vstr
239 CppStringLiteral {} -> vstr
233 CppStringLiteral {} -> vstr
240 CppBooleanLiteral {} -> vstr
234 CppBooleanLiteral {} -> vstr
241− _ -> "cast" ++ angles (runType typ) ++ parens val'
235+ _ -> "cast" <> angles (runType typ) <> parensT val'
243 vstr = prettyPrintCpp1 val
237 vstr = prettyPrintCpp1 val
244− val' | '(' `elem` vstr || '[' `elem` vstr = parens vstr
238+ val' | "(" `T.isInfixOf` vstr || "[" `T.isInfixOf` vstr = parensT vstr
245 | otherwise = vstr
239 | otherwise = vstr
246 match (CppGet i@(CppSymbol _) val) =
240 match (CppGet i@(CppSymbol _) val) =
247− return $ printf "get(%s, %s)" (prettyPrintCpp1 i) (prettyPrintCpp1 val)
241+ return . prettyPrintCpp1 $ CppApp (CppVar "get") [i, val]
248 match (CppGet i val) =
242 match (CppGet i val) =
249− return $ printf "get<%s>(%s)" (prettyPrintCpp1 i) (prettyPrintCpp1 val)
243+ return . prettyPrintCpp1 $ CppApp (CppVar $ "get" <> angles (prettyPrintCpp1 i)) [val]
250 match (CppVar ident)
244 match (CppVar ident)
251− | ident == C.__unused = match (CppVar $ '$' : ident)
245+ | ident == C.__unused = match (CppVar $ '$' `T.cons` ident)
252 match (CppVar ident) = return ident
246 match (CppVar ident) = return ident
253− match (CppSymbol ident) = return $ "SYMBOL" ++ parens (symbolname ident)
247+ match (CppSymbol ident) = return $ "SYMBOL" <> parensT (symbolname ident)
254 match (CppApp v [CppNoOp]) = return (prettyPrintCpp1 v)
248 match (CppApp v [CppNoOp]) = return (prettyPrintCpp1 v)
255 match (CppVariableIntroduction (ident, typ) qs value)
249 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)
257 match (CppVariableIntroduction (ident, typ) qs value) =
251 match (CppVariableIntroduction (ident, typ) qs value) =
258− fmap concat $ sequence
252+ mconcat <$> sequence
259− [ return . concatMap (++ " ") . filter (not . null) $ runValueQual <$> qs
253+ [ return . T.concat . fmap (<> " ") . filter (not . T.null) $ runValueQual <$> qs
260− , return $ runType (fromMaybe (Any [Const]) typ) ++ " "
254+ , return $ runType (fromMaybe (Any [Const]) typ) <> " "
261 , return ident
255 , return ident
262− , maybe (return "") (fmap (" = " ++) . prettyPrintCpp') value
256+ , maybe (return "") (fmap (" = " <>) . prettyPrintCpp') value
264− match (CppAssignment target value) = fmap concat $ sequence
258+ match (CppAssignment target value) = mconcat <$> sequence
265 [ prettyPrintCpp' target
259 [ prettyPrintCpp' target
266 , return " = "
260 , return " = "
267 , prettyPrintCpp' value
261 , prettyPrintCpp' value
269− match (CppWhile cond sts) = fmap concat $ sequence
263+ match (CppWhile cond sts) = mconcat <$> sequence
270 [ return "while ("
264 [ return "while ("
271 , prettyPrintCpp' cond
265 , prettyPrintCpp' cond
272 , return ") "
266 , return ") "
@@ -276,24 +270,24 @@ literals = mkPattern' match
276 sts' | CppBlock cpps'@(_:_) <- sts,
270 sts' | CppBlock cpps'@(_:_) <- sts,
277 last cpps' == CppContinue = CppBlock (init cpps')
271 last cpps' == CppContinue = CppBlock (init cpps')
278 | otherwise = sts
272 | otherwise = sts
279− match (CppIfElse cond thens elses) = fmap concat $ sequence
273+ match (CppIfElse cond thens elses) = mconcat <$> sequence
280 [ return "if ("
274 [ return "if ("
281 , prettyPrintCpp' cond
275 , prettyPrintCpp' cond
282 , return ") "
276 , return ") "
283 , prettyPrintCpp' thens
277 , prettyPrintCpp' thens
284− , maybe (return "") (fmap (" else " ++) . prettyPrintCpp') elses
278+ , maybe (return "") (fmap (" else " <>) . prettyPrintCpp') elses
286− match (CppSwitch cond cases@((case1,_):_:_)) = fmap concat $ sequence
280+ match (CppSwitch cond cases@((case1,_):_:_)) = mconcat <$> sequence
287 [ return "switch "
281 [ return "switch "
288− , return . parens $ prettyPrintCpp1 (cast case1 cond)
282+ , return . parensT $ prettyPrintCpp1 (cast case1 cond)
289 , return " {\n"
283 , return " {\n"
290 , withIndent $ do
284 , withIndent $ do
291 cpps <- forM cases $ \(c, s) -> do
285 cpps <- forM cases $ \(c, s) -> do
292 c' <- prettyPrintCpp' c
286 c' <- prettyPrintCpp' c
293 s' <- prettyPrintCpp' s
287 s' <- prettyPrintCpp' s
294− return $ "case " ++ c' ++ ": " ++ s' ++ ";"
288+ return $ "case " <> c' <> ": " <> s' <> ";"
295 indentString <- currentIndent
289 indentString <- currentIndent
296− return $ intercalate "\n" $ map (indentString ++) cpps
290+ return $ T.intercalate "\n" $ map (indentString <>) cpps
297 , return "\n"
291 , return "\n"
298 , currentIndent
292 , currentIndent
299 , return "}"
293 , return "}"
@@ -304,71 +298,63 @@ literals = mkPattern' match
304 cast CppBooleanLiteral {} cpp' = CppCast boolType cpp'
298 cast CppBooleanLiteral {} cpp' = CppCast boolType cpp'
305 cast CppCharLiteral {} cpp' = CppCast charType cpp'
299 cast CppCharLiteral {} cpp' = CppCast charType cpp'
306 cast _ cpp' = cpp'
300 cast _ cpp' = cpp'
307− match (CppReturn (CppBlock (cpp:cpps))) = fmap concat $ sequence
301+ match (CppReturn (CppBlock (cpp:cpps))) = mconcat <$> sequence
308 [ do s <- prettyPrintCpp' cpp
302 [ do s <- prettyPrintCpp' cpp
309− return $ dropWhile isSpace s
303+ return $ T.dropWhile isSpace s
310 , return $ if null cpps then "" else "\n"
304 , return $ if null cpps then "" else "\n"
311 , prettyStatements cpps
305 , prettyStatements cpps
313− match (CppReturn value@(CppStringLiteral _)) = fmap concat $ sequence
307+ match (CppReturn value@(CppStringLiteral _)) = mconcat <$> sequence
314 [ return "return "
308 [ return "return "
315 , return . runType $ Any []
309 , return . runType $ Any []
316 , return "("
310 , return "("
317 , prettyPrintCpp' value
311 , prettyPrintCpp' value
318 , return ")"
312 , return ")"
320− match (CppReturn value) = fmap concat $ sequence
314+ match (CppReturn value) = mconcat <$> sequence
321 [ return "return "
315 [ return "return "
322 , prettyPrintCpp' value
316 , prettyPrintCpp' value
324− match (CppThrow value) = fmap concat $ sequence
318+ match (CppThrow value) = mconcat <$> sequence
325 [ return "throw "
319 [ return "throw "
326 , prettyPrintCpp' value
320 , prettyPrintCpp' value
328 match CppContinue = return "continue"
322 match CppContinue = return "continue"
329 match (CppComment [] cpp) = match cpp
323 match (CppComment [] cpp) = match cpp
330− match (CppComment com cpp) = fmap concat $ sequence $
324+ match (CppComment com cpp) = mconcat <$> sequence
331− [ return "\n"
325+ ([ return "\n"
332 , currentIndent
326 , currentIndent
333 , return "/**\n"
327 , return "/**\n"
335− map asLine (concatMap commentLines com) ++
329+ map asLine (concat $ commentLines <$> com) ++
336 [ currentIndent
330 [ currentIndent
337 , return " */\n"
331 , return " */\n"
338 , currentIndent
332 , currentIndent
339 , prettyPrintCpp' cpp
333 , prettyPrintCpp' cpp
342− commentLines :: Comment -> [String]
336+ commentLines :: Comment -> [Text]
343 commentLines (LineComment s) = [s]
337 commentLines (LineComment s) = [s]
344− commentLines (BlockComment s) = lines s
338+ commentLines (BlockComment s) = T.lines s
345− asLine :: String -> StateT PrinterState Maybe String
339+ asLine :: Text -> StateT PrinterState Maybe Text
346 asLine s = do
340 asLine s = do
347 i <- currentIndent
341 i <- currentIndent
348− return $ i ++ " * " ++ removeComments s ++ "\n"
342+ return $ i <> " * " <> removeComments s <> "\n"
349− removeComments :: String -> String
344+ removeComments :: Text -> Text
350− removeComments ('*':'/':s) = removeComments s
345+ removeComments t =
346+ case T.stripPrefix "*/" t of
351− removeComments (c:s) = c : removeComments s
347+ Just rest -> removeComments rest
352− removeComments [] = []
348+ Nothing -> case T.uncons t of
349+ Just (x, xs) -> x `T.cons` removeComments xs
353 match (CppRaw cpp) = return cpp
351 match (CppRaw cpp) = return cpp
354 match _ = mzero
352 match _ = mzero
356−string :: String -> String
354+string :: Text -> Text
357−string s = '"' : concatMap encodeChar (decodeSurrogates s) ++ "\""
355+string s = "\"" <> T.concatMap encodeChar s <> "\""
359− decodeSurrogates :: String -> String
360− decodeSurrogates [c] = [c]
361− decodeSurrogates s' = catMaybes $ zipWith decodePair s' (tail s' ++ ['\0'])
363− decodePair :: Char -> Char -> Maybe Char
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)
369− | fromEnum a >= 0xD800 && fromEnum a <= 0xDFFF = Nothing
370− decodePair a _ = Just a
371− encodeChar :: Char -> String
357+ encodeChar :: Char -> Text
372 encodeChar '\b' = "\\b"
358 encodeChar '\b' = "\\b"
373 encodeChar '\t' = "\\t"
359 encodeChar '\t' = "\\t"
374 encodeChar '\n' = "\\n"
360 encodeChar '\n' = "\\n"
@@ -377,73 +363,69 @@ string s = '"' : concatMap encodeChar (decodeSurrogates s) ++ "\""
377 encodeChar '\r' = "\\r"
363 encodeChar '\r' = "\\r"
378 encodeChar '"' = "\\\""
364 encodeChar '"' = "\\\""
379 encodeChar '\\' = "\\\\"
365 encodeChar '\\' = "\\\\"
380− encodeChar c
366+ -- PureScript strings are sequences of UTF-16 code units, so this case should never be hit.
381− | fromEnum c > 0xFFFF = "\\U" ++ leading ++ hex
367+ -- If it is somehow hit, though, output the designated Unicode replacement character U+FFFD.
383− hex = showHex (fromEnum c) ""
384− leading = replicate (8 - length hex) '0'
385− encodeChar c
368+ encodeChar c | fromEnum c > 0xFFFF = "\\uFFFD"
386− | fromEnum c > 0xFFF = "\\u" ++ showHex (fromEnum c) ""
369+ encodeChar c | fromEnum c > 0xFFF = "\\u" <> showHex' (fromEnum c) ""
388− | fromEnum c > 0xFF = "\\u0" ++ showHex (fromEnum c) ""
370+ encodeChar c | fromEnum c > 0xFF = "\\u0" <> showHex' (fromEnum c) ""
390− | fromEnum c < 0x10 = "\\x0" ++ showHex (fromEnum c) ""
371+ encodeChar c | fromEnum c < 0x10 = "\\x0" <> showHex' (fromEnum c) ""
392− | fromEnum c > 0x7E || fromEnum c < 0x20 = "\\x" ++ showHex (fromEnum c) ""
372+ encodeChar c | fromEnum c > 0x7E || fromEnum c < 0x20 = "\\x" <> showHex' (fromEnum c) ""
393− encodeChar c = [c]
373+ encodeChar c = T.singleton c
375+ showHex' a b = T.pack (showHex a b)
395−accessor :: Pattern PrinterState Cpp (String, Cpp)
377+accessor :: Pattern PrinterState Cpp (Text, Cpp)
396accessor = mkPattern match
378accessor = mkPattern match
398 match (CppAccessor prop val) = Just (prettyPrintCpp1 prop, val)
380 match (CppAccessor prop val) = Just (prettyPrintCpp1 prop, val)
399 match _ = Nothing
381 match _ = Nothing
401−indexer :: Pattern PrinterState Cpp (String, Cpp)
383+indexer :: Pattern PrinterState Cpp (Text, Cpp)
402indexer = mkPattern' match
384indexer = mkPattern' match
404 match (CppIndexer (CppNumericLiteral (Left 0)) val) = return ("0UL", val)
386 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)
406 match (CppIndexer index val) = do
388 match (CppIndexer index val) = do
407 index' <- prettyPrintCpp' index
389 index' <- prettyPrintCpp' index
408 return (index', val)
390 return (index', val)
409 match _ = mzero
391 match _ = mzero
411−lam :: Pattern PrinterState Cpp ((String, [(String, Maybe CppType)], Maybe CppType), Cpp)
393+lam :: Pattern PrinterState Cpp ((Text, [(Text, Maybe CppType)], Maybe CppType), Cpp)
412lam = mkPattern match
394lam = mkPattern match
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)
415 match _ = Nothing
397 match _ = Nothing
417−app :: Pattern PrinterState Cpp (String, Cpp)
399+app :: Pattern PrinterState Cpp (Text, Cpp)
418app = mkPattern' match
400app = mkPattern' match
420 match (CppApp _ [CppNoOp]) = mzero
402 match (CppApp _ [CppNoOp]) = mzero
421 match (CppApp val args) = do
403 match (CppApp val args) = do
422 cpps <- mapM prettyPrintCpp' args
404 cpps <- mapM prettyPrintCpp' args
423− return (intercalate ", " cpps, val)
405+ return (T.intercalate ", " cpps, val)
424 match _ = mzero
406 match _ = mzero
426−unary' :: UnaryOperator -> (Cpp -> String) -> Operator PrinterState Cpp String
408+unary' :: UnaryOperator -> (Cpp -> Text) -> Operator PrinterState Cpp Text
427−unary' op mkStr = Wrap match (++)
409+unary' op mkStr = Wrap match (<>)
429− match :: Pattern PrinterState Cpp (String, Cpp)
411+ match :: Pattern PrinterState Cpp (Text, Cpp)
430 match = mkPattern match'
412 match = mkPattern match'
432 match' (CppUnary op' val)
414 match' (CppUnary op' val)
433 | op' == op = Just (mkStr val, val)
415 | op' == op = Just (mkStr val, val)
434 match' _ = Nothing
416 match' _ = Nothing
436−unary :: UnaryOperator -> String -> Operator PrinterState Cpp String
418+unary :: UnaryOperator -> Text -> Operator PrinterState Cpp Text
437unary op str = unary' op (const str)
419unary op str = unary' op (const str)
439−negateOperator :: Operator PrinterState Cpp String
421+negateOperator :: Operator PrinterState Cpp Text
440negateOperator = unary' Negate (\v -> if isNegate v then "- " else "-")
422negateOperator = unary' Negate (\v -> if isNegate v then "- " else "-")
442 isNegate (CppUnary Negate _) = True
424 isNegate (CppUnary Negate _) = True
443 isNegate _ = False
425 isNegate _ = False
445−binary :: BinaryOperator -> String -> Operator PrinterState Cpp String
427+binary :: BinaryOperator -> Text -> Operator PrinterState Cpp Text
446−binary op str = AssocL match (\v1 v2 -> v1 ++ str ++ v2)
428+binary op str = AssocL match (\v1 v2 -> v1 <> str <> v2)
448 match :: Pattern PrinterState Cpp (Cpp, Cpp)
430 match :: Pattern PrinterState Cpp (Cpp, Cpp)
449 match = mkPattern match'
431 match = mkPattern match'
@@ -454,53 +436,54 @@ binary op str = AssocL match (\v1 v2 -> v1 ++ str ++ v2)
454 | op' == op = Just (v1, v2)
436 | op' == op = Just (v1, v2)
455 match' _ = Nothing
437 match' _ = Nothing
457−prettyStatements :: [Cpp] -> StateT PrinterState Maybe String
439+prettyStatements :: [Cpp] -> StateT PrinterState Maybe Text
458prettyStatements sts = do
440prettyStatements sts = do
459 cpps <- forM (filter (not . isNoOp) sts) prettyPrintCpp'
441 cpps <- forM (filter (not . isNoOp) sts) prettyPrintCpp'
460 indentString <- currentIndent
442 indentString <- currentIndent
461− return $ intercalate "\n" $ map (addsemi . (indentString ++)) cpps
443+ return $ T.intercalate "\n" $ map (addsemi . (indentString <>)) cpps
463− addsemi :: String -> String
445+ addsemi :: Text -> Text
464− addsemi [] = []
446+ addsemi s | T.null s = s
448+ | T.all isSpace s = ""
465 addsemi s
449 addsemi s
466− | all isSpace s = []
450+ | T.head s == '#' = s
467− addsemi s@('#':_) = s
468 addsemi s
451 addsemi s
469− | last s == '#' = init s
452+ | T.last s == '#' = T.init s
470− addsemi s = s ++ ";"
453+ addsemi s = s <> ";"
473-- Generate a pretty-printed string representing a C++11 expression
456-- Generate a pretty-printed string representing a C++11 expression
475−prettyPrintCpp1 :: Cpp -> String
458+prettyPrintCpp1 :: Cpp -> Text
476prettyPrintCpp1 = fromMaybe (error "Incomplete pattern") . flip evalStateT (PrinterState 0) . prettyPrintCpp'
459prettyPrintCpp1 = fromMaybe (error "Incomplete pattern") . flip evalStateT (PrinterState 0) . prettyPrintCpp'
479-- Generate a pretty-printed string representing a collection of C++11 expressions at the same indentation level
462-- Generate a pretty-printed string representing a collection of C++11 expressions at the same indentation level
481−prettyPrintCpp :: [Cpp] -> String
464+prettyPrintCpp :: [Cpp] -> Text
482prettyPrintCpp = fromMaybe (error "Incomplete pattern") . flip evalStateT (PrinterState 0) . prettyStatements
465prettyPrintCpp = fromMaybe (error "Incomplete pattern") . flip evalStateT (PrinterState 0) . prettyStatements
485-- Generate an indented, pretty-printed string representing a C++11 expression
468-- Generate an indented, pretty-printed string representing a C++11 expression
487−prettyPrintCpp' :: Cpp -> StateT PrinterState Maybe String
470+prettyPrintCpp' :: Cpp -> StateT PrinterState Maybe Text
488prettyPrintCpp' = A.runKleisli $ runPattern matchValue
471prettyPrintCpp' = A.runKleisli $ runPattern matchValue
490− matchValue :: Pattern PrinterState Cpp String
473+ matchValue :: Pattern PrinterState Cpp Text
491− matchValue = buildPrettyPrinter operators (literals <+> fmap parens matchValue)
474+ matchValue = buildPrettyPrinter operators (literals <+> fmap parensT matchValue)
492− operators :: OperatorTable PrinterState Cpp String
475+ operators :: OperatorTable PrinterState Cpp Text
493 operators =
476 operators =
494− OperatorTable [ [ Wrap accessor $ \prop val -> val ++ "::" ++ prop ]
477+ OperatorTable [ [ Wrap accessor $ \prop val -> val <> "::" <> prop ]
495− , [ Wrap indexer $ \index val -> val ++ "[" ++ index ++ "]" ]
478+ , [ Wrap indexer $ \index val -> val <> "[" <> index <> "]" ]
496− , [ Wrap app $ \args val -> val ++ parens args ]
479+ , [ Wrap app $ \args val -> val <> parensT args ]
497 , [ unary New "new " ]
480 , [ unary New "new " ]
498− , [ Wrap lam $ \(caps, args, rty) ret -> '[' : caps ++ "]"
481+ , [ Wrap lam $ \(caps, args, rty) ret -> '[' `T.cons` caps <> "]"
499− ++ let args' = argstr <$> args in
482+ <> let args' = argstr <$> args in
500− parens (intercalate ", " args')
483+ parensT (T.intercalate ", " args')
501− ++ maybe "" ((" -> " ++) . runType) rty
484+ <> maybe "" ((" -> " <>) . runType) rty
503− ++ ret ]
486+ <> ret ]
504 , [ unary Not "!"
487 , [ unary Not "!"
505 , unary BitwiseNot "~"
488 , unary BitwiseNot "~"
506 , unary Positive "+"
489 , unary Positive "+"
@@ -526,35 +509,35 @@ prettyPrintCpp' = A.runKleisli $ runPattern matchValue
526 , [ binary Or " || " ]
509 , [ binary Or " || " ]
529−dotsTo :: Char -> String -> String
512+dotsTo :: Char -> Text -> Text
530−dotsTo chr' = map (\c -> if c == '.' then chr' else c)
513+dotsTo chr' = T.map (\c -> if c == '.' then chr' else c)
532−argstr :: (String, Maybe CppType) -> String
515+argstr :: (Text, Maybe CppType) -> Text
533argstr (name, Nothing) = argStr name (Auto [])
516argstr (name, Nothing) = argStr name (Auto [])
534argstr (name, Just typ)
517argstr (name, Just typ)
535− | name == C.__unused = argStr [] typ
518+ | name == C.__unused = argStr "" typ
536argstr (name, Just typ) = argStr name typ
519argstr (name, Just typ) = argStr name typ
538−argStr :: String -> CppType -> String
521+argStr :: Text -> CppType -> Text
539−argStr name typ =
522+argStr name typ = runType typ <>
541− if null name
523+ if T.null name
543− else " " ++ name
525+ else " " <> name
545−templDecl :: [(String, Int)] -> String
527+templDecl :: [(Text, Int)] -> Text
546−templDecl ps = "template " ++ angles (intercalate ", " (go <$> ps))
528+templDecl ps = "template " <> angles (intercalate ", " (go <$> ps))
548− go :: (String, Int) -> String
530+ go :: (Text, Int) -> Text
549− go (name, 0) = "typename " ++ name
531+ go (name, 0) = "typename " <> name
550− go (name, n) = "typename" ++ parens (intercalate "," $ replicate n "typename") ++ ' ' : name
532+ go (name, n) = "typename" <> parensT (intercalate "," $ replicate n "typename") <> (' ' `T.cons` name)
552isNestedNamespace :: Cpp -> Bool
534isNestedNamespace :: Cpp -> Bool
553−isNestedNamespace (CppNamespace (':':':':_) _) = True
535+isNestedNamespace (CppNamespace name _)
536+ | "::" `T.isPrefixOf` name = True
554isNestedNamespace _ = False
537isNestedNamespace _ = False
556−angles :: String -> String
539+angles :: Text -> Text
557−angles s = '<' : s ++ ">"
540+angles s = "<" <> s <> ">"
559linebreak :: [Cpp]
542linebreak :: [Cpp]
560linebreak = [CppRaw ""]
543linebreak = [CppRaw ""]