Respect special where ind.; Some layouting fixes

pull/1/head
Lennart Spitzner 2016-08-04 19:53:37 +02:00
parent 9949ed7225
commit 6b748ea3eb
6 changed files with 81 additions and 72 deletions

View File

@ -74,6 +74,7 @@ library {
, strict >=0.3.2 && <0.4 , strict >=0.3.2 && <0.4
, monad-memo >=0.4.1 && <0.5 , monad-memo >=0.4.1 && <0.5
, unsafe >=0.0 && <0.1 , unsafe >=0.0 && <0.1
, safe >=0.3.9 && <0.4
, deepseq >=1.4.2.0 && <1.5 , deepseq >=1.4.2.0 && <1.5
} }
default-extensions: { default-extensions: {
@ -129,6 +130,7 @@ executable brittany
, uniplate , uniplate
, strict , strict
, monad-memo , monad-memo
, safe
} }
hs-source-dirs: src-brittany hs-source-dirs: src-brittany
default-language: Haskell2010 default-language: Haskell2010
@ -193,6 +195,7 @@ test-suite unittests
, uniplate , uniplate
, strict , strict
, monad-memo , monad-memo
, safe
} }
ghc-options: -Wall ghc-options: -Wall
main-is: TestMain.hs main-is: TestMain.hs

View File

@ -768,6 +768,8 @@ transformSimplifyFloating = stepBO .> stepFull
-- note that semantically, stepFull is completely sufficient. -- note that semantically, stepFull is completely sufficient.
-- but the bottom-up switch-to-top-down-on-match transformation has much -- but the bottom-up switch-to-top-down-on-match transformation has much
-- better complexity. -- better complexity.
-- UPDATE: by now, stepBO does more than stepFull; for semantic equivalence
-- the push/pop cases would need to be copied over
where where
descendPost = transformDownMay $ \case descendPost = transformDownMay $ \case
-- post floating in -- post floating in
@ -796,19 +798,19 @@ transformSimplifyFloating = stepBO .> stepFull
Just $ BDAddBaseY indent $ BDAnnotationPrior annKey1 x Just $ BDAddBaseY indent $ BDAnnotationPrior annKey1 x
_ -> Nothing _ -> Nothing
descendBYPush = transformDownMay $ \case descendBYPush = transformDownMay $ \case
BDBaseYPushCur (BDCols sig cols) -> BDBaseYPushCur (BDCols sig cols@(_:_)) ->
Just $ BDCols sig (BDBaseYPushCur (List.head cols) : List.tail cols) Just $ BDCols sig (BDBaseYPushCur (List.head cols) : List.tail cols)
_ -> Nothing _ -> Nothing
descendBYPop = transformDownMay $ \case descendBYPop = transformDownMay $ \case
BDBaseYPop (BDCols sig cols) -> BDBaseYPop (BDCols sig cols@(_:_)) ->
Just $ BDCols sig (List.init cols ++ [BDBaseYPop (List.last cols)]) Just $ BDCols sig (List.init cols ++ [BDBaseYPop (List.last cols)])
_ -> Nothing _ -> Nothing
descendILPush = transformDownMay $ \case descendILPush = transformDownMay $ \case
BDIndentLevelPushCur (BDCols sig cols) -> BDIndentLevelPushCur (BDCols sig cols@(_:_)) ->
Just $ BDCols sig (BDIndentLevelPushCur (List.head cols) : List.tail cols) Just $ BDCols sig (BDIndentLevelPushCur (List.head cols) : List.tail cols)
_ -> Nothing _ -> Nothing
descendILPop = transformDownMay $ \case descendILPop = transformDownMay $ \case
BDIndentLevelPop (BDCols sig cols) -> BDIndentLevelPop (BDCols sig cols@(_:_)) ->
Just $ BDCols sig (List.init cols ++ [BDIndentLevelPop (List.last cols)]) Just $ BDCols sig (List.init cols ++ [BDIndentLevelPop (List.last cols)])
_ -> Nothing _ -> Nothing
descendAddB = transformDownMay $ \case descendAddB = transformDownMay $ \case

View File

