module Data.Rope.UTF16.Internal.Position where

import Data.Semigroup

data RowColumn = RowColumn
  { RowColumn -> Int
row :: !Int -- ^ Number of newlines before this position
  , RowColumn -> Int
column :: !Int -- ^ Number of UTF-16 code units since last newline or start of string
  } deriving (RowColumn -> RowColumn -> Bool
(RowColumn -> RowColumn -> Bool)
-> (RowColumn -> RowColumn -> Bool) -> Eq RowColumn
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: RowColumn -> RowColumn -> Bool
$c/= :: RowColumn -> RowColumn -> Bool
== :: RowColumn -> RowColumn -> Bool
$c== :: RowColumn -> RowColumn -> Bool
Eq, Eq RowColumn
Eq RowColumn
-> (RowColumn -> RowColumn -> Ordering)
-> (RowColumn -> RowColumn -> Bool)
-> (RowColumn -> RowColumn -> Bool)
-> (RowColumn -> RowColumn -> Bool)
-> (RowColumn -> RowColumn -> Bool)
-> (RowColumn -> RowColumn -> RowColumn)
-> (RowColumn -> RowColumn -> RowColumn)
-> Ord RowColumn
RowColumn -> RowColumn -> Bool
RowColumn -> RowColumn -> Ordering
RowColumn -> RowColumn -> RowColumn
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
min :: RowColumn -> RowColumn -> RowColumn
$cmin :: RowColumn -> RowColumn -> RowColumn
max :: RowColumn -> RowColumn -> RowColumn
$cmax :: RowColumn -> RowColumn -> RowColumn
>= :: RowColumn -> RowColumn -> Bool
$c>= :: RowColumn -> RowColumn -> Bool
> :: RowColumn -> RowColumn -> Bool
$c> :: RowColumn -> RowColumn -> Bool
<= :: RowColumn -> RowColumn -> Bool
$c<= :: RowColumn -> RowColumn -> Bool
< :: RowColumn -> RowColumn -> Bool
$c< :: RowColumn -> RowColumn -> Bool
compare :: RowColumn -> RowColumn -> Ordering
$ccompare :: RowColumn -> RowColumn -> Ordering
$cp1Ord :: Eq RowColumn
Ord, Int -> RowColumn -> ShowS
[RowColumn] -> ShowS
RowColumn -> String
(Int -> RowColumn -> ShowS)
-> (RowColumn -> String)
-> ([RowColumn] -> ShowS)
-> Show RowColumn
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [RowColumn] -> ShowS
$cshowList :: [RowColumn] -> ShowS
show :: RowColumn -> String
$cshow :: RowColumn -> String
showsPrec :: Int -> RowColumn -> ShowS
$cshowsPrec :: Int -> RowColumn -> ShowS
Show)

instance Semigroup RowColumn where
  RowColumn Int
0 Int
c1 <> :: RowColumn -> RowColumn -> RowColumn
<> RowColumn Int
0 Int
c2 = Int -> Int -> RowColumn
RowColumn Int
0 (Int -> RowColumn) -> Int -> RowColumn
forall a b. (a -> b) -> a -> b
$ Int
c1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
c2
  RowColumn Int
0 Int
_ <> RowColumn
v2 = RowColumn
v2
  RowColumn Int
r1 Int
c1 <> RowColumn Int
0 Int
c2 = Int -> Int -> RowColumn
RowColumn Int
r1 (Int -> RowColumn) -> Int -> RowColumn
forall a b. (a -> b) -> a -> b
$ Int
c1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
c2
  RowColumn Int
r1 Int
_ <> RowColumn Int
r2 Int
c2 = Int -> Int -> RowColumn
RowColumn (Int
r1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
r2) Int
c2

instance Monoid RowColumn where
  mempty :: RowColumn
mempty = Int -> Int -> RowColumn
RowColumn Int
0 Int
0
  mappend :: RowColumn -> RowColumn -> RowColumn
mappend = RowColumn -> RowColumn -> RowColumn
forall a. Semigroup a => a -> a -> a
(<>)

data Position = Position
  { Position -> Int
codeUnits :: !Int -- ^ UTF-16 code units
  , Position -> RowColumn
rowColumn :: !RowColumn
  } deriving (Position -> Position -> Bool
(Position -> Position -> Bool)
-> (Position -> Position -> Bool) -> Eq Position
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Position -> Position -> Bool
$c/= :: Position -> Position -> Bool
== :: Position -> Position -> Bool
$c== :: Position -> Position -> Bool
Eq, Eq Position
Eq Position
-> (Position -> Position -> Ordering)
-> (Position -> Position -> Bool)
-> (Position -> Position -> Bool)
-> (Position -> Position -> Bool)
-> (Position -> Position -> Bool)
-> (Position -> Position -> Position)
-> (Position -> Position -> Position)
-> Ord Position
Position -> Position -> Bool
Position -> Position -> Ordering
Position -> Position -> Position
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
min :: Position -> Position -> Position
$cmin :: Position -> Position -> Position
max :: Position -> Position -> Position
$cmax :: Position -> Position -> Position
>= :: Position -> Position -> Bool
$c>= :: Position -> Position -> Bool
> :: Position -> Position -> Bool
$c> :: Position -> Position -> Bool
<= :: Position -> Position -> Bool
$c<= :: Position -> Position -> Bool
< :: Position -> Position -> Bool
$c< :: Position -> Position -> Bool
compare :: Position -> Position -> Ordering
$ccompare :: Position -> Position -> Ordering
$cp1Ord :: Eq Position
Ord, Int -> Position -> ShowS
[Position] -> ShowS
Position -> String
(Int -> Position -> ShowS)
-> (Position -> String) -> ([Position] -> ShowS) -> Show Position
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Position] -> ShowS
$cshowList :: [Position] -> ShowS
show :: Position -> String
$cshow :: Position -> String
showsPrec :: Int -> Position -> ShowS
$cshowsPrec :: Int -> Position -> ShowS
Show)

instance Semigroup Position where
  Position Int
cu RowColumn
rc <> :: Position -> Position -> Position
<> Position Int
cu' RowColumn
rc'
    = Int -> RowColumn -> Position
Position (Int
cu Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
cu') (RowColumn
rc RowColumn -> RowColumn -> RowColumn
forall a. Semigroup a => a -> a -> a
<> RowColumn
rc')

instance Monoid Position where
  mempty :: Position
mempty = Int -> RowColumn -> Position
Position Int
0 RowColumn
forall a. Monoid a => a
mempty
  mappend :: Position -> Position -> Position
mappend = Position -> Position -> Position
forall a. Semigroup a => a -> a -> a
(<>)