Skip to content

Commit 810e6ad

Browse files
authored
fix renderFits (#10)
1 parent 304589e commit 810e6ad

File tree

1 file changed

+38
-22
lines changed

1 file changed

+38
-22
lines changed

src/Text/PrettyPrint/Leijen.purs

Lines changed: 38 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import Data.Foldable (foldr, intercalate)
1111
import Data.Generic.Rep (class Generic)
1212
import Data.Generic.Rep.Show (genericShow)
1313
import Data.Int as Int
14+
import Data.Lazy (Lazy, force, defer)
1415
import Data.List as List
1516
import Data.List.Lazy as LL
1617
import Data.Maybe (Maybe(..))
@@ -589,6 +590,20 @@ data SimpleDoc = SFail
589590
| SText Int String SimpleDoc
590591
| SLine Int SimpleDoc
591592

593+
data LazySimpleDoc = SFail'
594+
| SEmpty'
595+
| SChar' Char (Lazy LazySimpleDoc)
596+
| SText' Int String (Lazy LazySimpleDoc)
597+
| SLine' Int (Lazy LazySimpleDoc)
598+
599+
forceSimpleDoc :: LazySimpleDoc -> SimpleDoc
600+
forceSimpleDoc = case _ of
601+
SFail' -> SFail
602+
SEmpty' -> SEmpty
603+
SChar' c x -> SChar c (forceSimpleDoc $ force x)
604+
SText' i s x -> SText i s (forceSimpleDoc $ force x)
605+
SLine' i x -> SLine i (forceSimpleDoc $ force x)
606+
592607
derive instance simpleDocEq :: Eq SimpleDoc
593608
derive instance simpleDocOrd :: Ord SimpleDoc
594609
derive instance genericSimpleDoc :: Generic SimpleDoc _
@@ -748,7 +763,7 @@ renderPretty = renderFits fits1
748763
renderSmart :: Number -> Int -> Doc -> SimpleDoc
749764
renderSmart = renderFits fitsR
750765

751-
renderFits :: (Int -> Int -> Int -> SimpleDoc -> Boolean)
766+
renderFits :: (Int -> Int -> Int -> LazySimpleDoc -> Boolean)
752767
-> Number -> Int -> Doc -> SimpleDoc
753768
renderFits fits rfrac w headNode
754769
-- I used to do a @SSGR [Reset]@ here, but if you do that it will result
@@ -759,22 +774,23 @@ renderFits fits rfrac w headNode
759774
-- What I "really" want to do here is do an initial Reset iff there is some
760775
-- ANSI color within the Doc, but that's a bit fiddly. I'll fix it if someone
761776
-- complains!
762-
= best 0 0 (Cons 0 headNode Nil)
777+
= forceSimpleDoc $best 0 0 (Cons 0 headNode Nil)
763778
where
764779
-- r :: the ribbon width in characters
765780
r = max 0 (min w (Int.round (Int.toNumber w * rfrac)))
766781

767782
-- best :: n = indentation of current line
768783
-- k = current column
769784
-- (ie. (k >= n) && (k - n == count of inserted characters)
770-
best n k Nil = SEmpty
785+
best :: Int -> Int -> Docs -> LazySimpleDoc
786+
best n k Nil = SEmpty'
771787
best n k (Cons i d ds)
772788
= case d of
773-
Fail -> SFail
789+
Fail -> SFail'
774790
Empty -> best n k ds
775-
Char c -> let k' = k+1 in SChar c (best n k' ds)
776-
Text l s -> let k' = k+l in SText l s (best n k' ds)
777-
Line -> SLine i (best i i ds)
791+
Char c -> let k' = k+1 in SChar' c (defer \_ -> best n k' ds)
792+
Text l s -> let k' = k+l in SText' l s (defer\_ -> best n k' ds)
793+
Line -> SLine' i (defer \_ -> best i i ds)
778794
FlatAlt x _ -> best n k (Cons i x ds)
779795
Cat x y -> best n k (Cons i x (Cons i y ds))
780796
Nest j x -> let i' = i+j in best n k (Cons i' x ds)
@@ -800,13 +816,13 @@ renderFits fits rfrac w headNode
800816
in if fits w (min n k) width' x' then x' else let y' = best n k (Cons i y ds) in y'
801817

802818
-- | @fits1@ does 1 line lookahead.
803-
fits1 :: Int -> Int -> Int -> SimpleDoc -> Boolean
804-
fits1 _ _ w x | w < 0 = false
805-
fits1 _ _ w SFail = false
806-
fits1 _ _ w SEmpty = true
807-
fits1 p m w (SChar c x) = fits1 p m (w - 1) x
808-
fits1 p m w (SText l s x) = fits1 p m (w - l) x
809-
fits1 _ _ w (SLine i x) = true
819+
fits1 :: Int -> Int -> Int -> LazySimpleDoc -> Boolean
820+
fits1 _ _ w x | w < 0 = false
821+
fits1 _ _ w SFail' = false
822+
fits1 _ _ w SEmpty' = true
823+
fits1 p m w (SChar' c x) = fits1 p m (w - 1) (force x)
824+
fits1 p m w (SText' l s x) = fits1 p m (w - l) (force x)
825+
fits1 _ _ w (SLine' i x) = true
810826

811827
-- | @fitsR@ has a little more lookahead: assuming that nesting roughly
812828
-- | corresponds to syntactic depth, @fitsR@ checks that not only the current line
@@ -818,14 +834,14 @@ fits1 _ _ w (SLine i x) = true
818834
-- | p = pagewidth
819835
-- | m = minimum nesting level to fit in
820836
-- | w = the width in which to fit the first line
821-
fitsR :: Int -> Int -> Int -> SimpleDoc -> Boolean
822-
fitsR p m w x | w < 0 = false
823-
fitsR p m w SFail = false
824-
fitsR p m w SEmpty = true
825-
fitsR p m w (SChar c x) = fitsR p m (w - 1) x
826-
fitsR p m w (SText l s x) = fitsR p m (w - l) x
827-
fitsR p m w (SLine i x) | m < i = fitsR p m (p - i) x
828-
| otherwise = true
837+
fitsR :: Int -> Int -> Int -> LazySimpleDoc -> Boolean
838+
fitsR p m w x | w < 0 = false
839+
fitsR p m w SFail' = false
840+
fitsR p m w SEmpty' = true
841+
fitsR p m w (SChar' c x) = fitsR p m (w - 1) (force x)
842+
fitsR p m w (SText' l s x) = fitsR p m (w - l) (force x)
843+
fitsR p m w (SLine' i x) | m < i = fitsR p m (p - i) (force x)
844+
| otherwise = true
829845

830846
-----------------------------------------------------------
831847
-- renderCompact: renders documents without indentation

0 commit comments

Comments
 (0)