@ -149,11 +149,25 @@ layoutPatternBindFinal binderDoc mPatDoc clauseDocs mWhereDocs = do
patPartParWrap = case mPatDoc of patPartParWrap = case mPatDoc of
Nothing -> id Nothing -> id
Just patDoc -> docPar (return patDoc) Just patDoc -> docPar (return patDoc)
_whereIndent <- mAsk whereIndent <- mAsk
<&> _conf_layout <&> _conf_layout
.> _lconfig_indentWhereSpecial .> _lconfig_indentWhereSpecial
.> runIdentity .> runIdentity
.> Bool.bool BrIndentRegular (BrIndentSpecial 1) .> Bool.bool BrIndentRegular (BrIndentSpecial 1)
-- TODO: apart from this, there probably are more nodes below which could
-- be shared between alternatives.
wherePartMultiLine :: [ToBriDocM BriDocNumbered] <- case mWhereDocs of
Nothing -> return $ []
Just ws -> fmap (fmap return) $ sequence $ return @[]
$ docEnsureIndent whereIndent
$ docLines
[ docLit $ Text.pack "where"
, docEnsureIndent whereIndent
$ docSetIndentLevel
$ docNonBottomSpacing
$ docLines
$ return <$> ws
]
docAlt $ docAlt $
-- one-line solution -- one-line solution
[ docCols ColBindingLine [ docCols ColBindingLine
@ -177,38 +191,48 @@ layoutPatternBindFinal binderDoc mPatDoc clauseDocs mWhereDocs = do
$ [appSep $ docLit $ Text.pack "|"] $ [appSep $ docLit $ Text.pack "|"]
++ List.intersperse docCommaSep (return <$> gs) ++ List.intersperse docCommaSep (return <$> gs)
++ [docSeparator] ++ [docSeparator]
, let , wherePart <- case mWhereDocs of
wherePart = case mWhereDocs of Nothing -> return @[] $ docEmpty
Nothing -> docEmpty Just [w] -> return @[] $ docSeq
Just [w] -> docAlt
[ docSeq
[ docSeparator [ docSeparator
, appSep $ docLit $ Text.pack "where" , appSep $ docLit $ Text.pack "where"
, docSetIndentLevel $ docForceSingleline $ return w , docSetIndentLevel $ docForceSingleline $ return w
] ]
, docAddBaseY BrIndentRegular _ -> []
$ docPar docEmpty
$ docAddBaseY BrIndentRegular
$ docPar
(docLit $ Text.pack "where")
(docSetIndentLevel $ return w)
]
Just ws ->
docAddBaseY BrIndentRegular
$ docPar docEmpty
$ docAddBaseY BrIndentRegular
$ docPar
(docLit $ Text.pack "where")
(docSetIndentLevel $ docLines $ return <$> ws)
] ++ ] ++
-- two-line solution -- one-line solution + where in next line(s)
[ docLines
$ [ docCols ColBindingLine
[ docSeq
(patPartInline ++ [guardPart])
, docSeq
[ appSep $ return binderDoc
, lineMod $ return body
]
]
] ++ wherePartMultiLine
| [(guards, body, bodyRaw)] <- [clauseDocs]
, let lineMod = case mWhereDocs of
Nothing | isExpressionTypeHeadPar bodyRaw ->
docAddBaseY BrIndentRegular
_ -> docForceSingleline
, let guardPart = case guards of
[] -> docEmpty
[g] -> docSeq [appSep $ docLit $ Text.pack "|", return g, docSeparator]
gs -> docSeq
$ [appSep $ docLit $ Text.pack "|"]
++ List.intersperse docCommaSep (return <$> gs)
++ [docSeparator]
, Data.Maybe.isJust mWhereDocs
] ++
-- two-line solution + where in next line(s)
[ docLines [ docLines
$ [ docForceSingleline $ [ docForceSingleline
$ docSeq (patPartInline ++ [guardPart, return binderDoc]) $ docSeq (patPartInline ++ [guardPart, return binderDoc])
, docEnsureIndent BrIndentRegular , docEnsureIndent BrIndentRegular
$ docForceSingleline $ docForceSingleline
$ return body $ return body
] ++ wherePart ] ++ wherePartMultiLine
| [(guards, body, _bodyRaw)] <- [clauseDocs] | [(guards, body, _bodyRaw)] <- [clauseDocs]
, let guardPart = case guards of , let guardPart = case guards of
[] -> docEmpty [] -> docEmpty
@ -217,14 +241,9 @@ layoutPatternBindFinal binderDoc mPatDoc clauseDocs mWhereDocs = do
$ [appSep $ docLit $ Text.pack "|"] $ [appSep $ docLit $ Text.pack "|"]
++ List.intersperse docCommaSep (return <$> gs) ++ List.intersperse docCommaSep (return <$> gs)
++ [docSeparator] ++ [docSeparator]
, let wherePart = case mWhereDocs of
Nothing -> []
Just ws -> pure $ docEnsureIndent BrIndentRegular $ docPar
(docLit $ Text.pack "where")
(docSetIndentLevel $ docLines $ return <$> ws)
] ++ ] ++
-- pattern and exactly one clause in single line, body and where -- pattern and exactly one clause in single line, body as par;
-- indented if necessary. -- where in following lines
[ docLines [ docLines
$ [ docCols ColBindingLine $ [ docCols ColBindingLine
[ docSeq [ docSeq
@ -238,7 +257,7 @@ layoutPatternBindFinal binderDoc mPatDoc clauseDocs mWhereDocs = do
-- ] -- ]
] ]
] ]
] ++ wherePart ] ++ wherePartMultiLine
| [(guards, body, bodyRaw)] <- [clauseDocs] | [(guards, body, bodyRaw)] <- [clauseDocs]
, let lineMod = case () of , let lineMod = case () of
_ | isExpressionTypeHeadPar bodyRaw -> id _ | isExpressionTypeHeadPar bodyRaw -> id
@ -249,20 +268,15 @@ layoutPatternBindFinal binderDoc mPatDoc clauseDocs mWhereDocs = do
gs -> docSeq gs -> docSeq
$ [appSep $ docLit $ Text.pack "|"] $ [appSep $ docLit $ Text.pack "|"]
++ List.intersperse docCommaSep (return <$> gs) ++ List.intersperse docCommaSep (return <$> gs)
, let wherePart = case mWhereDocs of
Nothing -> []
Just ws -> pure $ docEnsureIndent BrIndentRegular $ docPar
(docLit $ Text.pack "where")
(docSetIndentLevel $ docLines $ return <$> ws)
] ++ ] ++
-- pattern and exactly one clause in single line, body in new line. -- pattern and exactly one clause in single line, body in new line.
[ docAddBaseY BrIndentRegular [ docLines
$ docPar $ [ docSeq (patPartInline ++ [appSep $ guardPart, return binderDoc])
(docSeq (patPartInline ++ [appSep $ guardPart, return binderDoc])) , docEnsureIndent BrIndentRegular
( docNonBottomSpacing $ docNonBottomSpacing
$ docLines $ docLines
$ [ docAddBaseY BrIndentRegular $ return body ] ++ wherePart $ [ docAddBaseY BrIndentRegular $ return body ]
) ] ++ wherePartMultiLine
| [(guards, body, _)] <- [clauseDocs] | [(guards, body, _)] <- [clauseDocs]
, let guardPart = case guards of , let guardPart = case guards of
[] -> docEmpty [] -> docEmpty
@ -270,17 +284,13 @@ layoutPatternBindFinal binderDoc mPatDoc clauseDocs mWhereDocs = do
gs -> docSeq gs -> docSeq
$ [appSep $ docLit $ Text.pack "|"] $ [appSep $ docLit $ Text.pack "|"]
++ List.intersperse docCommaSep (return <$> gs) ++ List.intersperse docCommaSep (return <$> gs)
, let wherePart = case mWhereDocs of
Nothing -> []
Just ws -> pure $ docAddBaseY BrIndentRegular $ docPar
(docLit $ Text.pack "where")
(docSetIndentLevel $ docLines $ return <$> ws)
] ++ ] ++
-- conservative approach: everything starts on the left. -- conservative approach: everything starts on the left.
[ docAddBaseY BrIndentRegular [ docLines $
$ patPartParWrap [ patPartParWrap
$ docLines $ $ docLines
(clauseDocs >>= \(guardDocs, bodyDoc, _) -> $ fmap (docEnsureIndent BrIndentRegular)
$ clauseDocs >>= \(guardDocs, bodyDoc, _) ->
(case guardDocs of (case guardDocs of
[] -> [] [] -> []
[g] -> [docSeq [appSep $ docLit $ Text.pack "|", return g]] [g] -> [docSeq [appSep $ docLit $ Text.pack "|", return g]]
@ -295,13 +305,5 @@ layoutPatternBindFinal binderDoc mPatDoc clauseDocs mWhereDocs = do
[ appSep $ return binderDoc [ appSep $ return binderDoc
, docAddBaseY BrIndentRegular $ return bodyDoc] , docAddBaseY BrIndentRegular $ return bodyDoc]
] ]
) ++ ] ++ wherePartMultiLine
(case mWhereDocs of
Nothing -> []
Just whereDocs ->
[ docAddBaseY BrIndentRegular
$ docPar (docLit $ Text.pack "where")
$ docSetIndentLevel $ docLines (return <$> whereDocs)
]
)
] ]

