Some minor refactors to improve building performance
Getty Ritter
7 years ago
| 194 | 194 | -- s-expressions, then we might as well consider it flat and let |
| 195 | 195 | -- it take the whole line |
| 196 | 196 | | Just strings <- T.traverse ppBasic (initial Seq.<| values) = |
| 197 |
Seq.singleton (B. |
|
| 197 | Seq.singleton (B.singleton '(' <> buildUnwords strings <> pTail rest) | |
| 198 | 198 | |
| 199 | 199 | -- it's not "flat", so we might want to swing after the first thing |
| 200 | 200 | | Swing <- iv = |
| 206 | 206 | -- ...or after several things |
| 207 | 207 | | SwingAfter n <- iv = |
| 208 | 208 | let (hs, xs) = Seq.splitAt n (initial Seq.<| values) |
| 209 |
hd = B. |
|
| 209 | hd = B.singleton '(' <> buildUnwords (F.foldMap go hs) | |
| 210 | 210 | butLast = hd Seq.<| fmap doIndent (F.foldMap go xs) |
| 211 | 211 | in handleTail rest butLast |
| 212 | 212 | |
| 229 | 229 | -- with spaces and everything else gets indended the |
| 230 | 230 | -- forementioned length |
| 231 | 231 | y Seq.:< ys -> |
| 232 |
let hd = B. |
|
| 232 | let hd = B.singleton '(' <> buildUnwords (F.foldMap go (Seq.fromList [initial, y])) | |
| 233 | 233 | butLast = hd Seq.<| fmap (doIndentOf (fromIntegral len)) (F.foldMap go ys) |
| 234 | 234 | in handleTail rest butLast |
| 235 | 235 | |
| 242 | 242 | insertParen :: Seq.Seq B.Builder -> Seq.Seq B.Builder |
| 243 | 243 | insertParen s = case Seq.viewl s of |
| 244 | 244 | Seq.EmptyL -> s |
| 245 |
x Seq.:< xs -> (B. |
|
| 245 | x Seq.:< xs -> (B.singleton '(' <> x) Seq.<| xs | |
| 246 | 246 | |
| 247 | 247 | handleTail :: Maybe Text -> Seq.Seq B.Builder -> Seq.Seq B.Builder |
| 248 | 248 | handleTail Nothing = insertCloseParen |
| 249 | 249 | handleTail (Just t) = |
| 250 |
(Seq.|> (B.fromString " . " <> B.fromText t <> B. |
|
| 250 | (Seq.|> (B.fromString " . " <> B.fromText t <> B.singleton ')')) | |
| 251 | 251 | |
| 252 | 252 | insertCloseParen :: Seq.Seq B.Builder -> Seq.Seq B.Builder |
| 253 | 253 | insertCloseParen s = case Seq.viewr s of |
| 254 | Seq.EmptyR -> Seq.singleton (B.fromString ")") | |
| 255 | xs Seq.:> x -> xs Seq.|> (x <> B.fromString ")") | |
| 254 | Seq.EmptyR -> Seq.singleton (B.singleton ')') | |
| 255 | xs Seq.:> x -> xs Seq.|> (x <> B.singleton ')') | |
| 256 | 256 | |
| 257 | 257 | buildUnwords sq = |
| 258 | 258 | case Seq.viewl sq of |
| 259 | 259 | Seq.EmptyL -> mempty |
| 260 | t Seq.:< ts -> t <> F.foldMap (\ x -> B.fromString " " <> x) ts | |
| 261 | ||
| 262 | pTail Nothing = B.fromString ")" | |
| 263 | pTail (Just t) = B.fromString " . " <> B.fromText t <> B.fromString ")" | |
| 260 | t Seq.:< ts -> t <> F.foldMap (\ x -> B.singleton ' ' <> x) ts | |
| 261 | ||
| 262 | pTail Nothing = B.singleton ')' | |
| 263 | pTail (Just t) = B.fromString " . " <> B.fromText t <> B.singleton ')' | |
| 264 | 264 | |
| 265 | 265 | ppBasic (IAtom t) = Just (B.fromText t) |
| 266 | 266 | ppBasic (IEmpty) = Just (B.fromString "()") |
| 324 | 324 | setIndentStrategy st pr = pr { swingIndent = st } |
| 325 | 325 | |
| 326 | 326 | |
| 327 | spaceDot :: B.Builder | |
| 328 | spaceDot = B.singleton ' ' <> B.singleton '.' <> B.singleton ' ' | |
| 329 | ||
| 327 | 330 | -- Indents a line by n spaces |
| 328 | 331 | indent :: Int -> B.Builder -> B.Builder |
| 329 |
indent n ts = |
|
| 332 | indent n ts = | |
| 333 | mconcat [ B.singleton ' ' | _ <- [1..n]] <> ts | |
| 330 | 334 | |
| 331 | 335 | |
| 332 | 336 | -- Sort of like 'unlines' but without the trailing newline |
| 386 | 390 | pp ind (IList i sz h values end) = |
| 387 | 391 | -- we always are going to have a head, a (possibly empty) body, |
| 388 | 392 | -- and a (possibly empty) tail in our list formats |
| 389 |
B. |
|
| 393 | B.singleton '(' <> hd <> body <> tl <> B.singleton ')' | |
| 390 | 394 | where |
| 391 | 395 | -- the tail is either nothing, or the final dotted pair |
| 392 | 396 | tl = case end of |
| 416 | 420 | | length values == 0 = mempty |
| 417 | 421 | -- if we can't fit the whole next s-expression on the same |
| 418 | 422 | -- line, then we use the indented form |
| 419 |
| sizeSum sz + ind > maxAmt = B. |
|
| 423 | | sizeSum sz + ind > maxAmt = B.singleton ' ' <> indented | |
| 420 | 424 | | otherwise = |
| 421 | 425 | -- otherwise we print the whole thing on one line! |
| 422 |
B. |
|
| 426 | B.singleton ' ' <> unwordsS (fmap (pp (ind + 1)) values) | |
| 423 | 427 | |
| 424 | 428 | |
| 425 | 429 | -- if we don't indent anything, then we can ignore a bunch of the |
| 428 | 432 | flatPrintSExpr = B.toLazyText . pHead |
| 429 | 433 | where |
| 430 | 434 | pHead (SCons x xs) = |
| 431 |
B. |
|
| 435 | B.singleton '(' <> pHead x <> pTail xs | |
| 432 | 436 | pHead (SAtom t) = |
| 433 | 437 | B.fromText t |
| 434 | 438 | pHead SNil = |
| 435 |
B. |
|
| 439 | B.singleton '(' <> B.singleton ')' | |
| 436 | 440 | |
| 437 | 441 | pTail (SCons x xs) = |
| 438 |
B. |
|
| 442 | B.singleton ' ' <> pHead x <> pTail xs | |
| 439 | 443 | pTail (SAtom t) = |
| 440 |
|
|
| 444 | spaceDot <> | |
| 445 | B.fromText t <> | |
| 446 | B.singleton ')' | |
| 441 | 447 | pTail SNil = |
| 442 |
B. |
|
| 448 | B.singleton ')' | |
| 449 | ||
| 443 | 450 | |
| 444 | 451 | -- | Turn a single s-expression into a string according to a given |
| 445 | 452 | -- 'SExprPrinter'. |
| 447 | 454 | encodeOne s@(SExprPrinter { .. }) = |
| 448 | 455 | TL.toStrict . prettyPrintSExpr (s { fromCarrier = id }) . fromCarrier |
| 449 | 456 | |
| 457 | ||
| 450 | 458 | -- | Turn a list of s-expressions into a single string according to |
| 451 | 459 | -- a given 'SExprPrinter'. |
| 452 | 460 | encode :: SExprPrinter atom carrier -> [carrier] -> Text |
| 453 | 461 | encode spec = |
| 454 | 462 | T.intercalate "\n\n" . map (encodeOne spec) |
| 455 | 463 | |
| 464 | ||
| 456 | 465 | -- | Turn a single s-expression into a lazy 'Text' according to a given |
| 457 | 466 | -- 'SExprPrinter'. |
| 458 | 467 | encodeOneLazy :: SExprPrinter atom carrier -> carrier -> TL.Text |
| 459 | 468 | encodeOneLazy s@(SExprPrinter { .. }) = |
| 460 | 469 | prettyPrintSExpr (s { fromCarrier = id }) . fromCarrier |
| 461 | 470 | |
| 471 | ||
| 462 | 472 | -- | Turn a list of s-expressions into a lazy 'Text' according to |
| 463 | 473 | -- a given 'SExprPrinter'. |
| 464 | 474 | encodeLazy :: SExprPrinter atom carrier -> [carrier] -> TL.Text |