module Text.PrettyPrint.JoinPrint.JoinString
(
JoinString
, toString
, empty
, text
, cons
, snoc
, cons1
, (++)
, length
, null
, foldr
, foldl
, takeLeft
, takeRight
, dropLeft
, dropRight
) where
import Data.Monoid
import qualified Prelude as Pre
import Prelude hiding ( (++), foldl, foldr, length, null )
data JoinString = Empty
| Leaf Int String
| Tree Int JoinString JoinString
deriving (Eq,Show)
instance Monoid JoinString where
mempty = Empty
mappend = (++)
empty :: JoinString
empty = Empty
text :: String -> JoinString
text [] = Empty
text s = Leaf (Pre.length s) s
cons :: String -> JoinString -> JoinString
cons s xs = text s ++ xs
snoc :: JoinString -> String -> JoinString
snoc xs s = xs ++ text s
cons1 :: Char -> JoinString -> JoinString
cons1 c Empty = Leaf 1 [c]
cons1 c (Leaf i s) = Leaf (i+1) (c:s)
cons1 c (Tree i t u) = Tree (i+1) (cons1 c t) u
(++) :: JoinString -> JoinString -> JoinString
Empty ++ ys = ys
xs ++ Empty = xs
xs ++ ys = Tree (length xs + length ys) xs ys
length :: JoinString -> Int
length Empty = 0
length (Leaf i _) = i
length (Tree i _ _) = i
null :: JoinString -> Bool
null Empty = True
null _ = False
toString :: JoinString -> String
toString = foldr (flip (Pre.++)) ""
foldr :: (String -> b -> b) -> b -> JoinString -> b
foldr _ e Empty = e
foldr f e (Leaf _ xs) = f xs e
foldr f e (Tree _ t u) = foldr f (foldr f e t) u
foldl :: (b -> String -> b) -> b -> JoinString -> b
foldl _ e Empty = e
foldl f e (Leaf _ xs) = f e xs
foldl f e (Tree _ t u) = foldl f (foldl f e u) t
takeLeft :: Int -> JoinString -> JoinString
takeLeft = build `oo` step where
build (i,xs) | i <= 0 = Empty
| otherwise = Leaf i xs
step :: Int -> JoinString -> (Int,String)
step _ Empty = (0,"")
step n (Leaf i xs) | n >= i = (i,xs)
| otherwise = (n,Pre.take n xs)
step n (Tree _ t u) = let (i,ls) = step n t in
if i<n then let (j,rs) = step (ni) u in
(i+j,ls Pre.++ rs)
else (i,ls)
takeRight :: Int -> JoinString -> JoinString
takeRight = build `oo` step where
build (i,xs) | i <= 0 = Empty
| otherwise = Leaf i xs
step :: Int -> JoinString -> (Int,String)
step _ Empty = (0,"")
step n (Leaf i xs) | n >= i = (i,xs)
| otherwise = (n,ltr n xs)
step n (Tree _ t u) = let (i,rs) = step n u in
if i<n then let (j,ls) = step (ni) t in
(i+j,ls Pre.++ rs)
else (i,rs)
ltr :: Int -> [a] -> [a]
ltr n = ($ []) . snd . Pre.foldr fn (0,id) where
fn e (i,f) | i < n = (i+1, (e:) . f)
| otherwise = (i,f)
dropLeft :: Int -> JoinString -> JoinString
dropLeft = snd `oo` step where
step n Empty = (n,Empty)
step n (Leaf a xs) | n >= a = (na,Empty)
| otherwise = (0,Leaf (an) (drop n xs))
step n (Tree a t u) | n >= a = (na,Empty)
| otherwise = let (n',t') = step n t in
if n' > 0 then step n' u
else (0,mkTree (an) t' u)
mkTree _ Empty u = u
mkTree n t u = Tree n t u
dropRight :: Int -> JoinString -> JoinString
dropRight = snd `oo` step where
step n Empty = (n,Empty)
step n (Leaf a xs) | n >= a = (na,Empty)
| otherwise = (0,Leaf (an) (take (an) xs))
step n (Tree a t u) | n >= a = (na,Empty)
| otherwise = let (n',u') = step n u in
if n' > 0 then step n' t
else (0, mkTree (an) t u')
mkTree _ t Empty = t
mkTree n t u = Tree n t u
oo :: (c -> d) -> (a -> b -> c) -> a -> b -> d
oo f g r s = f (g r s)