View File

@ -46,7 +46,7 @@ layoutStmt lstmt@(L _ stmt) = docWrapNode lstmt $ case stmt of
Just [bindDoc] -> docAlt Just [bindDoc] -> docAlt
[ docCols ColDoLet [ docCols ColDoLet
[ appSep $ docLit $ Text.pack "let" [ appSep $ docLit $ Text.pack "let"
, docSetIndentLevel $ docAddBaseY BrIndentRegular (return bindDoc) , docSetIndentLevel $ return bindDoc
] ]
, docAddBaseY BrIndentRegular $ docPar , docAddBaseY BrIndentRegular $ docPar
(docLit $ Text.pack "let") (docLit $ Text.pack "let")
@ -59,17 +59,17 @@ layoutStmt lstmt@(L _ stmt) = docWrapNode lstmt $ case stmt of
[ docLines [ docLines
$ (docCols ColDoLet $ (docCols ColDoLet
[ appSep $ docLit $ Text.pack "let" [ appSep $ docLit $ Text.pack "let"
, docSetIndentLevel $ docAddBaseY BrIndentRegular (return bindDoc1) , docSetIndentLevel $ return bindDoc1
]) ])
: (bindDocr <&> \bindDoc -> : (bindDocr <&> \bindDoc ->
docCols ColDoLet docCols ColDoLet
[ docEnsureIndent (BrIndentSpecial 4) docEmpty [ docEnsureIndent (BrIndentSpecial 4) docEmpty
, docSetIndentLevel $ docAddBaseY BrIndentRegular (return bindDoc) , docSetIndentLevel $ return bindDoc
]) ])
, docAddBaseY BrIndentRegular , docAddBaseY BrIndentRegular
$ docPar $ docPar
(docLit $ Text.pack "let") (docLit $ Text.pack "let")
(docSetIndentLevel $ docAddBaseY BrIndentRegular $ docLines $ return <$> bindDocs) (docSetIndentLevel $ docLines $ return <$> bindDocs)
] ]
BodyStmt expr _ _ _ -> do BodyStmt expr _ _ _ -> do
expDoc <- docSharedWrapper layoutExpr expr expDoc <- docSharedWrapper layoutExpr expr

View File

@ -83,10 +83,10 @@ data LayoutState = LayoutState
} }
lstate_baseY :: LayoutState -> Int lstate_baseY :: LayoutState -> Int
lstate_baseY = head . _lstate_baseYs lstate_baseY = Safe.headNote "lstate_baseY" . _lstate_baseYs
lstate_indLevel :: LayoutState -> Int lstate_indLevel :: LayoutState -> Int
lstate_indLevel = head . _lstate_indLevels lstate_indLevel = Safe.headNote "lstate_baseY" . _lstate_indLevels
-- evil, incomplete Show instance; only for debugging. -- evil, incomplete Show instance; only for debugging.
instance Show LayoutState where instance Show LayoutState where

View File

@ -428,6 +428,8 @@ import qualified Control.Monad.Trans.State.Strict as StateS
import qualified Data.Strict.Maybe as Strict import qualified Data.Strict.Maybe as Strict
import qualified Safe as Safe
import Data.Functor.Identity ( Identity(..) ) import Data.Functor.Identity ( Identity(..) )
import Control.Concurrent.Chan ( Chan ) import Control.Concurrent.Chan ( Chan )
import Control.Concurrent.MVar ( MVar ) import Control.Concurrent.MVar ( MVar )