{-# 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))