1156 lines
41 KiB
Haskell
1156 lines
41 KiB
Haskell
#define INSERTTRACES 0
|
|
|
|
{-# LANGUAGE DataKinds #-}
|
|
{-# LANGUAGE DeriveDataTypeable #-}
|
|
{-# LANGUAGE TypeApplications #-}
|
|
#if !INSERTTRACES
|
|
{-# OPTIONS_GHC -Wno-redundant-constraints #-}
|
|
#endif
|
|
|
|
module Language.Haskell.Brittany.LayoutBasics
|
|
( processDefault
|
|
, rdrNameToText
|
|
, lrdrNameToText
|
|
, lrdrNameToTextAnn
|
|
, lrdrNameToTextAnnTypeEqualityIsSpecial
|
|
, askIndent
|
|
, layoutWriteAppend
|
|
, layoutWriteAppendMultiline
|
|
, layoutWriteNewlineBlock
|
|
, layoutWriteNewline
|
|
, layoutWriteEnsureNewlineBlock
|
|
, layoutWriteEnsureBlock
|
|
, layoutWithAddBaseCol
|
|
, layoutWithAddBaseColBlock
|
|
, layoutWithAddBaseColN
|
|
, layoutWithAddBaseColNBlock
|
|
, layoutBaseYPushCur
|
|
, layoutBaseYPop
|
|
, layoutIndentLevelPushCur
|
|
, layoutIndentLevelPop
|
|
, layoutWriteEnsureAbsoluteN
|
|
, layoutAddSepSpace
|
|
, layoutSetCommentCol
|
|
, layoutMoveToCommentPos
|
|
, layoutIndentRestorePostComment
|
|
, moveToExactAnn
|
|
, layoutWritePriorComments
|
|
, layoutWritePostComments
|
|
, layoutRemoveIndentLevelLinger
|
|
, extractAllComments
|
|
, filterAnns
|
|
, ppmMoveToExactLoc
|
|
, docEmpty
|
|
, docLit
|
|
, docAlt
|
|
, docAltFilter
|
|
, docLines
|
|
, docCols
|
|
, docSeq
|
|
, docPar
|
|
, docNodeAnnKW
|
|
, docWrapNode
|
|
, docWrapNodePrior
|
|
, docWrapNodeRest
|
|
, docForceSingleline
|
|
, docForceMultiline
|
|
, docEnsureIndent
|
|
, docAddBaseY
|
|
, docSetBaseY
|
|
, docSetIndentLevel
|
|
, docSeparator
|
|
, docAnnotationPrior
|
|
, docAnnotationKW
|
|
, docAnnotationRest
|
|
, docNonBottomSpacing
|
|
, docSetParSpacing
|
|
, docForceParSpacing
|
|
, docDebug
|
|
, docSetBaseAndIndent
|
|
, briDocByExact
|
|
, briDocByExactNoComment
|
|
, foldedAnnKeys
|
|
, unknownNodeError
|
|
, appSep
|
|
, docCommaSep
|
|
, docParenLSep
|
|
, spacifyDocs
|
|
, briDocMToPPM
|
|
, allocateNode
|
|
, docSharedWrapper
|
|
, hasAnyCommentsBelow
|
|
)
|
|
where
|
|
|
|
|
|
|
|
#include "prelude.inc"
|
|
|
|
import qualified Language.Haskell.GHC.ExactPrint as ExactPrint
|
|
import qualified Language.Haskell.GHC.ExactPrint.Annotate as ExactPrint.Annotate
|
|
import qualified Language.Haskell.GHC.ExactPrint.Types as ExactPrint.Types
|
|
import qualified Language.Haskell.GHC.ExactPrint.Types as ExactPrint
|
|
import qualified Language.Haskell.GHC.ExactPrint.Utils as ExactPrint.Utils
|
|
|
|
import Language.Haskell.GHC.ExactPrint.Types ( AnnKey, Annotation, KeywordId )
|
|
|
|
import qualified Data.Text.Lazy.Builder as Text.Builder
|
|
|
|
import Language.Haskell.Brittany.Config.Types
|
|
import Language.Haskell.Brittany.Types
|
|
import Language.Haskell.Brittany.Utils
|
|
|
|
import RdrName ( RdrName(..) )
|
|
import GHC ( runGhc, GenLocated(L), moduleNameString )
|
|
import qualified Outputable as GHC
|
|
import qualified DynFlags as GHC
|
|
import qualified FastString as GHC
|
|
import qualified SrcLoc as GHC
|
|
import SrcLoc ( SrcSpan )
|
|
import OccName ( occNameString )
|
|
import Name ( getOccString )
|
|
import Module ( moduleName )
|
|
import ApiAnnotation ( AnnKeywordId(..) )
|
|
|
|
import Data.Data
|
|
import Data.Generics.Schemes
|
|
import Data.Generics.Aliases
|
|
|
|
import DataTreePrint
|
|
|
|
import qualified Text.PrettyPrint as PP
|
|
|
|
import Data.Function ( fix )
|
|
|
|
|
|
traceLocal
|
|
:: (MonadMultiState LayoutState m, MonadMultiWriter (Seq String) m, Show a)
|
|
=> a
|
|
-> m ()
|
|
#if INSERTTRACES
|
|
traceLocal x = do
|
|
mGet >>= tellDebugMessShow @LayoutState
|
|
tellDebugMessShow x
|
|
#else
|
|
traceLocal _ = return ()
|
|
#endif
|
|
|
|
processDefault :: (ExactPrint.Annotate.Annotate ast, MonadMultiWriter
|
|
Text.Builder.Builder m,
|
|
MonadMultiReader ExactPrint.Types.Anns m)
|
|
=> GenLocated SrcSpan ast
|
|
-> m ()
|
|
processDefault x = do
|
|
anns <- mAsk
|
|
let str = ExactPrint.exactPrint x anns
|
|
-- this hack is here so our print-empty-module trick does not add
|
|
-- a newline at the start if there actually is no module header / imports
|
|
-- / anything.
|
|
-- TODO: instead the appropriate annotation could be removed when "cleaning"
|
|
-- the module (header). This would remove the need for this hack!
|
|
case str of
|
|
"\n" -> return ()
|
|
_ -> mTell $ Text.Builder.fromString $ str
|
|
|
|
briDocByExact :: (ExactPrint.Annotate.Annotate ast) => GenLocated SrcSpan ast -> ToBriDocM BriDocNumbered
|
|
briDocByExact ast = do
|
|
anns <- mAsk
|
|
traceIfDumpConf "ast" _dconf_dump_ast_unknown
|
|
(printTreeWithCustom 100 (customLayouterF anns) ast)
|
|
docExt ast anns True
|
|
|
|
briDocByExactNoComment :: (ExactPrint.Annotate.Annotate ast) => GenLocated SrcSpan ast -> ToBriDocM BriDocNumbered
|
|
briDocByExactNoComment ast = do
|
|
anns <- mAsk
|
|
traceIfDumpConf "ast" _dconf_dump_ast_unknown
|
|
(printTreeWithCustom 100 (customLayouterF anns) ast)
|
|
docExt ast anns False
|
|
|
|
rdrNameToText :: RdrName -> Text
|
|
-- rdrNameToText = Text.pack . show . flip runSDoc unsafeGlobalDynFlags . ppr
|
|
rdrNameToText ( Unqual occname ) = Text.pack $ occNameString occname
|
|
rdrNameToText ( Qual mname occname ) = Text.pack $ moduleNameString mname
|
|
++ "."
|
|
++ occNameString occname
|
|
rdrNameToText ( Orig modul occname ) = Text.pack $ moduleNameString (moduleName modul)
|
|
++ occNameString occname
|
|
rdrNameToText ( Exact name ) = Text.pack $ getOccString name
|
|
|
|
lrdrNameToText :: GenLocated l RdrName -> Text
|
|
lrdrNameToText (L _ n) = rdrNameToText n
|
|
|
|
lrdrNameToTextAnn :: ( MonadMultiReader Config m
|
|
, MonadMultiReader (Map AnnKey Annotation) m
|
|
)
|
|
=> GenLocated SrcSpan RdrName
|
|
-> m Text
|
|
lrdrNameToTextAnn ast@(L _ n) = do
|
|
anns <- mAsk
|
|
let t = rdrNameToText n
|
|
let hasUni x (ExactPrint.Types.G y, _) = x==y
|
|
hasUni _ _ = False
|
|
-- TODO: in general: we should _always_ process all annotaiton stuff here.
|
|
-- whatever we don't probably should have had some effect on the
|
|
-- output. in such cases, resorting to byExact is probably the safe
|
|
-- choice.
|
|
return $ case Map.lookup (ExactPrint.Types.mkAnnKey ast) anns of
|
|
Nothing -> t
|
|
Just (ExactPrint.Types.Ann _ _ _ aks _ _) -> case n of
|
|
Exact{} | t == Text.pack "()" -> t
|
|
_ | any (hasUni AnnBackquote) aks -> Text.pack "`" <> t <> Text.pack "`"
|
|
_ | any (hasUni AnnCommaTuple) aks -> t
|
|
_ | any (hasUni AnnOpenP) aks -> Text.pack "(" <> t <> Text.pack ")"
|
|
_ | otherwise -> t
|
|
|
|
lrdrNameToTextAnnTypeEqualityIsSpecial
|
|
:: (MonadMultiReader Config m, MonadMultiReader (Map AnnKey Annotation) m)
|
|
=> GenLocated SrcSpan RdrName
|
|
-> m Text
|
|
lrdrNameToTextAnnTypeEqualityIsSpecial ast = do
|
|
x <- lrdrNameToTextAnn ast
|
|
return $ if x == Text.pack "Data.Type.Equality~"
|
|
then Text.pack "~" -- rraaaahhh special casing rraaahhhhhh
|
|
else x
|
|
|
|
askIndent :: (MonadMultiReader Config m) => m Int
|
|
askIndent = confUnpack . _lconfig_indentAmount . _conf_layout <$> mAsk
|
|
|
|
layoutWriteAppend :: (MonadMultiWriter
|
|
Text.Builder.Builder m,
|
|
MonadMultiState LayoutState m
|
|
, MonadMultiWriter (Seq String) m)
|
|
=> Text
|
|
-> m ()
|
|
layoutWriteAppend t = do
|
|
traceLocal ("layoutWriteAppend", t)
|
|
state <- mGet
|
|
case _lstate_curYOrAddNewline state of
|
|
Right i -> do
|
|
#if INSERTTRACES
|
|
tellDebugMessShow (" inserted newlines: ", i)
|
|
#endif
|
|
replicateM_ i $ mTell $ Text.Builder.fromString $ "\n"
|
|
Left{} -> do
|
|
#if INSERTTRACES
|
|
tellDebugMessShow (" inserted no newlines")
|
|
#endif
|
|
return ()
|
|
let spaces = case _lstate_addSepSpace state of
|
|
Just i -> i
|
|
Nothing -> 0
|
|
#if INSERTTRACES
|
|
tellDebugMessShow (" inserted spaces: ", spaces)
|
|
#endif
|
|
mTell $ Text.Builder.fromText $ Text.pack (replicate spaces ' ')
|
|
mTell $ Text.Builder.fromText $ t
|
|
mModify $ \s -> s
|
|
{ _lstate_curYOrAddNewline = Left $ case _lstate_curYOrAddNewline s of
|
|
Left c -> c + Text.length t + spaces
|
|
Right{} -> Text.length t + spaces
|
|
, _lstate_addSepSpace = Nothing
|
|
}
|
|
|
|
layoutWriteAppendSpaces :: (MonadMultiWriter
|
|
Text.Builder.Builder m,
|
|
MonadMultiState LayoutState m
|
|
, MonadMultiWriter (Seq String) m)
|
|
=> Int
|
|
-> m ()
|
|
layoutWriteAppendSpaces i = do
|
|
traceLocal ("layoutWriteAppendSpaces", i)
|
|
unless (i==0) $ do
|
|
state <- mGet
|
|
mSet $ state { _lstate_addSepSpace = Just
|
|
$ maybe i (+i)
|
|
$ _lstate_addSepSpace state
|
|
}
|
|
|
|
layoutWriteAppendMultiline :: (MonadMultiWriter
|
|
Text.Builder.Builder m,
|
|
MonadMultiState LayoutState m
|
|
, MonadMultiWriter (Seq String) m)
|
|
=> Text
|
|
-> m ()
|
|
layoutWriteAppendMultiline t = do
|
|
traceLocal ("layoutWriteAppendMultiline", t)
|
|
case Text.lines t of
|
|
[] ->
|
|
layoutWriteAppend t -- need to write empty, too.
|
|
(l:lr) -> do
|
|
layoutWriteAppend l
|
|
lr `forM_` \x -> do
|
|
layoutWriteNewline
|
|
layoutWriteAppend x
|
|
|
|
-- adds a newline and adds spaces to reach the base column.
|
|
layoutWriteNewlineBlock :: (MonadMultiWriter
|
|
Text.Builder.Builder m,
|
|
MonadMultiState LayoutState m
|
|
, MonadMultiWriter (Seq String) m)
|
|
=> m ()
|
|
layoutWriteNewlineBlock = do
|
|
traceLocal ("layoutWriteNewlineBlock")
|
|
state <- mGet
|
|
mSet $ state { _lstate_curYOrAddNewline = Right 1
|
|
, _lstate_addSepSpace = Just $ lstate_baseY state
|
|
, _lstate_inhibitMTEL = False
|
|
}
|
|
|
|
-- layoutMoveToIndentCol :: ( MonadMultiState LayoutState m
|
|
-- , MonadMultiWriter (Seq String) m) => Int -> m ()
|
|
-- layoutMoveToIndentCol i = do
|
|
-- #if INSERTTRACES
|
|
-- tellDebugMessShow ("layoutMoveToIndentCol", i)
|
|
-- #endif
|
|
-- state <- mGet
|
|
-- mSet $ state
|
|
-- { _lstate_addSepSpace = Just
|
|
-- $ if isJust $ _lstate_addNewline state
|
|
-- then i
|
|
-- else _lstate_indLevelLinger state + i - _lstate_curY state
|
|
-- }
|
|
|
|
layoutSetCommentCol :: ( MonadMultiState LayoutState m
|
|
, MonadMultiWriter (Seq String) m )
|
|
=> m ()
|
|
layoutSetCommentCol = do
|
|
state <- mGet
|
|
let col = case _lstate_curYOrAddNewline state of
|
|
Left i -> i + fromMaybe 0 (_lstate_addSepSpace state)
|
|
Right{} -> lstate_baseY state
|
|
traceLocal ("layoutSetCommentCol", col)
|
|
unless (Data.Maybe.isJust $ _lstate_commentCol state)
|
|
$ mSet state { _lstate_commentCol = Just col }
|
|
|
|
layoutMoveToCommentPos
|
|
:: ( MonadMultiWriter Text.Builder.Builder m
|
|
, MonadMultiState LayoutState m
|
|
, MonadMultiWriter (Seq String) m
|
|
)
|
|
=> Int
|
|
-> Int
|
|
-> m ()
|
|
layoutMoveToCommentPos y x = do
|
|
traceLocal ("layoutMoveToCommentPos", y, x)
|
|
state <- mGet
|
|
if Data.Maybe.isJust (_lstate_commentCol state)
|
|
then do
|
|
mSet state
|
|
{ _lstate_curYOrAddNewline = case _lstate_curYOrAddNewline state of
|
|
Left i -> if y==0 then Left i else Right y
|
|
Right{} -> Right y
|
|
, _lstate_addSepSpace = Just $ case _lstate_curYOrAddNewline state of
|
|
Left{} -> if y==0
|
|
then x
|
|
else _lstate_indLevelLinger state + x
|
|
Right{} -> _lstate_indLevelLinger state + x
|
|
}
|
|
else do
|
|
mSet state
|
|
{ _lstate_curYOrAddNewline = case _lstate_curYOrAddNewline state of
|
|
Left i -> if y==0 then Left i else Right y
|
|
Right{} -> Right y
|
|
, _lstate_addSepSpace = Just $ if y==0
|
|
then x
|
|
else _lstate_indLevelLinger state + x
|
|
, _lstate_commentCol = Just $ case _lstate_curYOrAddNewline state of
|
|
Left i -> i + fromMaybe 0 (_lstate_addSepSpace state)
|
|
Right{} -> lstate_baseY state
|
|
}
|
|
|
|
-- | does _not_ add spaces to again reach the current base column.
|
|
layoutWriteNewline :: (MonadMultiWriter
|
|
Text.Builder.Builder m,
|
|
MonadMultiState LayoutState m
|
|
, MonadMultiWriter (Seq String) m)
|
|
=> m ()
|
|
layoutWriteNewline = do
|
|
traceLocal ("layoutWriteNewline")
|
|
state <- mGet
|
|
mSet $ state { _lstate_curYOrAddNewline = case _lstate_curYOrAddNewline state of
|
|
Left{} -> Right 1
|
|
Right i -> Right (i+1)
|
|
, _lstate_addSepSpace = Nothing
|
|
, _lstate_inhibitMTEL = False
|
|
}
|
|
|
|
layoutWriteEnsureNewlineBlock :: (MonadMultiWriter
|
|
Text.Builder.Builder m,
|
|
MonadMultiState LayoutState m
|
|
, MonadMultiWriter (Seq String) m)
|
|
=> m ()
|
|
layoutWriteEnsureNewlineBlock = do
|
|
traceLocal ("layoutWriteEnsureNewlineBlock")
|
|
state <- mGet
|
|
mSet $ state
|
|
{ _lstate_curYOrAddNewline = case _lstate_curYOrAddNewline state of
|
|
Left{} -> Right 1
|
|
Right i -> Right $ max 1 i
|
|
, _lstate_addSepSpace = Just $ lstate_baseY state
|
|
, _lstate_inhibitMTEL = False
|
|
, _lstate_commentCol = Nothing
|
|
}
|
|
|
|
layoutWriteEnsureBlock :: (MonadMultiWriter
|
|
Text.Builder.Builder m,
|
|
MonadMultiState LayoutState m
|
|
, MonadMultiWriter (Seq String) m)
|
|
=> m ()
|
|
layoutWriteEnsureBlock = do
|
|
traceLocal ("layoutWriteEnsureBlock")
|
|
state <- mGet
|
|
let
|
|
diff = case (_lstate_addSepSpace state, _lstate_curYOrAddNewline state) of
|
|
(Nothing, Left i) -> lstate_baseY state - i
|
|
(Nothing, Right{}) -> lstate_baseY state
|
|
(Just sp, Left i) -> max sp (lstate_baseY state - i)
|
|
(Just sp, Right{}) -> max sp (lstate_baseY state)
|
|
-- when (diff>0) $ layoutWriteNewlineBlock
|
|
when (diff > 0) $ do
|
|
mSet $ state { _lstate_addSepSpace = Just $ diff }
|
|
|
|
layoutWriteEnsureAbsoluteN :: (MonadMultiWriter
|
|
Text.Builder.Builder m,
|
|
MonadMultiState LayoutState m
|
|
, MonadMultiWriter (Seq String) m)
|
|
=> Int -> m ()
|
|
layoutWriteEnsureAbsoluteN n = do
|
|
state <- mGet
|
|
let diff = case _lstate_curYOrAddNewline state of
|
|
Left i -> n-i
|
|
Right{} -> n
|
|
traceLocal ("layoutWriteEnsureAbsoluteN", n, diff)
|
|
when (diff>0) $ do
|
|
mSet $ state { _lstate_addSepSpace = Just diff -- this always sets to
|
|
-- at least (Just 1), so we won't
|
|
-- overwrite any old value in any
|
|
-- bad way.
|
|
}
|
|
|
|
layoutBaseYPushInternal
|
|
:: (MonadMultiState LayoutState m, MonadMultiWriter (Seq String) m)
|
|
=> Int
|
|
-> m ()
|
|
layoutBaseYPushInternal i = do
|
|
traceLocal ("layoutBaseYPushInternal", i)
|
|
mModify $ \s -> s { _lstate_baseYs = i : _lstate_baseYs s }
|
|
|
|
layoutBaseYPopInternal
|
|
:: (MonadMultiState LayoutState m, MonadMultiWriter (Seq String) m) => m ()
|
|
layoutBaseYPopInternal = do
|
|
traceLocal ("layoutBaseYPopInternal")
|
|
mModify $ \s -> s { _lstate_baseYs = List.tail $ _lstate_baseYs s }
|
|
|
|
layoutIndentLevelPushInternal
|
|
:: (MonadMultiState LayoutState m, MonadMultiWriter (Seq String) m)
|
|
=> Int
|
|
-> m ()
|
|
layoutIndentLevelPushInternal i = do
|
|
traceLocal ("layoutIndentLevelPushInternal", i)
|
|
mModify $ \s -> s { _lstate_indLevelLinger = lstate_indLevel s
|
|
, _lstate_indLevels = i : _lstate_indLevels s
|
|
}
|
|
|
|
layoutIndentLevelPopInternal
|
|
:: (MonadMultiState LayoutState m, MonadMultiWriter (Seq String) m) => m ()
|
|
layoutIndentLevelPopInternal = do
|
|
traceLocal ("layoutIndentLevelPopInternal")
|
|
mModify $ \s -> s { _lstate_indLevelLinger = lstate_indLevel s
|
|
, _lstate_indLevels = List.tail $ _lstate_indLevels s
|
|
}
|
|
|
|
layoutRemoveIndentLevelLinger :: ( MonadMultiState LayoutState m
|
|
, MonadMultiWriter (Seq String) m
|
|
) => m ()
|
|
layoutRemoveIndentLevelLinger = do
|
|
#if INSERTTRACES
|
|
tellDebugMessShow ("layoutRemoveIndentLevelLinger")
|
|
#endif
|
|
mModify $ \s -> s { _lstate_indLevelLinger = lstate_indLevel s
|
|
}
|
|
|
|
layoutWithAddBaseCol :: (MonadMultiWriter
|
|
Text.Builder.Builder m,
|
|
MonadMultiState LayoutState m
|
|
,MonadMultiReader Config m
|
|
, MonadMultiWriter (Seq String) m)
|
|
=> m ()
|
|
-> m ()
|
|
layoutWithAddBaseCol m = do
|
|
#if INSERTTRACES
|
|
tellDebugMessShow ("layoutWithAddBaseCol")
|
|
#endif
|
|
amount <- mAsk <&> _conf_layout .> _lconfig_indentAmount .> confUnpack
|
|
state <- mGet
|
|
layoutBaseYPushInternal $ lstate_baseY state + amount
|
|
m
|
|
layoutBaseYPopInternal
|
|
|
|
layoutWithAddBaseColBlock
|
|
:: ( MonadMultiWriter Text.Builder.Builder m
|
|
, MonadMultiState LayoutState m
|
|
, MonadMultiReader Config m
|
|
, MonadMultiWriter (Seq String) m
|
|
)
|
|
=> m ()
|
|
-> m ()
|
|
layoutWithAddBaseColBlock m = do
|
|
#if INSERTTRACES
|
|
tellDebugMessShow ("layoutWithAddBaseColBlock")
|
|
#endif
|
|
amount <- mAsk <&> _conf_layout .> _lconfig_indentAmount .> confUnpack
|
|
state <- mGet
|
|
layoutBaseYPushInternal $ lstate_baseY state + amount
|
|
layoutWriteEnsureBlock
|
|
m
|
|
layoutBaseYPopInternal
|
|
|
|
layoutWithAddBaseColNBlock
|
|
:: ( MonadMultiWriter Text.Builder.Builder m
|
|
, MonadMultiState LayoutState m
|
|
, MonadMultiWriter (Seq String) m
|
|
)
|
|
=> Int
|
|
-> m ()
|
|
-> m ()
|
|
layoutWithAddBaseColNBlock amount m = do
|
|
traceLocal ("layoutWithAddBaseColNBlock", amount)
|
|
state <- mGet
|
|
layoutBaseYPushInternal $ lstate_baseY state + amount
|
|
layoutWriteEnsureBlock
|
|
m
|
|
layoutBaseYPopInternal
|
|
|
|
layoutWithAddBaseColN :: (MonadMultiWriter
|
|
Text.Builder.Builder m,
|
|
MonadMultiState LayoutState m
|
|
, MonadMultiWriter (Seq String) m)
|
|
=> Int
|
|
-> m ()
|
|
-> m ()
|
|
layoutWithAddBaseColN amount m = do
|
|
#if INSERTTRACES
|
|
tellDebugMessShow ("layoutWithAddBaseColN", amount)
|
|
#endif
|
|
state <- mGet
|
|
layoutBaseYPushInternal $ lstate_baseY state + amount
|
|
m
|
|
layoutBaseYPopInternal
|
|
|
|
layoutBaseYPushCur
|
|
:: (MonadMultiState LayoutState m, MonadMultiWriter (Seq String) m) => m ()
|
|
layoutBaseYPushCur = do
|
|
traceLocal ("layoutBaseYPushCur")
|
|
state <- mGet
|
|
case _lstate_commentCol state of
|
|
Nothing -> case (_lstate_curYOrAddNewline state, _lstate_addSepSpace state) of
|
|
(Left i, Just j) -> layoutBaseYPushInternal (i+j)
|
|
(Left i, Nothing) -> layoutBaseYPushInternal i
|
|
(Right{}, _) -> layoutBaseYPushInternal $ lstate_baseY state
|
|
Just cCol -> layoutBaseYPushInternal cCol
|
|
|
|
layoutBaseYPop
|
|
:: (MonadMultiState LayoutState m, MonadMultiWriter (Seq String) m) => m ()
|
|
layoutBaseYPop = do
|
|
traceLocal ("layoutBaseYPop")
|
|
layoutBaseYPopInternal
|
|
|
|
layoutIndentLevelPushCur
|
|
:: (MonadMultiState LayoutState m, MonadMultiWriter (Seq String) m) => m ()
|
|
layoutIndentLevelPushCur = do
|
|
traceLocal ("layoutIndentLevelPushCur")
|
|
state <- mGet
|
|
let y = case (_lstate_curYOrAddNewline state, _lstate_addSepSpace state) of
|
|
(Left i, Just j) -> i + j
|
|
(Left i, Nothing) -> i
|
|
(Right{}, Just j) -> j
|
|
(Right{}, Nothing) -> 0
|
|
layoutIndentLevelPushInternal y
|
|
layoutBaseYPushInternal y
|
|
|
|
layoutIndentLevelPop
|
|
:: (MonadMultiState LayoutState m, MonadMultiWriter (Seq String) m) => m ()
|
|
layoutIndentLevelPop = do
|
|
traceLocal ("layoutIndentLevelPop")
|
|
layoutBaseYPopInternal
|
|
layoutIndentLevelPopInternal
|
|
-- why are comment indentations relative to the previous indentation on
|
|
-- the first node of an additional indentation, and relative to the outer
|
|
-- indentation after the last node of some indented stuff? sure does not
|
|
-- make sense.
|
|
layoutRemoveIndentLevelLinger
|
|
|
|
layoutAddSepSpace :: (MonadMultiState LayoutState m
|
|
, MonadMultiWriter (Seq String) m)
|
|
=> m ()
|
|
layoutAddSepSpace = do
|
|
#if INSERTTRACES
|
|
tellDebugMessShow ("layoutAddSepSpace")
|
|
#endif
|
|
state <- mGet
|
|
mSet $ state { _lstate_addSepSpace = Just $ fromMaybe 1 $ _lstate_addSepSpace state }
|
|
|
|
-- TODO: when refactoring is complete, the other version of this method
|
|
-- can probably be removed.
|
|
moveToExactAnn
|
|
:: ( MonadMultiWriter Text.Builder.Builder m
|
|
, MonadMultiState LayoutState m
|
|
, MonadMultiReader (Map AnnKey Annotation) m
|
|
, MonadMultiWriter (Seq String) m
|
|
)
|
|
=> AnnKey
|
|
-> m ()
|
|
moveToExactAnn annKey = do
|
|
traceLocal ("moveToExactAnn", annKey)
|
|
anns <- mAsk
|
|
case Map.lookup annKey anns of
|
|
Nothing -> return ()
|
|
Just ann -> do
|
|
-- curY <- mGet <&> _lstate_curY
|
|
let ExactPrint.Types.DP (y, _x) = ExactPrint.Types.annEntryDelta ann
|
|
-- mModify $ \state -> state { _lstate_addNewline = Just x }
|
|
mModify $ \state ->
|
|
let upd = case _lstate_curYOrAddNewline state of
|
|
Left i -> if y==0 then Left i else Right y
|
|
Right i -> Right $ max y i
|
|
in state
|
|
{ _lstate_curYOrAddNewline = upd
|
|
, _lstate_addSepSpace = if Data.Either.isRight upd
|
|
then _lstate_commentCol state <|> _lstate_addSepSpace state <|> Just (lstate_baseY state)
|
|
else Nothing
|
|
, _lstate_commentCol = Nothing
|
|
}
|
|
-- fixMoveToLineByIsNewline :: MonadMultiState
|
|
-- LayoutState m => Int -> m Int
|
|
-- fixMoveToLineByIsNewline x = do
|
|
-- newLineState <- mGet <&> _lstate_isNewline
|
|
-- return $ if newLineState == NewLineStateYes
|
|
-- then x-1
|
|
-- else x
|
|
|
|
ppmMoveToExactLoc :: MonadMultiWriter Text.Builder.Builder m
|
|
=> ExactPrint.Types.DeltaPos
|
|
-> m ()
|
|
ppmMoveToExactLoc (ExactPrint.Types.DP (x,y)) = do
|
|
replicateM_ x $ mTell $ Text.Builder.fromString "\n"
|
|
replicateM_ y $ mTell $ Text.Builder.fromString " "
|
|
|
|
layoutWritePriorComments :: (Data.Data.Data ast,
|
|
MonadMultiWriter Text.Builder.Builder m,
|
|
MonadMultiState LayoutState m
|
|
, MonadMultiWriter (Seq String) m)
|
|
=> GenLocated SrcSpan ast -> m ()
|
|
layoutWritePriorComments ast = do
|
|
mAnn <- do
|
|
state <- mGet
|
|
let key = ExactPrint.Types.mkAnnKey ast
|
|
let anns = _lstate_comments state
|
|
let mAnn = ExactPrint.annPriorComments <$> Map.lookup key anns
|
|
mSet $ state
|
|
{ _lstate_comments =
|
|
Map.adjust (\ann -> ann { ExactPrint.annPriorComments = [] }) key anns
|
|
}
|
|
return mAnn
|
|
#if INSERTTRACES
|
|
tellDebugMessShow ("layoutWritePriorComments", ExactPrint.Types.mkAnnKey ast, mAnn)
|
|
#endif
|
|
case mAnn of
|
|
Nothing -> return ()
|
|
Just priors -> do
|
|
when (not $ null priors) $ layoutSetCommentCol
|
|
priors `forM_` \( ExactPrint.Types.Comment comment _ _
|
|
, ExactPrint.Types.DP (x, y)
|
|
) -> do
|
|
replicateM_ x layoutWriteNewline
|
|
layoutWriteAppendSpaces y
|
|
layoutWriteAppendMultiline $ Text.pack $ comment
|
|
|
|
-- this currently only extracs from the `annsDP` field of Annotations.
|
|
-- per documentation, this seems sufficient, as the
|
|
-- "..`annFollowingComments` are only added by AST transformations ..".
|
|
layoutWritePostComments :: (Data.Data.Data ast,
|
|
MonadMultiWriter Text.Builder.Builder m,
|
|
MonadMultiState LayoutState m
|
|
, MonadMultiWriter (Seq String) m)
|
|
=> GenLocated SrcSpan ast -> m ()
|
|
layoutWritePostComments ast = do
|
|
mAnn <- do
|
|
state <- mGet
|
|
let key = ExactPrint.Types.mkAnnKey ast
|
|
let anns = _lstate_comments state
|
|
let mAnn = ExactPrint.annFollowingComments <$> Map.lookup key anns
|
|
mSet $ state
|
|
{ _lstate_comments =
|
|
Map.adjust (\ann -> ann { ExactPrint.annFollowingComments = [] })
|
|
key
|
|
anns
|
|
}
|
|
return mAnn
|
|
#if INSERTTRACES
|
|
tellDebugMessShow ("layoutWritePostComments", ExactPrint.Types.mkAnnKey ast, mAnn)
|
|
#endif
|
|
case mAnn of
|
|
Nothing -> return ()
|
|
Just posts -> do
|
|
when (not $ null posts) $ layoutSetCommentCol
|
|
posts `forM_` \( ExactPrint.Types.Comment comment _ _
|
|
, ExactPrint.Types.DP (x, y)
|
|
) -> do
|
|
replicateM_ x layoutWriteNewline
|
|
layoutWriteAppend $ Text.pack $ replicate y ' '
|
|
layoutWriteAppendMultiline $ Text.pack $ comment
|
|
|
|
layoutIndentRestorePostComment
|
|
:: ( MonadMultiState LayoutState m
|
|
, MonadMultiWriter Text.Builder.Builder m
|
|
, MonadMultiWriter (Seq String) m
|
|
)
|
|
=> m ()
|
|
layoutIndentRestorePostComment = do
|
|
state <- mGet
|
|
let mCommentCol = _lstate_commentCol state
|
|
let eCurYAddNL = _lstate_curYOrAddNewline state
|
|
#if INSERTTRACES
|
|
tellDebugMessShow ("layoutIndentRestorePostComment", mCommentCol)
|
|
#endif
|
|
mModify $ \s -> s { _lstate_commentCol = Nothing }
|
|
case (mCommentCol, eCurYAddNL) of
|
|
(Just commentCol, Left{}) -> do
|
|
layoutWriteEnsureNewlineBlock
|
|
layoutWriteEnsureAbsoluteN $ commentCol + fromMaybe 0 (_lstate_addSepSpace state)
|
|
_ -> return ()
|
|
|
|
-- layoutWritePriorCommentsRestore :: (Data.Data.Data ast,
|
|
-- MonadMultiWriter Text.Builder.Builder m,
|
|
-- MonadMultiState LayoutState m
|
|
-- , MonadMultiWriter (Seq String) m)
|
|
-- => GenLocated SrcSpan ast -> m ()
|
|
-- layoutWritePriorCommentsRestore x = do
|
|
-- layoutWritePriorComments x
|
|
-- layoutIndentRestorePostComment
|
|
--
|
|
-- layoutWritePostCommentsRestore :: (Data.Data.Data ast,
|
|
-- MonadMultiWriter Text.Builder.Builder m,
|
|
-- MonadMultiState LayoutState m
|
|
-- , MonadMultiWriter (Seq String) m)
|
|
-- => GenLocated SrcSpan ast -> m ()
|
|
-- layoutWritePostCommentsRestore x = do
|
|
-- layoutWritePostComments x
|
|
-- layoutIndentRestorePostComment
|
|
|
|
extractAllComments
|
|
:: ExactPrint.Annotation -> [(ExactPrint.Comment, ExactPrint.DeltaPos)]
|
|
extractAllComments ann =
|
|
ExactPrint.annPriorComments ann
|
|
++ ExactPrint.annFollowingComments ann
|
|
++ (ExactPrint.annsDP ann >>= \case
|
|
(ExactPrint.AnnComment com, dp) -> [(com, dp)]
|
|
_ -> []
|
|
)
|
|
|
|
|
|
foldedAnnKeys :: Data.Data.Data ast
|
|
=> ast
|
|
-> Set ExactPrint.AnnKey
|
|
foldedAnnKeys ast = everything
|
|
Set.union
|
|
(\x -> maybe
|
|
Set.empty
|
|
Set.singleton
|
|
[ gmapQi 1 (\t -> ExactPrint.mkAnnKey $ L l t) x
|
|
| locTyCon == typeRepTyCon (typeOf x)
|
|
, l <- gmapQi 0 cast x
|
|
]
|
|
)
|
|
ast
|
|
where
|
|
locTyCon = typeRepTyCon (typeOf (L () ()))
|
|
|
|
filterAnns :: Data.Data.Data ast
|
|
=> ast
|
|
-> ExactPrint.Anns
|
|
-> ExactPrint.Anns
|
|
filterAnns ast anns =
|
|
Map.filterWithKey (\k _ -> k `Set.member` foldedAnnKeys ast) anns
|
|
|
|
hasAnyCommentsBelow :: Data ast => GHC.Located ast -> ToBriDocM Bool
|
|
hasAnyCommentsBelow ast@(L l _) = do
|
|
anns <- filterAnns ast <$> mAsk
|
|
return $ List.any (\(c, _) -> ExactPrint.commentIdentifier c > l)
|
|
$ (=<<) extractAllComments
|
|
$ Map.elems
|
|
$ anns
|
|
|
|
-- new BriDoc stuff
|
|
|
|
allocateNode :: MonadMultiState NodeAllocIndex m
|
|
=> BriDocFInt
|
|
-> m BriDocNumbered
|
|
allocateNode bd = do
|
|
i <- allocNodeIndex
|
|
return (i, bd)
|
|
|
|
allocNodeIndex :: MonadMultiState NodeAllocIndex m => m Int
|
|
allocNodeIndex = do
|
|
NodeAllocIndex i <- mGet
|
|
mSet $ NodeAllocIndex (i+1)
|
|
return i
|
|
|
|
-- docEmpty :: MonadMultiState NodeAllocIndex m => m BriDocNumbered
|
|
-- docEmpty = allocateNode BDFEmpty
|
|
--
|
|
-- docLit :: MonadMultiState NodeAllocIndex m => Text -> m BriDocNumbered
|
|
-- docLit t = allocateNode $ BDFLit t
|
|
--
|
|
-- docExt :: (ExactPrint.Annotate.Annotate ast, MonadMultiState NodeAllocIndex m)
|
|
-- => GenLocated SrcSpan ast -> ExactPrint.Types.Anns -> Bool -> m BriDocNumbered
|
|
-- docExt x anns shouldAddComment = allocateNode $ BDFExternal
|
|
-- (ExactPrint.Types.mkAnnKey x)
|
|
-- (foldedAnnKeys x)
|
|
-- shouldAddComment
|
|
-- (Text.pack $ ExactPrint.exactPrint x anns)
|
|
--
|
|
-- docAlt :: MonadMultiState NodeAllocIndex m => [m BriDocNumbered] -> m BriDocNumbered
|
|
-- docAlt l = allocateNode . BDFAlt =<< sequence l
|
|
--
|
|
--
|
|
-- docSeq :: MonadMultiState NodeAllocIndex m => [m BriDocNumbered] -> m BriDocNumbered
|
|
-- docSeq l = allocateNode . BDFSeq =<< sequence l
|
|
--
|
|
-- docLines :: MonadMultiState NodeAllocIndex m => [m BriDocNumbered] -> m BriDocNumbered
|
|
-- docLines l = allocateNode . BDFLines =<< sequence l
|
|
--
|
|
-- docCols :: MonadMultiState NodeAllocIndex m => ColSig -> [m BriDocNumbered] -> m BriDocNumbered
|
|
-- docCols sig l = allocateNode . BDFCols sig =<< sequence l
|
|
--
|
|
-- docAddBaseY :: MonadMultiState NodeAllocIndex m => BrIndent -> m BriDocNumbered -> m BriDocNumbered
|
|
-- docAddBaseY ind bdm = allocateNode . BDFAddBaseY ind =<< bdm
|
|
--
|
|
-- docSetBaseY :: MonadMultiState NodeAllocIndex m => m BriDocNumbered -> m BriDocNumbered
|
|
-- docSetBaseY bdm = allocateNode . BDFSetBaseY =<< bdm
|
|
--
|
|
-- docSetIndentLevel :: MonadMultiState NodeAllocIndex m => m BriDocNumbered -> m BriDocNumbered
|
|
-- docSetIndentLevel bdm = allocateNode . BDFSetIndentLevel =<< bdm
|
|
--
|
|
-- docSeparator :: MonadMultiState NodeAllocIndex m => m BriDocNumbered
|
|
-- docSeparator = allocateNode BDFSeparator
|
|
--
|
|
-- docAnnotationPrior :: MonadMultiState NodeAllocIndex m => AnnKey -> m BriDocNumbered -> m BriDocNumbered
|
|
-- docAnnotationPrior annKey bdm = allocateNode . BDFAnnotationPrior annKey =<< bdm
|
|
--
|
|
-- docAnnotationPost :: MonadMultiState NodeAllocIndex m => AnnKey -> m BriDocNumbered -> m BriDocNumbered
|
|
-- docAnnotationPost annKey bdm = allocateNode . BDFAnnotationPost annKey =<< bdm
|
|
--
|
|
-- docNonBottomSpacing :: MonadMultiState NodeAllocIndex m => m BriDocNumbered -> m BriDocNumbered
|
|
-- docNonBottomSpacing bdm = allocateNode . BDFNonBottomSpacing =<< bdm
|
|
--
|
|
-- appSep :: MonadMultiState NodeAllocIndex m => m BriDocNumbered -> m BriDocNumbered
|
|
-- appSep x = docSeq [x, docSeparator]
|
|
--
|
|
-- docCommaSep :: MonadMultiState NodeAllocIndex m => m BriDocNumbered
|
|
-- docCommaSep = appSep $ docLit $ Text.pack ","
|
|
--
|
|
-- docParenLSep :: MonadMultiState NodeAllocIndex m => m BriDocNumbered
|
|
-- docParenLSep = appSep $ docLit $ Text.pack "("
|
|
--
|
|
--
|
|
-- docPostComment :: (Data.Data.Data ast, MonadMultiState NodeAllocIndex m)
|
|
-- => GenLocated SrcSpan ast
|
|
-- -> m BriDocNumbered
|
|
-- -> m BriDocNumbered
|
|
-- docPostComment ast bdm = do
|
|
-- bd <- bdm
|
|
-- allocateNode $ BDFAnnotationPost (ExactPrint.Types.mkAnnKey ast) bd
|
|
--
|
|
-- docWrapNode :: ( Data.Data.Data ast, MonadMultiState NodeAllocIndex m)
|
|
-- => GenLocated SrcSpan ast
|
|
-- -> m BriDocNumbered
|
|
-- -> m BriDocNumbered
|
|
-- docWrapNode ast bdm = do
|
|
-- bd <- bdm
|
|
-- i1 <- allocNodeIndex
|
|
-- i2 <- allocNodeIndex
|
|
-- return
|
|
-- $ (,) i1
|
|
-- $ BDFAnnotationPrior (ExactPrint.Types.mkAnnKey ast)
|
|
-- $ (,) i2
|
|
-- $ BDFAnnotationPost (ExactPrint.Types.mkAnnKey ast)
|
|
-- $ bd
|
|
--
|
|
-- docPar :: MonadMultiState NodeAllocIndex m
|
|
-- => m BriDocNumbered
|
|
-- -> m BriDocNumbered
|
|
-- -> m BriDocNumbered
|
|
-- docPar lineM indentedM = do
|
|
-- line <- lineM
|
|
-- indented <- indentedM
|
|
-- allocateNode $ BDFPar BrIndentNone line indented
|
|
--
|
|
-- docForceSingleline :: MonadMultiState NodeAllocIndex m => m BriDocNumbered -> m BriDocNumbered
|
|
-- docForceSingleline bdm = allocateNode . BDFForceSingleline =<< bdm
|
|
--
|
|
-- docForceMultiline :: MonadMultiState NodeAllocIndex m => m BriDocNumbered -> m BriDocNumbered
|
|
-- docForceMultiline bdm = allocateNode . BDFForceMultiline =<< bdm
|
|
--
|
|
-- docEnsureIndent :: MonadMultiState NodeAllocIndex m => BrIndent -> m BriDocNumbered -> m BriDocNumbered
|
|
-- docEnsureIndent ind mbd = mbd >>= \bd -> allocateNode $ BDFEnsureIndent ind bd
|
|
|
|
docEmpty :: ToBriDocM BriDocNumbered
|
|
docEmpty = allocateNode BDFEmpty
|
|
|
|
docLit :: Text -> ToBriDocM BriDocNumbered
|
|
docLit t = allocateNode $ BDFLit t
|
|
|
|
docExt :: (ExactPrint.Annotate.Annotate ast)
|
|
=> GenLocated SrcSpan ast -> ExactPrint.Types.Anns -> Bool -> ToBriDocM BriDocNumbered
|
|
docExt x anns shouldAddComment = allocateNode $ BDFExternal
|
|
(ExactPrint.Types.mkAnnKey x)
|
|
(foldedAnnKeys x)
|
|
shouldAddComment
|
|
(Text.pack $ ExactPrint.exactPrint x anns)
|
|
|
|
docAlt :: [ToBriDocM BriDocNumbered] -> ToBriDocM BriDocNumbered
|
|
docAlt l = allocateNode . BDFAlt =<< sequence l
|
|
|
|
docAltFilter :: [(Bool, ToBriDocM BriDocNumbered)] -> ToBriDocM BriDocNumbered
|
|
docAltFilter = docAlt . map snd . filter fst
|
|
|
|
|
|
docSeq :: [ToBriDocM BriDocNumbered] -> ToBriDocM BriDocNumbered
|
|
docSeq l = allocateNode . BDFSeq =<< sequence l
|
|
|
|
docLines :: [ToBriDocM BriDocNumbered] -> ToBriDocM BriDocNumbered
|
|
docLines l = allocateNode . BDFLines =<< sequence l
|
|
|
|
docCols :: ColSig -> [ToBriDocM BriDocNumbered] -> ToBriDocM BriDocNumbered
|
|
docCols sig l = allocateNode . BDFCols sig =<< sequence l
|
|
|
|
docAddBaseY :: BrIndent -> ToBriDocM BriDocNumbered -> ToBriDocM BriDocNumbered
|
|
docAddBaseY ind bdm = allocateNode . BDFAddBaseY ind =<< bdm
|
|
|
|
docSetBaseY :: ToBriDocM BriDocNumbered -> ToBriDocM BriDocNumbered
|
|
docSetBaseY bdm = do
|
|
bd <- bdm
|
|
-- the order here is important so that these two nodes can be treated
|
|
-- properly over at `transformAlts`.
|
|
n1 <- allocateNode $ BDFBaseYPushCur bd
|
|
n2 <- allocateNode $ BDFBaseYPop n1
|
|
return n2
|
|
|
|
docSetIndentLevel :: ToBriDocM BriDocNumbered -> ToBriDocM BriDocNumbered
|
|
docSetIndentLevel bdm = do
|
|
bd <- bdm
|
|
n1 <- allocateNode $ BDFIndentLevelPushCur bd
|
|
n2 <- allocateNode $ BDFIndentLevelPop n1
|
|
return n2
|
|
|
|
docSetBaseAndIndent :: ToBriDocM BriDocNumbered -> ToBriDocM BriDocNumbered
|
|
docSetBaseAndIndent = docSetBaseY . docSetIndentLevel
|
|
|
|
docSeparator :: ToBriDocM BriDocNumbered
|
|
docSeparator = allocateNode BDFSeparator
|
|
|
|
docAnnotationPrior
|
|
:: AnnKey -> ToBriDocM BriDocNumbered -> ToBriDocM BriDocNumbered
|
|
docAnnotationPrior annKey bdm = allocateNode . BDFAnnotationPrior annKey =<< bdm
|
|
|
|
docAnnotationKW
|
|
:: AnnKey -> Maybe AnnKeywordId -> ToBriDocM BriDocNumbered -> ToBriDocM BriDocNumbered
|
|
docAnnotationKW annKey kw bdm = allocateNode . BDFAnnotationKW annKey kw =<< bdm
|
|
|
|
docAnnotationRest
|
|
:: AnnKey -> ToBriDocM BriDocNumbered -> ToBriDocM BriDocNumbered
|
|
docAnnotationRest annKey bdm = allocateNode . BDFAnnotationRest annKey =<< bdm
|
|
|
|
docNonBottomSpacing :: ToBriDocM BriDocNumbered -> ToBriDocM BriDocNumbered
|
|
docNonBottomSpacing bdm = allocateNode . BDFNonBottomSpacing =<< bdm
|
|
|
|
docSetParSpacing :: ToBriDocM BriDocNumbered -> ToBriDocM BriDocNumbered
|
|
docSetParSpacing bdm = allocateNode . BDFSetParSpacing =<< bdm
|
|
|
|
docForceParSpacing :: ToBriDocM BriDocNumbered -> ToBriDocM BriDocNumbered
|
|
docForceParSpacing bdm = allocateNode . BDFForceParSpacing =<< bdm
|
|
|
|
docDebug :: String -> ToBriDocM BriDocNumbered -> ToBriDocM BriDocNumbered
|
|
docDebug s bdm = allocateNode . BDFDebug s =<< bdm
|
|
|
|
appSep :: ToBriDocM BriDocNumbered -> ToBriDocM BriDocNumbered
|
|
appSep x = docSeq [x, docSeparator]
|
|
|
|
docCommaSep :: ToBriDocM BriDocNumbered
|
|
docCommaSep = appSep $ docLit $ Text.pack ","
|
|
|
|
docParenLSep :: ToBriDocM BriDocNumbered
|
|
docParenLSep = appSep $ docLit $ Text.pack "("
|
|
|
|
docNodeAnnKW
|
|
:: Data.Data.Data ast
|
|
=> GenLocated SrcSpan ast
|
|
-> Maybe AnnKeywordId
|
|
-> ToBriDocM BriDocNumbered
|
|
-> ToBriDocM BriDocNumbered
|
|
docNodeAnnKW ast kw bdm =
|
|
docAnnotationKW (ExactPrint.Types.mkAnnKey ast) kw bdm
|
|
|
|
class DocWrapable a where
|
|
docWrapNode :: ( Data.Data.Data ast)
|
|
=> GenLocated SrcSpan ast
|
|
-> ToBriDocM a
|
|
-> ToBriDocM a
|
|
docWrapNodePrior :: ( Data.Data.Data ast)
|
|
=> GenLocated SrcSpan ast
|
|
-> ToBriDocM a
|
|
-> ToBriDocM a
|
|
docWrapNodeRest :: ( Data.Data.Data ast)
|
|
=> GenLocated SrcSpan ast
|
|
-> ToBriDocM a
|
|
-> ToBriDocM a
|
|
|
|
instance DocWrapable BriDocNumbered where
|
|
docWrapNode ast bdm = do
|
|
bd <- bdm
|
|
i1 <- allocNodeIndex
|
|
i2 <- allocNodeIndex
|
|
return
|
|
$ (,) i1
|
|
$ BDFAnnotationPrior (ExactPrint.Types.mkAnnKey ast)
|
|
$ (,) i2
|
|
$ BDFAnnotationRest (ExactPrint.Types.mkAnnKey ast)
|
|
$ bd
|
|
docWrapNodePrior ast bdm = do
|
|
bd <- bdm
|
|
i1 <- allocNodeIndex
|
|
return
|
|
$ (,) i1
|
|
$ BDFAnnotationPrior (ExactPrint.Types.mkAnnKey ast)
|
|
$ bd
|
|
docWrapNodeRest ast bdm = do
|
|
bd <- bdm
|
|
i2 <- allocNodeIndex
|
|
return
|
|
$ (,) i2
|
|
$ BDFAnnotationRest (ExactPrint.Types.mkAnnKey ast)
|
|
$ bd
|
|
|
|
instance DocWrapable a => DocWrapable [a] where
|
|
docWrapNode ast bdsm = do
|
|
bds <- bdsm
|
|
case bds of
|
|
[] -> return $ [] -- TODO: this might be bad. maybe. then again, not really. well.
|
|
[bd] -> do
|
|
bd' <- docWrapNode ast (return bd)
|
|
return [bd']
|
|
(bd1:bdR) | (bdN:bdM) <- reverse bdR -> do
|
|
bd1' <- docWrapNodePrior ast (return bd1)
|
|
bdN' <- docWrapNodeRest ast (return bdN)
|
|
return $ [bd1'] ++ reverse bdM ++ [bdN']
|
|
_ -> error "cannot happen (TM)"
|
|
docWrapNodePrior ast bdsm = do
|
|
bds <- bdsm
|
|
case bds of
|
|
[] -> return $ []
|
|
(bd1:bdR) -> do
|
|
bd1' <- docWrapNodePrior ast (return bd1)
|
|
return $ (bd1':bdR)
|
|
docWrapNodeRest ast bdsm = do
|
|
bds <- bdsm
|
|
case reverse bds of
|
|
[] -> return $ []
|
|
(bdN:bdR) -> do
|
|
bdN' <- docWrapNodeRest ast (return bdN)
|
|
return $ reverse $ (bdN':bdR)
|
|
|
|
instance DocWrapable a => DocWrapable (Seq a) where
|
|
docWrapNode ast bdsm = do
|
|
bds <- bdsm
|
|
case Seq.viewl bds of
|
|
Seq.EmptyL -> return $ Seq.empty -- TODO: this might be bad. maybe. then again, not really. well.
|
|
bd1 Seq.:< rest -> case Seq.viewr rest of
|
|
Seq.EmptyR -> do
|
|
bd1' <- docWrapNode ast (return bd1)
|
|
return $ Seq.singleton bd1'
|
|
bdM Seq.:> bdN -> do
|
|
bd1' <- docWrapNodePrior ast (return bd1)
|
|
bdN' <- docWrapNodeRest ast (return bdN)
|
|
return $ (bd1' Seq.<| bdM) Seq.|> bdN'
|
|
docWrapNodePrior ast bdsm = do
|
|
bds <- bdsm
|
|
case Seq.viewl bds of
|
|
Seq.EmptyL -> return $ Seq.empty
|
|
bd1 Seq.:< bdR -> do
|
|
bd1' <- docWrapNodePrior ast (return bd1)
|
|
return $ bd1' Seq.<| bdR
|
|
docWrapNodeRest ast bdsm = do
|
|
bds <- bdsm
|
|
case Seq.viewr bds of
|
|
Seq.EmptyR -> return $ Seq.empty
|
|
bdR Seq.:> bdN -> do
|
|
bdN' <- docWrapNodeRest ast (return bdN)
|
|
return $ bdR Seq.|> bdN'
|
|
|
|
instance DocWrapable ([BriDocNumbered], BriDocNumbered, a) where
|
|
docWrapNode ast stuffM = do
|
|
(bds, bd, x) <- stuffM
|
|
if null bds
|
|
then do
|
|
bd' <- docWrapNode ast (return bd)
|
|
return $ (bds, bd', x)
|
|
else do
|
|
bds' <- docWrapNodePrior ast (return bds)
|
|
bd' <- docWrapNodeRest ast (return bd)
|
|
return $ (bds', bd', x)
|
|
docWrapNodePrior ast stuffM = do
|
|
(bds, bd, x) <- stuffM
|
|
bds' <- docWrapNodePrior ast (return bds)
|
|
return $ (bds', bd, x)
|
|
docWrapNodeRest ast stuffM = do
|
|
(bds, bd, x) <- stuffM
|
|
bd' <- docWrapNodeRest ast (return bd)
|
|
return $ (bds, bd', x)
|
|
|
|
|
|
|
|
docPar :: ToBriDocM BriDocNumbered
|
|
-> ToBriDocM BriDocNumbered
|
|
-> ToBriDocM BriDocNumbered
|
|
docPar lineM indentedM = do
|
|
line <- lineM
|
|
indented <- indentedM
|
|
allocateNode $ BDFPar BrIndentNone line indented
|
|
|
|
docForceSingleline :: ToBriDocM BriDocNumbered -> ToBriDocM BriDocNumbered
|
|
docForceSingleline bdm = allocateNode . BDFForceSingleline =<< bdm
|
|
|
|
docForceMultiline :: ToBriDocM BriDocNumbered -> ToBriDocM BriDocNumbered
|
|
docForceMultiline bdm = allocateNode . BDFForceMultiline =<< bdm
|
|
|
|
docEnsureIndent :: BrIndent -> ToBriDocM BriDocNumbered -> ToBriDocM BriDocNumbered
|
|
docEnsureIndent ind mbd = mbd >>= \bd -> allocateNode $ BDFEnsureIndent ind bd
|
|
|
|
unknownNodeError
|
|
:: Data.Data.Data ast => String -> ast -> ToBriDocM BriDocNumbered
|
|
unknownNodeError infoStr ast = do
|
|
mTell $ [LayoutErrorUnknownNode infoStr ast]
|
|
docLit $ Text.pack "{- BRITTANY ERROR UNHANDLED SYNTACTICAL CONSTRUCT -}"
|
|
|
|
spacifyDocs :: [ToBriDocM BriDocNumbered] -> [ToBriDocM BriDocNumbered]
|
|
spacifyDocs [] = []
|
|
spacifyDocs ds = fmap appSep (List.init ds) ++ [List.last ds]
|
|
|
|
briDocMToPPM :: ToBriDocM a -> PPM a
|
|
briDocMToPPM m = do
|
|
readers <- MultiRWSS.mGetRawR
|
|
let ((x, errs), debugs) = runIdentity
|
|
$ MultiRWSS.runMultiRWSTNil
|
|
$ MultiRWSS.withMultiStateA (NodeAllocIndex 1)
|
|
$ MultiRWSS.withMultiReaders readers
|
|
$ MultiRWSS.withMultiWriterAW
|
|
$ MultiRWSS.withMultiWriterAW
|
|
$ m
|
|
mTell debugs
|
|
mTell errs
|
|
return x
|
|
|
|
docSharedWrapper :: Monad m => (x -> m y) -> x -> m (m y)
|
|
docSharedWrapper f x = return <$> f x
|