Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

First naive attempt to generalise the API to support different textual representations #43

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 44 additions & 23 deletions bench/Bench.hs
Original file line number Diff line number Diff line change
@@ -1,11 +1,20 @@
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE PackageImports #-}
{-# OPTIONS_GHC -fno-warn-orphans #-}
module Main where

import Criterion.Main
import qualified Data.ByteString.Char8 as B
import Data.String
import Data.List
import Text.PrettyPrint.Annotated.HughesPJ (txtPrinter, RuneSequence(..))
import Text.PrettyPrint.HughesPJ
import Data.Proxy

instance RuneSequence B.ByteString where
len = B.length
unpack = B.unpack

--------------------------------------------------------------------------------
f_left :: Int -> Doc
Expand All @@ -16,39 +25,37 @@ f_right :: Int -> Doc
f_right n = foldr (<>) empty (map (text . show) [10001..10000+n])

--------------------------------------------------------------------------------
stuff :: String -> String -> Double -> Rational -> Int -> Int -> Int -> Doc
stuff s1 s2 d1 r1 i1 i2 i3 =
stuff :: (IsString r, RuneSequence r) => Proxy r -> r -> r -> Double -> Rational -> Int -> Int -> Int -> Doc
stuff proxy s1 s2 d1 r1 i1 i2 i3 =
let a = nest i1 $ text s1
b = double d1
c = rational r1
d = replicate i1 (text s2 <> b <> c <+> a)
e = cat d $+$ cat d $$ (c <> b <+> a)
f = parens e <> brackets c <> hcat d
g = lparen <> f <> rparen
h = text $ s2 ++ s1
h = text $ (append proxy s2 s1)
i = map rational ([1..(toRational i2)]::[Rational])
j = punctuate comma i
k = nest i3 h <> (nest (i1 + i3) $ sep i) $+$ g <> cat j
l = cat $ punctuate (comma <> b <> comma) $ replicate i3 k
in l

--------------------------------------------------------------------------------
doc1 :: Doc
doc1 = stuff "Adsas ads" "dassdab weeaa xxxxx" 123.231321 ((-1)/5) 30 300 20
append :: RuneSequence r => Proxy r -> r -> r -> r
append Proxy = mappend

--------------------------------------------------------------------------------
doc2 :: Doc
doc2 = stuff "aDSAS ADS asdasdsa sdsda xx" "SDAB WEEAA" 1333.212 ((-4)/5) 31 301 30
doc1 :: (IsString r, RuneSequence r) => Proxy r -> Doc
doc1 p = stuff p "Adsas ads" "dassdab weeaa xxxxx" 123.231321 ((-1)/5) 30 300 40

--------------------------------------------------------------------------------
doc3 :: Doc
doc3 = stuff "ADsAs --____ aDS" "DasSdAB weEAA" 2533.21299 ((-4)/999) 39 399 60
----------------------------------------------------------------------------------
doc2 :: (IsString r, RuneSequence r) => Proxy r -> Doc
doc2 p = stuff p "aDSAS ADS asdasdsa sdsda xx" "SDAB WEEAA" 1333.212 ((-4)/5) 31 301 60

--------------------------------------------------------------------------------
processTxt :: TextDetails -> String -> String
processTxt (Chr c) s = c:s
processTxt (Str s1) s2 = s1 ++ s2
processTxt (PStr s1) s2 = s1 ++ s2
----------------------------------------------------------------------------------
doc3 :: (IsString r, RuneSequence r) => Proxy r -> Doc
doc3 p = stuff p "ADsAs --____ aDS" "DasSdAB weEAA" 2533.21299 ((-4)/999) 39 399 120

--------------------------------------------------------------------------------
main :: IO ()
Expand All @@ -61,15 +68,29 @@ main = defaultMain $ [
, bench "right30k" $ nf (length . render . f_right) 30000
]

, bgroup "render" [ bench "doc1" $ nf render doc1
, bench "doc2" $ nf render doc2
, bench "doc3" $ nf render doc3
, bgroup "render" [ bench "doc1/string" $ nf render (doc1 strPxy)
, bench "doc1/bytestring" $ nf render (doc1 bsPxy)
, bench "doc2/string" $ nf render (doc2 strPxy)
, bench "doc2/bytestring" $ nf render (doc2 bsPxy)
, bench "doc3/string" $ nf render (doc3 strPxy)
, bench "doc2/bytestring" $ nf render (doc3 bsPxy)
]

, bgroup "fullRender" [ bench "PageMode 1000" $ nf (fullRender PageMode 1000 4 processTxt "") doc2
, bench "PageMode 100" $ nf (fullRender PageMode 100 1.5 processTxt "") doc2
, bench "ZigZagMode" $ nf (fullRender ZigZagMode 1000 4 processTxt "") doc2
, bench "LeftMode" $ nf (fullRender LeftMode 1000 4 processTxt "") doc2
, bench "OneLineMode" $ nf (fullRender OneLineMode 1000 4 processTxt "") doc3
, bgroup "fullRender" [ bench "PageMode 1000/string" $ nf (fullRender PageMode 1000 4 txtPrinter "") (doc2 strPxy)
, bench "PageMode 1000/bytestring" $ nf (fullRender PageMode 1000 4 txtPrinter "") (doc2 bsPxy)
, bench "PageMode 100/string" $ nf (fullRender PageMode 100 1.5 txtPrinter "") (doc2 strPxy)
, bench "PageMode 100/bytestring" $ nf (fullRender PageMode 100 1.5 txtPrinter "") (doc2 bsPxy)
, bench "ZigZagMode/string" $ nf (fullRender ZigZagMode 1000 4 txtPrinter "") (doc2 strPxy)
, bench "ZigZagMode/bytestring" $ nf (fullRender ZigZagMode 1000 4 txtPrinter "") (doc2 bsPxy)
, bench "LeftMode/string" $ nf (fullRender LeftMode 1000 4 txtPrinter "") (doc2 strPxy)
, bench "LeftMode/bytestring" $ nf (fullRender LeftMode 1000 4 txtPrinter "") (doc2 bsPxy)
, bench "OneLineMode/string" $ nf (fullRender OneLineMode 1000 4 txtPrinter "") (doc3 strPxy)
, bench "OneLineMode/bytestring" $ nf (fullRender OneLineMode 1000 4 txtPrinter "") (doc3 bsPxy)
]
]
where
strPxy :: Proxy String
strPxy = Proxy

bsPxy :: Proxy B.ByteString
bsPxy = Proxy
1 change: 1 addition & 0 deletions pretty.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -77,3 +77,4 @@ benchmark pretty-bench
build-depends: base >= 4.5 && < 5
, criterion
, pretty
, bytestring
1 change: 1 addition & 0 deletions src/Text/PrettyPrint/Annotated.hs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ module Text.PrettyPrint.Annotated (
renderStyle,

-- ** General rendering
RuneSequence(..),
fullRender,
fullRenderAnn,
Mode(..), TextDetails(..)
Expand Down
28 changes: 22 additions & 6 deletions src/Text/PrettyPrint/Annotated/HughesPJ.hs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#if __GLASGOW_HASKELL__ >= 701
{-# LANGUAGE Safe #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE FlexibleInstances #-}
#endif

-----------------------------------------------------------------------------
Expand Down Expand Up @@ -76,8 +77,10 @@ module Text.PrettyPrint.Annotated.HughesPJ (
Mode(..),

-- ** General rendering
RuneSequence(..),
fullRender,
fullRenderAnn
fullRenderAnn,
txtPrinter

) where
#endif
Expand Down Expand Up @@ -248,6 +251,17 @@ annotSize :: AnnotDetails a -> Int
annotSize (NoAnnot _ l) = l
annotSize _ = 0

-- | A `RuneSequence` represents a piece of textual data which can be
-- reified back to a `String`, and which supports an efficient way to get
-- the total length of the sequence.
class Monoid r => RuneSequence r where
len :: r -> Int
unpack :: r -> String

instance RuneSequence [Char] where
len = length
unpack = id

-- | A TextDetails represents a fragment of text that will be output at some
-- point in a @Doc@.
data TextDetails = Chr {-# UNPACK #-} !Char -- ^ A single Char fragment
Expand All @@ -258,6 +272,7 @@ data TextDetails = Chr {-# UNPACK #-} !Char -- ^ A single Char fragment
#if __GLASGOW_HASKELL__ >= 701
deriving (Show, Eq, Generic)
#endif
{-# DEPRECATED PStr "PStr is deprecated, please use Str instead." #-}

-- Combining @Doc@ values
#if __GLASGOW_HASKELL__ >= 800
Expand Down Expand Up @@ -341,20 +356,21 @@ char c = textBeside_ (NoAnnot (Chr c) 1) Empty
--
-- The side condition on the last law is necessary because @'text' \"\"@
-- has height 1, while 'empty' has no height.
text :: String -> Doc a
text s = case length s of {sl -> textBeside_ (NoAnnot (Str s) sl) Empty}
text :: RuneSequence r => r -> Doc a
text s = case len s of {sl -> textBeside_ (NoAnnot (Str . unpack $ s) sl) Empty}

-- | Same as @text@. Used to be used for Bytestrings.
ptext :: String -> Doc a
ptext s = case length s of {sl -> textBeside_ (NoAnnot (PStr s) sl) Empty}
{-# DEPRECATED ptext "ptext is deprecated, use text instead." #-}

-- | Some text with any width. (@text s = sizedText (length s) s@)
sizedText :: Int -> String -> Doc a
sizedText l s = textBeside_ (NoAnnot (Str s) l) Empty
sizedText :: RuneSequence r => Int -> r -> Doc a
sizedText l s = textBeside_ (NoAnnot (Str . unpack $ s) l) Empty

-- | Some text, but without any width. Use for non-printing text
-- such as a HTML or Latex tags
zeroWidthText :: String -> Doc a
zeroWidthText :: RuneSequence r => r -> Doc a
zeroWidthText = sizedText 0

-- | The empty document, with no height and no width.
Expand Down
9 changes: 5 additions & 4 deletions src/Text/PrettyPrint/HughesPJ.hs
Original file line number Diff line number Diff line change
Expand Up @@ -171,22 +171,23 @@ char c = Doc (Ann.char c)
--
-- The side condition on the last law is necessary because @'text' \"\"@
-- has height 1, while 'empty' has no height.
text :: String -> Doc
text :: Ann.RuneSequence r => r -> Doc
text s = Doc (Ann.text s)
{-# INLINE text #-}

-- | Same as @text@. Used to be used for Bytestrings.
--- | Same as @text@. Used to be used for Bytestrings.
ptext :: String -> Doc
ptext s = Doc (Ann.ptext s)
{-# INLINE ptext #-}
{-# DEPRECATED ptext "ptext is deprecated, use text instead." #-}

-- | Some text with any width. (@text s = sizedText (length s) s@)
sizedText :: Int -> String -> Doc
sizedText :: Ann.RuneSequence r => Int -> r -> Doc
sizedText l s = Doc (Ann.sizedText l s)

-- | Some text, but without any width. Use for non-printing text
-- such as a HTML or Latex tags
zeroWidthText :: String -> Doc
zeroWidthText :: Ann.RuneSequence r => r -> Doc
zeroWidthText = sizedText 0

-- | The empty document, with no height and no width.
Expand Down
1 change: 1 addition & 0 deletions tests/PrettyTestVersion.hs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
{-# LANGUAGE BangPatterns #-}
#if __GLASGOW_HASKELL__ >= 701
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE FlexibleInstances #-}
#endif

#define TESTING
Expand Down