module Data.Loc.SpanOrLoc
  (
    SpanOrLoc,

    -- * Constructing
    span, loc, fromTo,

    -- * Deconstructing
    spanOrLoc,

    -- * Querying
    start, end,
  )
  where

import Data.Loc.Internal.Prelude

import Data.Loc.Loc (Loc)
import Data.Loc.Span (Span)

import qualified Data.Loc.Loc as Loc
import qualified Data.Loc.Span as Span

import Data.Data (Data)

{- |

A 'SpanOrLoc' consists of a start location and an end location.
The end location must be greater than or equal to the start location;
in other words, backwards spans are not permitted.

If the start and end location are the same, then the value is a 'Loc'.
If they differ, then the value is a 'Span'.

-}
data SpanOrLoc = Span Span | Loc Loc
  deriving (Typeable SpanOrLoc
SpanOrLoc -> DataType
SpanOrLoc -> Constr
(forall b. Data b => b -> b) -> SpanOrLoc -> SpanOrLoc
forall a.
Typeable a
-> (forall (c :: * -> *).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> a -> c a)
-> (forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c a)
-> (a -> Constr)
-> (a -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c a))
-> (forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c a))
-> ((forall b. Data b => b -> b) -> a -> a)
-> (forall r r'.
    (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall r r'.
    (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall u. (forall d. Data d => d -> u) -> a -> [u])
-> (forall u. Int -> (forall d. Data d => d -> u) -> a -> u)
-> (forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> Data a
forall u. Int -> (forall d. Data d => d -> u) -> SpanOrLoc -> u
forall u. (forall d. Data d => d -> u) -> SpanOrLoc -> [u]
forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> SpanOrLoc -> r
forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> SpanOrLoc -> r
forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> SpanOrLoc -> m SpanOrLoc
forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> SpanOrLoc -> m SpanOrLoc
forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c SpanOrLoc
forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> SpanOrLoc -> c SpanOrLoc
forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c SpanOrLoc)
forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c SpanOrLoc)
gmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> SpanOrLoc -> m SpanOrLoc
$cgmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> SpanOrLoc -> m SpanOrLoc
gmapMp :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> SpanOrLoc -> m SpanOrLoc
$cgmapMp :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> SpanOrLoc -> m SpanOrLoc
gmapM :: forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> SpanOrLoc -> m SpanOrLoc
$cgmapM :: forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> SpanOrLoc -> m SpanOrLoc
gmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> SpanOrLoc -> u
$cgmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> SpanOrLoc -> u
gmapQ :: forall u. (forall d. Data d => d -> u) -> SpanOrLoc -> [u]
$cgmapQ :: forall u. (forall d. Data d => d -> u) -> SpanOrLoc -> [u]
gmapQr :: forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> SpanOrLoc -> r
$cgmapQr :: forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> SpanOrLoc -> r
gmapQl :: forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> SpanOrLoc -> r
$cgmapQl :: forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> SpanOrLoc -> r
gmapT :: (forall b. Data b => b -> b) -> SpanOrLoc -> SpanOrLoc
$cgmapT :: (forall b. Data b => b -> b) -> SpanOrLoc -> SpanOrLoc
dataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c SpanOrLoc)
$cdataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c SpanOrLoc)
dataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c SpanOrLoc)
$cdataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c SpanOrLoc)
dataTypeOf :: SpanOrLoc -> DataType
$cdataTypeOf :: SpanOrLoc -> DataType
toConstr :: SpanOrLoc -> Constr
$ctoConstr :: SpanOrLoc -> Constr
gunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c SpanOrLoc
$cgunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c SpanOrLoc
gfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> SpanOrLoc -> c SpanOrLoc
$cgfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> SpanOrLoc -> c SpanOrLoc
Data, SpanOrLoc -> SpanOrLoc -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: SpanOrLoc -> SpanOrLoc -> Bool
$c/= :: SpanOrLoc -> SpanOrLoc -> Bool
== :: SpanOrLoc -> SpanOrLoc -> Bool
$c== :: SpanOrLoc -> SpanOrLoc -> Bool
Eq, Eq SpanOrLoc
SpanOrLoc -> SpanOrLoc -> Bool
SpanOrLoc -> SpanOrLoc -> Ordering
SpanOrLoc -> SpanOrLoc -> SpanOrLoc
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 :: SpanOrLoc -> SpanOrLoc -> SpanOrLoc
$cmin :: SpanOrLoc -> SpanOrLoc -> SpanOrLoc
max :: SpanOrLoc -> SpanOrLoc -> SpanOrLoc
$cmax :: SpanOrLoc -> SpanOrLoc -> SpanOrLoc
>= :: SpanOrLoc -> SpanOrLoc -> Bool
$c>= :: SpanOrLoc -> SpanOrLoc -> Bool
> :: SpanOrLoc -> SpanOrLoc -> Bool
$c> :: SpanOrLoc -> SpanOrLoc -> Bool
<= :: SpanOrLoc -> SpanOrLoc -> Bool
$c<= :: SpanOrLoc -> SpanOrLoc -> Bool
< :: SpanOrLoc -> SpanOrLoc -> Bool
$c< :: SpanOrLoc -> SpanOrLoc -> Bool
compare :: SpanOrLoc -> SpanOrLoc -> Ordering
$ccompare :: SpanOrLoc -> SpanOrLoc -> Ordering
Ord)

instance Show SpanOrLoc
  where
    showsPrec :: Int -> SpanOrLoc -> ShowS
showsPrec Int
i = \case
        Span Span
x -> Int -> Span -> ShowS
Span.spanShowsPrec Int
i Span
x
        Loc Loc
x -> Int -> Loc -> ShowS
Loc.locShowsPrec Int
i Loc
x

span :: Span -> SpanOrLoc
span :: Span -> SpanOrLoc
span = Span -> SpanOrLoc
Span

loc :: Loc -> SpanOrLoc
loc :: Loc -> SpanOrLoc
loc = Loc -> SpanOrLoc
Loc

spanOrLoc :: (Span -> a) -> (Loc -> a) -> SpanOrLoc -> a
spanOrLoc :: forall a. (Span -> a) -> (Loc -> a) -> SpanOrLoc -> a
spanOrLoc Span -> a
f Loc -> a
_ (Span Span
x) = Span -> a
f Span
x
spanOrLoc Span -> a
_ Loc -> a
f (Loc Loc
x) = Loc -> a
f Loc
x

{- |

Construct a 'SpanOrLoc' from two 'Loc's. If the two locs are not equal,
the lesser loc will be the start, and the greater loc will be the end.

-}
fromTo :: Loc -> Loc -> SpanOrLoc
fromTo :: Loc -> Loc -> SpanOrLoc
fromTo Loc
a Loc
b =
  forall b a. b -> (a -> b) -> Maybe a -> b
maybe (Loc -> SpanOrLoc
Loc Loc
a) Span -> SpanOrLoc
Span (Loc -> Loc -> Maybe Span
Span.fromToMay Loc
a Loc
b)

start :: SpanOrLoc -> Loc
start :: SpanOrLoc -> Loc
start = forall a. (Span -> a) -> (Loc -> a) -> SpanOrLoc -> a
spanOrLoc Span -> Loc
Span.start forall a. a -> a
id

end :: SpanOrLoc -> Loc
end :: SpanOrLoc -> Loc
end = forall a. (Span -> a) -> (Loc -> a) -> SpanOrLoc -> a
spanOrLoc Span -> Loc
Span.end forall a. a -> a
id