@@ -11,6 +11,7 @@ import Data.Foldable (foldr, intercalate)
11
11
import Data.Generic.Rep (class Generic )
12
12
import Data.Generic.Rep.Show (genericShow )
13
13
import Data.Int as Int
14
+ import Data.Lazy (Lazy , force , defer )
14
15
import Data.List as List
15
16
import Data.List.Lazy as LL
16
17
import Data.Maybe (Maybe (..))
@@ -589,6 +590,20 @@ data SimpleDoc = SFail
589
590
| SText Int String SimpleDoc
590
591
| SLine Int SimpleDoc
591
592
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
+
592
607
derive instance simpleDocEq :: Eq SimpleDoc
593
608
derive instance simpleDocOrd :: Ord SimpleDoc
594
609
derive instance genericSimpleDoc :: Generic SimpleDoc _
@@ -748,7 +763,7 @@ renderPretty = renderFits fits1
748
763
renderSmart :: Number -> Int -> Doc -> SimpleDoc
749
764
renderSmart = renderFits fitsR
750
765
751
- renderFits :: (Int -> Int -> Int -> SimpleDoc -> Boolean )
766
+ renderFits :: (Int -> Int -> Int -> LazySimpleDoc -> Boolean )
752
767
-> Number -> Int -> Doc -> SimpleDoc
753
768
renderFits fits rfrac w headNode
754
769
-- 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
759
774
-- What I "really" want to do here is do an initial Reset iff there is some
760
775
-- ANSI color within the Doc, but that's a bit fiddly. I'll fix it if someone
761
776
-- complains!
762
- = best 0 0 (Cons 0 headNode Nil )
777
+ = forceSimpleDoc $ best 0 0 (Cons 0 headNode Nil )
763
778
where
764
779
-- r :: the ribbon width in characters
765
780
r = max 0 (min w (Int .round (Int .toNumber w * rfrac)))
766
781
767
782
-- best :: n = indentation of current line
768
783
-- k = current column
769
784
-- (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'
771
787
best n k (Cons i d ds)
772
788
= case d of
773
- Fail -> SFail
789
+ Fail -> SFail'
774
790
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)
778
794
FlatAlt x _ -> best n k (Cons i x ds)
779
795
Cat x y -> best n k (Cons i x (Cons i y ds))
780
796
Nest j x -> let i' = i+j in best n k (Cons i' x ds)
@@ -800,13 +816,13 @@ renderFits fits rfrac w headNode
800
816
in if fits w (min n k) width' x' then x' else let y' = best n k (Cons i y ds) in y'
801
817
802
818
-- | @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
810
826
811
827
-- | @fitsR@ has a little more lookahead: assuming that nesting roughly
812
828
-- | corresponds to syntactic depth, @fitsR@ checks that not only the current line
@@ -818,14 +834,14 @@ fits1 _ _ w (SLine i x) = true
818
834
-- | p = pagewidth
819
835
-- | m = minimum nesting level to fit in
820
836
-- | 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
829
845
830
846
-- ---------------------------------------------------------
831
847
-- renderCompact: renders documents without indentation
0 commit comments