module Data.Loc.Span
( Span,
fromTo,
fromToMay,
start,
end,
lines,
overlapping,
linesOverlapping,
touching,
join,
joinAsc,
(+),
(-),
spanShowsPrec,
spanReadPrec,
)
where
import Data.Foldable qualified as Foldable
import Data.List.NonEmpty qualified as NonEmpty
import Data.Loc.Exception (LocException (..))
import Data.Loc.Internal.Prelude
import Data.Loc.List.OneToTwo (OneToTwo)
import Data.Loc.List.OneToTwo qualified as OneToTwo
import Data.Loc.List.ZeroToTwo (ZeroToTwo)
import Data.Loc.List.ZeroToTwo qualified as ZeroToTwo
import Data.Loc.Loc (Loc, locReadPrec, locShowsPrec)
import Data.Loc.Loc qualified as Loc
import Data.Loc.Pos (Line)
data Span = Span
{ Span -> Loc
start :: Loc,
Span -> Loc
end :: Loc
}
deriving (Span -> Span -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Span -> Span -> Bool
$c/= :: Span -> Span -> Bool
== :: Span -> Span -> Bool
$c== :: Span -> Span -> Bool
Eq, Eq Span
Span -> Span -> Bool
Span -> Span -> Ordering
Span -> Span -> Span
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 :: Span -> Span -> Span
$cmin :: Span -> Span -> Span
max :: Span -> Span -> Span
$cmax :: Span -> Span -> Span
>= :: Span -> Span -> Bool
$c>= :: Span -> Span -> Bool
> :: Span -> Span -> Bool
$c> :: Span -> Span -> Bool
<= :: Span -> Span -> Bool
$c<= :: Span -> Span -> Bool
< :: Span -> Span -> Bool
$c< :: Span -> Span -> Bool
compare :: Span -> Span -> Ordering
$ccompare :: Span -> Span -> Ordering
Ord)
instance Show Span where
showsPrec :: Int -> Span -> ShowS
showsPrec = Int -> Span -> ShowS
spanShowsPrec
instance Read Span where
readPrec :: ReadPrec Span
readPrec = ReadPrec Span
spanReadPrec
spanShowsPrec :: Int -> Span -> ShowS
spanShowsPrec :: Int -> Span -> ShowS
spanShowsPrec Int
_ (Span Loc
a Loc
b) =
Int -> Loc -> ShowS
locShowsPrec Int
10 Loc
a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString String
"-"
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Loc -> ShowS
locShowsPrec Int
10 Loc
b
spanReadPrec :: ReadPrec Span
spanReadPrec :: ReadPrec Span
spanReadPrec =
ReadPrec Loc
locReadPrec forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \Loc
a ->
Char -> ReadPrec ()
readPrecChar Char
'-'
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> ReadPrec Loc
locReadPrec
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \Loc
b ->
forall b a. b -> (a -> b) -> Maybe a -> b
maybe forall (f :: * -> *) a. Alternative f => f a
empty forall (f :: * -> *) a. Applicative f => a -> f a
pure (Loc -> Loc -> Maybe Span
fromToMay Loc
a Loc
b)
fromTo :: Loc -> Loc -> Span
fromTo :: Loc -> Loc -> Span
fromTo Loc
a Loc
b =
forall a. a -> Maybe a -> a
fromMaybe (forall a e. Exception e => e -> a
throw LocException
EmptySpan) (Loc -> Loc -> Maybe Span
fromToMay Loc
a Loc
b)
fromToMay :: Loc -> Loc -> Maybe Span
fromToMay :: Loc -> Loc -> Maybe Span
fromToMay Loc
a Loc
b =
case forall a. Ord a => a -> a -> Ordering
compare Loc
a Loc
b of
Ordering
LT -> forall a. a -> Maybe a
Just (Loc -> Loc -> Span
Span Loc
a Loc
b)
Ordering
GT -> forall a. a -> Maybe a
Just (Loc -> Loc -> Span
Span Loc
b Loc
a)
Ordering
EQ -> forall a. Maybe a
Nothing
lines :: Span -> NonEmpty Line
lines :: Span -> NonEmpty Line
lines Span
s =
forall a. [a] -> NonEmpty a
NonEmpty.fromList [Loc -> Line
Loc.line (Span -> Loc
start Span
s) .. Loc -> Line
Loc.line (Span -> Loc
end Span
s)]
overlapping :: Span -> Span -> Bool
overlapping :: Span -> Span -> Bool
overlapping Span
a Span
b =
Bool -> Bool
not (Span -> Loc
end Span
a forall a. Ord a => a -> a -> Bool
<= Span -> Loc
start Span
b Bool -> Bool -> Bool
|| Span -> Loc
end Span
b forall a. Ord a => a -> a -> Bool
<= Span -> Loc
start Span
a)
linesOverlapping :: Span -> Span -> Bool
linesOverlapping :: Span -> Span -> Bool
linesOverlapping Span
a Span
b =
Bool -> Bool
not forall a b. (a -> b) -> a -> b
$
(Loc -> Line
Loc.line forall b c a. (b -> c) -> (a -> b) -> a -> c
. Span -> Loc
end) Span
a forall a. Ord a => a -> a -> Bool
< (Loc -> Line
Loc.line forall b c a. (b -> c) -> (a -> b) -> a -> c
. Span -> Loc
start) Span
b
Bool -> Bool -> Bool
|| (Loc -> Line
Loc.line forall b c a. (b -> c) -> (a -> b) -> a -> c
. Span -> Loc
end) Span
b forall a. Ord a => a -> a -> Bool
< (Loc -> Line
Loc.line forall b c a. (b -> c) -> (a -> b) -> a -> c
. Span -> Loc
start) Span
a
touching :: Span -> Span -> Bool
touching :: Span -> Span -> Bool
touching Span
a Span
b =
Bool -> Bool
not (Span -> Loc
end Span
a forall a. Ord a => a -> a -> Bool
< Span -> Loc
start Span
b Bool -> Bool -> Bool
|| Span -> Loc
end Span
b forall a. Ord a => a -> a -> Bool
< Span -> Loc
start Span
a)
join :: Span -> Span -> Span
join :: Span -> Span -> Span
join Span
a Span
b =
Loc -> Loc -> Span
Span
(forall a. Ord a => a -> a -> a
min (Span -> Loc
start Span
a) (Span -> Loc
start Span
b))
(forall a. Ord a => a -> a -> a
max (Span -> Loc
end Span
a) (Span -> Loc
end Span
b))
(+) :: Span -> Span -> OneToTwo Span
Span
a + :: Span -> Span -> OneToTwo Span
+ Span
b
| Span -> Span -> Bool
touching Span
a Span
b = forall a. a -> OneToTwo a
OneToTwo.One (Span -> Span -> Span
join Span
a Span
b)
| Bool
otherwise = forall a. a -> a -> OneToTwo a
OneToTwo.Two Span
a Span
b
(-) :: Span -> Span -> ZeroToTwo Span
Span
a - :: Span -> Span -> ZeroToTwo Span
- Span
b
| Bool -> Bool
not (Span -> Span -> Bool
overlapping Span
a Span
b) =
forall a. a -> ZeroToTwo a
ZeroToTwo.One Span
a
| Span -> Loc
start Span
b forall a. Ord a => a -> a -> Bool
> Span -> Loc
start Span
a Bool -> Bool -> Bool
&& Span -> Loc
end Span
b forall a. Ord a => a -> a -> Bool
< Span -> Loc
end Span
a =
forall a. a -> a -> ZeroToTwo a
ZeroToTwo.Two
(Loc -> Loc -> Span
Span (Span -> Loc
start Span
a) (Span -> Loc
start Span
b))
(Loc -> Loc -> Span
Span (Span -> Loc
end Span
b) (Span -> Loc
end Span
a))
| Span -> Loc
start Span
b forall a. Ord a => a -> a -> Bool
<= Span -> Loc
start Span
a Bool -> Bool -> Bool
&& Span -> Loc
end Span
b forall a. Ord a => a -> a -> Bool
< Span -> Loc
end Span
a =
forall a. a -> ZeroToTwo a
ZeroToTwo.One (Loc -> Loc -> Span
Span (Span -> Loc
end Span
b) (Span -> Loc
end Span
a))
| Span -> Loc
start Span
b forall a. Ord a => a -> a -> Bool
> Span -> Loc
start Span
a Bool -> Bool -> Bool
&& Span -> Loc
end Span
b forall a. Ord a => a -> a -> Bool
>= Span -> Loc
end Span
a =
forall a. a -> ZeroToTwo a
ZeroToTwo.One (Loc -> Loc -> Span
Span (Span -> Loc
start Span
a) (Span -> Loc
start Span
b))
| Bool
otherwise =
forall a. ZeroToTwo a
ZeroToTwo.Zero
joinAsc ::
[Span] ->
[Span]
joinAsc :: [Span] -> [Span]
joinAsc =
\case
Span
x : Span
y : [Span]
zs ->
let (Maybe Span
r, Span
s) = forall a. OneToTwo a -> (Maybe a, a)
OneToTwo.toTuple' (Span
x Span -> Span -> OneToTwo Span
+ Span
y)
in forall (t :: * -> *) a. Foldable t => t a -> [a]
Foldable.toList Maybe Span
r forall a. Semigroup a => a -> a -> a
<> [Span] -> [Span]
joinAsc (Span
s forall a. a -> [a] -> [a]
: [Span]
zs)
[Span]
xs -> [Span]
xs