module Agda.Position
( ToOffset(..)
, makeToOffset
, toOffset
, FromOffset(..)
, makeFromOffset
, fromOffset
, toAgdaPositionWithoutFile
, toAgdaRange
, prettyPositionWithoutFile
) where
import Agda.Syntax.Position
import Agda.Utils.FileName ( AbsolutePath(AbsolutePath) )
import Data.IntMap ( IntMap )
import qualified Data.IntMap as IntMap
import qualified Data.Sequence as Seq
import qualified Data.Strict.Maybe as Strict
import Data.Text ( Text )
import qualified Data.Text as Text
import qualified Language.LSP.Types as LSP
toAgdaRange :: ToOffset -> Text -> LSP.Range -> Range
toAgdaRange :: ToOffset -> Text -> Range -> Range
toAgdaRange ToOffset
table Text
path (LSP.Range Position
start Position
end) = forall a. a -> Seq IntervalWithoutFile -> Range' a
Range
(forall a. a -> Maybe a
Strict.Just (Text -> AbsolutePath
AbsolutePath Text
path))
(forall a. a -> Seq a
Seq.singleton IntervalWithoutFile
interval)
where
interval :: IntervalWithoutFile
interval :: IntervalWithoutFile
interval = forall a. Position' a -> Position' a -> Interval' a
Interval (ToOffset -> Position -> PositionWithoutFile
toAgdaPositionWithoutFile ToOffset
table Position
start)
(ToOffset -> Position -> PositionWithoutFile
toAgdaPositionWithoutFile ToOffset
table Position
end)
toAgdaPositionWithoutFile :: ToOffset -> LSP.Position -> PositionWithoutFile
toAgdaPositionWithoutFile :: ToOffset -> Position -> PositionWithoutFile
toAgdaPositionWithoutFile ToOffset
table (LSP.Position UInt
line UInt
col) = forall a. a -> Int32 -> Int32 -> Int32 -> Position' a
Pn
()
(forall a b. (Integral a, Num b) => a -> b
fromIntegral (ToOffset -> (Int, Int) -> Int
toOffset ToOffset
table (forall a b. (Integral a, Num b) => a -> b
fromIntegral UInt
line, forall a b. (Integral a, Num b) => a -> b
fromIntegral UInt
col)) forall a. Num a => a -> a -> a
+ Int32
1)
(forall a b. (Integral a, Num b) => a -> b
fromIntegral UInt
line forall a. Num a => a -> a -> a
+ Int32
1)
(forall a b. (Integral a, Num b) => a -> b
fromIntegral UInt
col forall a. Num a => a -> a -> a
+ Int32
1)
prettyPositionWithoutFile :: PositionWithoutFile -> String
prettyPositionWithoutFile :: PositionWithoutFile -> String
prettyPositionWithoutFile pos :: PositionWithoutFile
pos@(Pn () Int32
offset Int32
_line Int32
_col) =
String
"[" forall a. Semigroup a => a -> a -> a
<> forall a. Show a => a -> String
show PositionWithoutFile
pos forall a. Semigroup a => a -> a -> a
<> String
"-" forall a. Semigroup a => a -> a -> a
<> forall a. Show a => a -> String
show Int32
offset forall a. Semigroup a => a -> a -> a
<> String
"]"
newtype ToOffset = ToOffset { ToOffset -> IntMap Int
unToOffset :: IntMap Int }
data Accum = Accum
{ Accum -> Maybe Char
accumPreviousChar :: Maybe Char
, Accum -> Int
accumCurrentOffset :: Int
, Accum -> Int
accumCurrentLine :: Int
, Accum -> IntMap Int
accumResult :: IntMap Int
}
makeToOffset :: Text -> ToOffset
makeToOffset :: Text -> ToOffset
makeToOffset = IntMap Int -> ToOffset
ToOffset forall b c a. (b -> c) -> (a -> b) -> a -> c
. Accum -> IntMap Int
accumResult forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. (a -> Char -> a) -> a -> Text -> a
Text.foldl' Accum -> Char -> Accum
go Accum
initAccum
where
initAccum :: Accum
initAccum :: Accum
initAccum = Maybe Char -> Int -> Int -> IntMap Int -> Accum
Accum forall a. Maybe a
Nothing Int
0 Int
0 forall a. IntMap a
IntMap.empty
go :: Accum -> Char -> Accum
go :: Accum -> Char -> Accum
go (Accum (Just Char
'\r') Int
n Int
l IntMap Int
table) Char
'\n' =
Maybe Char -> Int -> Int -> IntMap Int -> Accum
Accum (forall a. a -> Maybe a
Just Char
'\n') (Int
1 forall a. Num a => a -> a -> a
+ Int
n) Int
l (forall a. (a -> Maybe a) -> IntMap a -> IntMap a
IntMap.updateMax (forall a. a -> Maybe a
Just forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Enum a => a -> a
succ) IntMap Int
table)
go (Accum Maybe Char
previous Int
n Int
l IntMap Int
table) Char
'\n' =
Maybe Char -> Int -> Int -> IntMap Int -> Accum
Accum (forall a. a -> Maybe a
Just Char
'\n') (Int
1 forall a. Num a => a -> a -> a
+ Int
n) (Int
1 forall a. Num a => a -> a -> a
+ Int
l) (forall a. Int -> a -> IntMap a -> IntMap a
IntMap.insert (Int
1 forall a. Num a => a -> a -> a
+ Int
l) (Int
1 forall a. Num a => a -> a -> a
+ Int
n) IntMap Int
table)
go (Accum Maybe Char
previous Int
n Int
l IntMap Int
table) Char
'\r' =
Maybe Char -> Int -> Int -> IntMap Int -> Accum
Accum (forall a. a -> Maybe a
Just Char
'\r') (Int
1 forall a. Num a => a -> a -> a
+ Int
n) (Int
1 forall a. Num a => a -> a -> a
+ Int
l) (forall a. Int -> a -> IntMap a -> IntMap a
IntMap.insert (Int
1 forall a. Num a => a -> a -> a
+ Int
l) (Int
1 forall a. Num a => a -> a -> a
+ Int
n) IntMap Int
table)
go (Accum Maybe Char
previous Int
n Int
l IntMap Int
table) Char
char = Maybe Char -> Int -> Int -> IntMap Int -> Accum
Accum (forall a. a -> Maybe a
Just Char
char) (Int
1 forall a. Num a => a -> a -> a
+ Int
n) Int
l IntMap Int
table
toOffset :: ToOffset -> (Int, Int) -> Int
toOffset :: ToOffset -> (Int, Int) -> Int
toOffset (ToOffset IntMap Int
table) (Int
line, Int
col) = case forall a. Int -> IntMap a -> Maybe a
IntMap.lookup Int
line IntMap Int
table of
Maybe Int
Nothing -> Int
col
Just Int
offset -> Int
offset forall a. Num a => a -> a -> a
+ Int
col
newtype FromOffset = FromOffset { FromOffset -> IntMap Int
unFromOffset :: IntMap Int }
fromOffset :: FromOffset -> Int -> (Int, Int)
fromOffset :: FromOffset -> Int -> (Int, Int)
fromOffset (FromOffset IntMap Int
table) Int
offset = case forall a. Int -> IntMap a -> Maybe (Int, a)
IntMap.lookupLE Int
offset IntMap Int
table of
Maybe (Int, Int)
Nothing -> (Int
0, Int
offset)
Just (Int
offsetOfFirstChar, Int
lineNo) -> (Int
lineNo, Int
offset forall a. Num a => a -> a -> a
- Int
offsetOfFirstChar)
makeFromOffset :: Text -> FromOffset
makeFromOffset :: Text -> FromOffset
makeFromOffset = IntMap Int -> FromOffset
FromOffset forall b c a. (b -> c) -> (a -> b) -> a -> c
. Accum -> IntMap Int
accumResult forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. (a -> Char -> a) -> a -> Text -> a
Text.foldl'
Accum -> Char -> Accum
go
(Maybe Char -> Int -> Int -> IntMap Int -> Accum
Accum forall a. Maybe a
Nothing Int
0 Int
0 forall a. IntMap a
IntMap.empty)
where
go :: Accum -> Char -> Accum
go :: Accum -> Char -> Accum
go (Accum (Just Char
'\r') Int
n Int
l IntMap Int
table) Char
'\n' = case forall a. IntMap a -> ((Int, a), IntMap a)
IntMap.deleteFindMax IntMap Int
table of
((Int
offset, Int
lineNo), IntMap Int
table') ->
Maybe Char -> Int -> Int -> IntMap Int -> Accum
Accum (forall a. a -> Maybe a
Just Char
'\n') (Int
1 forall a. Num a => a -> a -> a
+ Int
n) Int
l (forall a. Int -> a -> IntMap a -> IntMap a
IntMap.insert (Int
1 forall a. Num a => a -> a -> a
+ Int
offset) Int
lineNo IntMap Int
table')
go (Accum Maybe Char
previous Int
n Int
l IntMap Int
table) Char
'\n' =
Maybe Char -> Int -> Int -> IntMap Int -> Accum
Accum (forall a. a -> Maybe a
Just Char
'\n') (Int
1 forall a. Num a => a -> a -> a
+ Int
n) (Int
1 forall a. Num a => a -> a -> a
+ Int
l) (forall a. Int -> a -> IntMap a -> IntMap a
IntMap.insert (Int
1 forall a. Num a => a -> a -> a
+ Int
n) (Int
1 forall a. Num a => a -> a -> a
+ Int
l) IntMap Int
table)
go (Accum Maybe Char
previous Int
n Int
l IntMap Int
table) Char
'\r' =
Maybe Char -> Int -> Int -> IntMap Int -> Accum
Accum (forall a. a -> Maybe a
Just Char
'\r') (Int
1 forall a. Num a => a -> a -> a
+ Int
n) (Int
1 forall a. Num a => a -> a -> a
+ Int
l) (forall a. Int -> a -> IntMap a -> IntMap a
IntMap.insert (Int
1 forall a. Num a => a -> a -> a
+ Int
n) (Int
1 forall a. Num a => a -> a -> a
+ Int
l) IntMap Int
table)
go (Accum Maybe Char
previous Int
n Int
l IntMap Int
table) Char
char = Maybe Char -> Int -> Int -> IntMap Int -> Accum
Accum (forall a. a -> Maybe a
Just Char
char) (Int
1 forall a. Num a => a -> a -> a
+ Int
n) Int
l IntMap Int
table