@@ -308,20 +308,60 @@ p_stmt' pretty = \case
308308 LetStmt NoExt binds -> do
309309 txt "let "
310310 sitcc $ located binds p_hsLocalBinds
311− ParStmt NoExt stmts _ _ ->
312− sequence_ $ intersperse breakpoint $
313− withSep (txt "| ") p_parStmtBlock stmts
314− TransStmt {} -> notImplemented "TransStmt"
311+ ParStmt {} ->
312+ -- NOTE 'ParStmt' should always be eliminated in 'gatherStmt' already,
313+ -- such that it never occurs in 'p_stmt''. Consequently, handling it
314+ -- here would be redundant.
315+ notImplemented "ParStmt"
316+ TransStmt {..} -> do
317+ -- NOTE 'TransStmt' only needs to account for pretty printing itself,
318+ -- since pretty printing of relevant statements (e.g., in 'trS_stmts')
319+ -- is handled through 'gatherStmt'.
320+ case (trS_form, trS_by) of
321+ (ThenForm, Nothing) -> located trS_using $ \x -> do
322+ txt "then"
323+ breakpoint
324+ inci (p_hsExpr x)
325+ (ThenForm, Just e) -> do
326+ located trS_using $ \x -> do
327+ txt "then"
328+ breakpoint
329+ inci (p_hsExpr x)
330+ breakpoint
331+ located e $ \x -> do
332+ txt "by"
333+ breakpoint
334+ inci (p_hsExpr x)
335+ (GroupForm, Nothing) -> located trS_using $ \x -> do
336+ txt "then group using"
337+ breakpoint
338+ inci (p_hsExpr x)
339+ (GroupForm, Just e) -> do
340+ located e $ \x -> do
341+ txt "then group by"
342+ breakpoint
343+ inci (p_hsExpr x)
344+ breakpoint
345+ located trS_using $ \x -> do
346+ txt "using"
347+ breakpoint
348+ inci (p_hsExpr x)
315349 RecStmt {..} -> do
316350 txt "rec "
317351 sitcc $ newlineSep (located' (p_stmt' pretty)) recS_stmts
318352 XStmtLR {} -> notImplemented "XStmtLR"
319353
320−p_parStmtBlock :: ParStmtBlock GhcPs GhcPs -> R ()
321−p_parStmtBlock = \case
322− ParStmtBlock NoExt stmts _ _ ->
323− velt $ withSep comma (located' (sitcc . p_stmt)) stmts
324− XParStmtBlock {} -> notImplemented "XParStmtBlock"
354+gatherStmt :: ExprLStmt GhcPs -> [[ExprLStmt GhcPs]]
355+gatherStmt (L _ (ParStmt NoExt block _ _)) =
356+ foldr ((<>) . gatherStmtBlock) [] block
357+gatherStmt (L s stmt@TransStmt {..}) =
358+ foldr liftAppend [] ((gatherStmt <$> trS_stmts) <> pure [[L s stmt]])
359+gatherStmt stmt = [[stmt]]
360+
361+gatherStmtBlock :: ParStmtBlock GhcPs GhcPs -> [[ExprLStmt GhcPs]]
362+gatherStmtBlock (ParStmtBlock _ stmts _ _) =
363+ foldr (liftAppend . gatherStmt) [] stmts
364+gatherStmtBlock XParStmtBlock {} = notImplemented "XParStmtBlock"
325365
326366p_hsLocalBinds :: HsLocalBindsLR GhcPs GhcPs -> R ()
327367p_hsLocalBinds = \case
@@ -468,14 +508,21 @@ p_hsExpr = \case
468508 newline
469509 inci $ located es (newlineSep (located' (sitcc . p_stmt)))
470510 compBody = brackets $ located es $ \xs -> do
471− let stmts = init xs
511+ let p_parBody =
512+ sequence_ .
513+ intersperse breakpoint .
514+ withSep (txt "| ") p_seqBody
515+ p_seqBody =
516+ sequence_ .
517+ intersperse (vlayout (pure ()) newline) .
518+ withSep comma (located' (sitcc . p_stmt))
519+ stmts = init xs
472520 yield = last xs
521+ lists = foldr (liftAppend . gatherStmt) [] stmts
473522 located yield p_stmt
474523 breakpoint
475524 txt "| "
476− case stmts of
477− [stmt] | ParStmt {} <- unLoc stmt -> located stmt p_stmt
478− _ -> velt $ withSep comma (located' (sitcc . p_stmt)) stmts
525+ p_parBody lists
479526 case ctx of
480527 DoExpr -> doBody "do"
481528 MDoExpr -> doBody "mdo"
@@ -757,6 +804,15 @@ p_hsBracket = \case
757804----------------------------------------------------------------------------
758805-- Helpers
759806
807+-- | Append each element in both lists with semigroups. If one list is shorter
808+-- than the other, return the rest of the longer list unchanged.
809+
810+liftAppend :: Semigroup a => [a] -> [a] -> [a]
811+liftAppend [] [] = []
812+liftAppend [] (y : ys) = y : ys
813+liftAppend (x : xs) [] = x : xs
814+liftAppend (x : xs) (y : ys) = x <> y : liftAppend xs ys
815+
760816getGRHSSpan :: GRHS GhcPs (Located body) -> SrcSpan
761817getGRHSSpan (GRHS NoExt _ body) = getLoc body
762818getGRHSSpan (XGRHS NoExt) = notImplemented "XGRHS"