@@ -97,13 +97,45 @@ literals = mkPattern' match
9797 return $ ' ' : cpps
9898 else return ""
9999 ]
100− match (CppBlock sts) = fmap concat $ sequence
100+ match (CppBlock sts) = concat <$> sequence
101101 [ return "{\n"
102− , withIndent $ prettyStatements sts
102+ , withIndent $ prettyStatements (compact sts)
103103 , return $ if null sts then "" else "\n"
104104 , currentIndent
105105 , return "}"
106106 ]
107+ where
108+ compact :: [Cpp] -> [Cpp]
109+ compact (st'@(CppIfElse (CppBinary Equal a _) _ Nothing) : sts') =
110+ if length (fst cpps') > 1
111+ then CppSwitch a (mkCases <$> fst cpps') : snd cpps'
112+ else st' : sts'
113+ where
114+ cpps' = span (isIntEq a) (st' : sts')
115+ compact ((CppIfElse cond1 body1 Nothing) : (CppIfElse cond2 body2 Nothing) : _)
116+ | returns body1 && returns body2 &&
117+ (CppUnary CppNot cond1 == cond2 ||
118+ CppUnary CppNot cond2 == cond1) = [CppIfElse cond1 body1 (Just body2)]
119+ where
120+ returns :: Cpp -> Bool
121+ returns (CppBlock rets@(_:_)) | CppReturn{} <- last rets = True
122+ returns CppReturn{} = True
123+ returns _ = False
124+ compact (cpp' : cpps') = cpp' : compact cpps'
125+ compact cpps' = cpps'
126+ isIntEq :: Cpp -> Cpp -> Bool
127+ isIntEq a (CppIfElse (CppBinary Equal a' (CppNumericLiteral (Left _))) (CppBlock [CppReturn _]) Nothing)
128+ | a == a' = True
129+ isIntEq a (CppIfElse (CppBinary Equal a' (CppCharLiteral _)) (CppBlock [CppReturn _]) Nothing)
130+ | a == a' = True
131+ isIntEq a (CppIfElse (CppBinary Equal a' (CppBooleanLiteral _)) (CppBlock [CppReturn _]) Nothing)
132+ | a == a' = True
133+ isIntEq _ _ = False
134+ mkCases :: Cpp -> (Cpp, Cpp)
135+ mkCases (CppIfElse (CppBinary Equal _ b') (CppBlock [body]) Nothing) = (b', body)
136+ mkCases (CppIfElse (CppUnary CppNot _) (CppBlock [body]) Nothing) = (CppBooleanLiteral False, body)
137+ mkCases (CppIfElse _ (CppBlock [body]) Nothing) = (CppBooleanLiteral True, body)
138+ mkCases _ = error ""
107139 match (CppNamespace _ []) = return []
108140 match (CppNamespace (':':':':name) sts) = fmap concat $ sequence $
109141 [ return "\n"
@@ -208,6 +240,27 @@ literals = mkPattern' match
208240 , prettyPrintCpp' thens
209241 , maybe (return "") (fmap (" else " ++) . prettyPrintCpp') elses
210242 ]
243+ match (CppSwitch cond cases@((case1,_):_:_)) = fmap concat $ sequence
244+ [ return "switch "
245+ , return . parens $ prettyPrintCpp1 (cast case1 cond)
246+ , return " {\n"
247+ , withIndent $ do
248+ cpps <- forM cases $ \(c, s) -> do
249+ c' <- prettyPrintCpp' c
250+ s' <- prettyPrintCpp' s
251+ return $ "case " ++ c' ++ ": " ++ s' ++ ";"
252+ indentString <- currentIndent
253+ return $ intercalate "\n" $ map (indentString ++) cpps
254+ , return "\n"
255+ , currentIndent
256+ , return "}"
257+ ]
258+ where
259+ cast :: Cpp -> Cpp -> Cpp
260+ cast CppNumericLiteral{} cpp' = CppCast intType cpp'
261+ cast CppBooleanLiteral{} cpp' = CppCast boolType cpp'
262+ cast CppCharLiteral{} cpp' = CppCast charType cpp'
263+ cast _ cpp' = cpp'
211264 match (CppReturn (CppBlock (cpp:cpps))) = fmap concat $ sequence
212265 [ do s <- prettyPrintCpp' cpp
213266 return $ dropWhile isSpace s