{-# LANGUAGE OverloadedStrings #-}
module Oughta.Pos
( Pos(..)
, incPos
, Loc(..)
, printLoc
, Span(..)
, startLoc
, endLoc
, printSpan
) where
import Data.List qualified as List
import Data.Maybe qualified as Maybe
import Data.Text qualified as Text
import Data.Text (Text)
import Prelude hiding (last, lines, span)
tshow :: Show a => a -> Text
tshow :: forall a. Show a => a -> Text
tshow = String -> Text
Text.pack (String -> Text) -> (a -> String) -> a -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> String
forall a. Show a => a -> String
show
data Pos
= Pos
{ Pos -> Int
line :: {-# UNPACK #-} !Int
, Pos -> Int
col :: {-# UNPACK #-} !Int
}
incPos :: Pos -> Text -> Pos
incPos :: Pos -> Text -> Pos
incPos (Pos Int
l Int
c) Text
t =
let newlines :: Int
newlines = HasCallStack => Text -> Text -> Int
Text -> Text -> Int
Text.count Text
"\n" Text
t in
Int -> Int -> Pos
Pos (Int
l Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
newlines) (Int -> Pos) -> Int -> Pos
forall a b. (a -> b) -> a -> b
$
if Text
"\n" Text -> Text -> Bool
`Text.isSuffixOf` Text
t
then Int
1
else
case [Text] -> [Text]
forall a. [a] -> [a]
List.reverse (Text -> [Text]
Text.lines Text
t) of
[] -> Int
c
(Text
only : []) -> Int
c Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Text -> Int
Text.length Text
only
(Text
last : [Text]
_) -> Text -> Int
Text.length Text
last
printPos :: Pos -> Text
printPos :: Pos -> Text
printPos Pos
p = Int -> Text
forall a. Show a => a -> Text
tshow (Pos -> Int
line Pos
p) Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
":" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Int -> Text
forall a. Show a => a -> Text
tshow (Pos -> Int
col Pos
p)
data Loc
= Loc
{ Loc -> Maybe String
path :: !(Maybe FilePath)
, Loc -> Pos
pos :: {-# UNPACK #-} !Pos
}
printLoc :: Loc -> Text
printLoc :: Loc -> Text
printLoc Loc
l =
let p :: String
p = String -> Maybe String -> String
forall a. a -> Maybe a -> a
Maybe.fromMaybe String
"<unknown file>" (Loc -> Maybe String
path Loc
l) in
String -> Text
Text.pack String
p Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
":" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Pos -> Text
printPos (Loc -> Pos
pos Loc
l)
data Span
= Span
{ Span -> Maybe String
spanPath :: !(Maybe FilePath)
, Span -> Pos
spanStart :: {-# UNPACK #-} !Pos
, Span -> Pos
spanEnd :: {-# UNPACK #-} !Pos
}
startLoc :: Span -> Loc
startLoc :: Span -> Loc
startLoc Span
s = Maybe String -> Pos -> Loc
Loc (Span -> Maybe String
spanPath Span
s) (Span -> Pos
spanStart Span
s)
endLoc :: Span -> Loc
endLoc :: Span -> Loc
endLoc Span
s = Maybe String -> Pos -> Loc
Loc (Span -> Maybe String
spanPath Span
s) (Span -> Pos
spanEnd Span
s)
printSpan :: Span -> Text
printSpan :: Span -> Text
printSpan Span
s =
let p :: String
p = String -> Maybe String -> String
forall a. a -> Maybe a -> a
Maybe.fromMaybe String
"<unknown file>" (Span -> Maybe String
spanPath Span
s) in
String -> Text
Text.pack String
p Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
":" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Pos -> Text
printPos (Span -> Pos
spanStart Span
s) Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"-" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Pos -> Text
printPos (Span -> Pos
spanEnd Span
s)