{-# LANGUAGE Safe #-}
 {-# LANGUAGE DeriveDataTypeable #-}
 module Math.Tools.LineInfo where
 import Data.Monoid
 import Data.Typeable
 import Data.Binary
 import qualified Text.PrettyPrint as Pretty
 import qualified Math.Tools.PrettyP as PrettyP
 import Math.Tools.PrettyP
 import Math.Tools.Isomorphism

 data LineInfo = LineInfo { LineInfo -> String
liFile :: !String,
 			    LineInfo -> Int
liRow  :: {-# UNPACK #-} !Int,
 			    LineInfo -> Int
liColumn :: {-# UNPACK #-} !Int }
               | NoLineInfo
    deriving (LineInfo -> LineInfo -> Bool
(LineInfo -> LineInfo -> Bool)
-> (LineInfo -> LineInfo -> Bool) -> Eq LineInfo
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: LineInfo -> LineInfo -> Bool
== :: LineInfo -> LineInfo -> Bool
$c/= :: LineInfo -> LineInfo -> Bool
/= :: LineInfo -> LineInfo -> Bool
Eq,Eq LineInfo
Eq LineInfo =>
(LineInfo -> LineInfo -> Ordering)
-> (LineInfo -> LineInfo -> Bool)
-> (LineInfo -> LineInfo -> Bool)
-> (LineInfo -> LineInfo -> Bool)
-> (LineInfo -> LineInfo -> Bool)
-> (LineInfo -> LineInfo -> LineInfo)
-> (LineInfo -> LineInfo -> LineInfo)
-> Ord LineInfo
LineInfo -> LineInfo -> Bool
LineInfo -> LineInfo -> Ordering
LineInfo -> LineInfo -> LineInfo
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: LineInfo -> LineInfo -> Ordering
compare :: LineInfo -> LineInfo -> Ordering
$c< :: LineInfo -> LineInfo -> Bool
< :: LineInfo -> LineInfo -> Bool
$c<= :: LineInfo -> LineInfo -> Bool
<= :: LineInfo -> LineInfo -> Bool
$c> :: LineInfo -> LineInfo -> Bool
> :: LineInfo -> LineInfo -> Bool
$c>= :: LineInfo -> LineInfo -> Bool
>= :: LineInfo -> LineInfo -> Bool
$cmax :: LineInfo -> LineInfo -> LineInfo
max :: LineInfo -> LineInfo -> LineInfo
$cmin :: LineInfo -> LineInfo -> LineInfo
min :: LineInfo -> LineInfo -> LineInfo
Ord,Typeable)

 instance Binary LineInfo where
    put :: LineInfo -> Put
put (LineInfo String
f Int
r Int
c) = String -> Put
forall t. Binary t => t -> Put
put String
f Put -> Put -> Put
forall a b. PutM a -> PutM b -> PutM b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Int -> Put
forall t. Binary t => t -> Put
put Int
r Put -> Put -> Put
forall a b. PutM a -> PutM b -> PutM b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Int -> Put
forall t. Binary t => t -> Put
put Int
c
    get :: Get LineInfo
get = do { String
f <- Get String
forall t. Binary t => Get t
get ; Int
r <- Get Int
forall t. Binary t => Get t
get ; Int
c <- Get Int
forall t. Binary t => Get t
get ; LineInfo -> Get LineInfo
forall a. a -> Get a
forall (m :: * -> *) a. Monad m => a -> m a
return (String -> Int -> Int -> LineInfo
LineInfo String
f Int
r Int
c) }

 lineinfoIso :: Iso LineInfo (Either (String,Int,Int) ())
 lineinfoIso :: Iso LineInfo (Either (String, Int, Int) ())
lineinfoIso = (LineInfo -> Either (String, Int, Int) ())
-> (Either (String, Int, Int) () -> LineInfo)
-> Iso LineInfo (Either (String, Int, Int) ())
forall a b. (a -> b) -> (b -> a) -> a :==: b
Iso LineInfo -> Either (String, Int, Int) ()
openli Either (String, Int, Int) () -> LineInfo
closeli
    where openli :: LineInfo -> Either (String, Int, Int) ()
openli (LineInfo String
f Int
r Int
c) = (String, Int, Int) -> Either (String, Int, Int) ()
forall a b. a -> Either a b
Left (String
f,Int
r,Int
c)
          openli LineInfo
NoLineInfo = () -> Either (String, Int, Int) ()
forall a b. b -> Either a b
Right ()          
          closeli :: Either (String, Int, Int) () -> LineInfo
closeli (Left (String
f,Int
r,Int
c)) = String -> Int -> Int -> LineInfo
LineInfo String
f Int
r Int
c
          closeli (Right ()) = LineInfo
NoLineInfo

 class Located e where
    locationOf :: e -> LineInfo

 instance Located LineInfo where
    locationOf :: LineInfo -> LineInfo
locationOf = LineInfo -> LineInfo
forall a. a -> a
id

 instance Semigroup LineInfo where
    <> :: LineInfo -> LineInfo -> LineInfo
(<>) = LineInfo -> LineInfo -> LineInfo
sumLineinfo

 instance Monoid LineInfo where
    mempty :: LineInfo
mempty = LineInfo
emptyLineInfo
    mappend :: LineInfo -> LineInfo -> LineInfo
mappend = LineInfo -> LineInfo -> LineInfo
sumLineinfo

 instance Show LineInfo where
    show :: LineInfo -> String
show LineInfo
NoLineInfo = String
""
    show (LineInfo String
f Int
r Int
c) = ShowS
forall a. Show a => a -> String
show String
f String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
":" String -> ShowS
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show Int
r String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
":" String -> ShowS
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show Int
c

 instance PpShow LineInfo where
          pp :: LineInfo -> Doc
pp LineInfo
NoLineInfo = Doc
Pretty.empty
 	  pp (LineInfo String
f Int
r Int
c) = [Doc] -> Doc
Pretty.fcat [String -> Doc
forall a. PpShow a => a -> Doc
pp String
f,Char -> Doc
forall a. PpShow a => a -> Doc
pp Char
':', Int -> Doc
forall a. PpShow a => a -> Doc
pp Int
r, Char -> Doc
forall a. PpShow a => a -> Doc
pp Char
':', Int -> Doc
forall a. PpShow a => a -> Doc
pp Int
c]

 emptyLineInfo :: LineInfo
 emptyLineInfo :: LineInfo
emptyLineInfo = LineInfo
NoLineInfo

 sumLineinfo :: LineInfo -> LineInfo -> LineInfo
 sumLineinfo :: LineInfo -> LineInfo -> LineInfo
sumLineinfo LineInfo
NoLineInfo LineInfo
x = LineInfo
x
 sumLineinfo LineInfo
x LineInfo
_ = LineInfo
x

 newFile :: String -> LineInfo -> LineInfo
 newFile :: String -> LineInfo -> LineInfo
newFile String
f LineInfo
NoLineInfo = LineInfo { liFile :: String
liFile = String
f, liRow :: Int
liRow = Int
1, liColumn :: Int
liColumn = Int
0 }
 newFile String
f LineInfo
li = LineInfo
li { liFile = f, liRow = 1, liColumn = 0 }

 nextLine :: LineInfo -> LineInfo
 nextLine :: LineInfo -> LineInfo
nextLine li :: LineInfo
li@(LineInfo {}) = LineInfo
li { liRow = liRow li + 1, liColumn = 0 }
 nextLine LineInfo
NoLineInfo = LineInfo
NoLineInfo

 prevLine :: LineInfo -> LineInfo
 prevLine :: LineInfo -> LineInfo
prevLine li :: LineInfo
li@(LineInfo {}) = LineInfo
li { liRow = liRow li - 1, liColumn = 0 }
 prevLine LineInfo
NoLineInfo = LineInfo
NoLineInfo

 nextlineIso :: Iso LineInfo (LineInfo,Int)
 nextlineIso :: Iso LineInfo (LineInfo, Int)
nextlineIso = (LineInfo -> (LineInfo, Int))
-> ((LineInfo, Int) -> LineInfo) -> Iso LineInfo (LineInfo, Int)
forall a b. (a -> b) -> (b -> a) -> a :==: b
Iso (\LineInfo
li -> (LineInfo -> LineInfo
nextLine LineInfo
li, LineInfo -> Int
liColumn LineInfo
li))
                   (\ (LineInfo
li,Int
c) -> LineInfo
li { liRow = liRow li - 1, liColumn = c })

 addToLine :: Int -> LineInfo -> LineInfo
 addToLine :: Int -> LineInfo -> LineInfo
addToLine Int
i li :: LineInfo
li@(LineInfo{}) = LineInfo
li { liRow = liRow li + i, liColumn = 0 }
 addToLine Int
i LineInfo
NoLineInfo = LineInfo
NoLineInfo

 nextColumn :: LineInfo -> LineInfo
 nextColumn :: LineInfo -> LineInfo
nextColumn li :: LineInfo
li@(LineInfo {}) = LineInfo
li { liColumn = liColumn li + 1 }
 nextColumn LineInfo
NoLineInfo = LineInfo
NoLineInfo

 prevColumn :: LineInfo -> LineInfo
 prevColumn :: LineInfo -> LineInfo
prevColumn li :: LineInfo
li@(LineInfo {}) = LineInfo
li { liColumn = liColumn li - 1 }
 prevColumn LineInfo
NoLineInfo = LineInfo
NoLineInfo

 nextColumnIso :: Iso LineInfo LineInfo
 nextColumnIso :: Iso LineInfo LineInfo
nextColumnIso = (LineInfo -> LineInfo)
-> (LineInfo -> LineInfo) -> Iso LineInfo LineInfo
forall a b. (a -> b) -> (b -> a) -> a :==: b
Iso LineInfo -> LineInfo
nextColumn LineInfo -> LineInfo
prevColumn

 addToColumn :: Int -> LineInfo -> LineInfo
 addToColumn :: Int -> LineInfo -> LineInfo
addToColumn Int
x li :: LineInfo
li@(LineInfo {}) = LineInfo
li { liColumn = liColumn li + x }
 addToColumn Int
x LineInfo
NoLineInfo = LineInfo
NoLineInfo

 addToColumnIso :: Int -> Iso LineInfo LineInfo
 addToColumnIso :: Int -> Iso LineInfo LineInfo
addToColumnIso Int
i = (LineInfo -> LineInfo)
-> (LineInfo -> LineInfo) -> Iso LineInfo LineInfo
forall a b. (a -> b) -> (b -> a) -> a :==: b
Iso (Int -> LineInfo -> LineInfo
addToColumn Int
i) (Int -> LineInfo -> LineInfo
addToColumn (Int -> Int
forall a. Num a => a -> a
negate Int
i))