-- Copyright (C) 2018-2024 Jun Zhang <zhangjunphy[at]gmail[dot]com>
--
-- This file is a part of decafc.
--
-- decafc is free software: you can redistribute it and/or modify it under the
-- terms of the MIT (X11) License as described in the LICENSE file.
--
-- decafc is distributed in the hope that it will be useful, but WITHOUT ANY
-- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-- FOR A PARTICULAR PURPOSE.  See the X11 license for more details.

module Util.SourceLoc (Posn (..), Range (..), Located (..), unLoc, getLoc) where

import Formatting (formatToString, int, shown, (%))

data Posn = Posn
  { Posn -> Int
offset :: !Int,
    Posn -> Int
row :: !Int,
    Posn -> Int
col :: !Int
  }
  deriving (Posn -> Posn -> Bool
(Posn -> Posn -> Bool) -> (Posn -> Posn -> Bool) -> Eq Posn
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Posn -> Posn -> Bool
== :: Posn -> Posn -> Bool
$c/= :: Posn -> Posn -> Bool
/= :: Posn -> Posn -> Bool
Eq, Eq Posn
Eq Posn
-> (Posn -> Posn -> Ordering)
-> (Posn -> Posn -> Bool)
-> (Posn -> Posn -> Bool)
-> (Posn -> Posn -> Bool)
-> (Posn -> Posn -> Bool)
-> (Posn -> Posn -> Posn)
-> (Posn -> Posn -> Posn)
-> Ord Posn
Posn -> Posn -> Bool
Posn -> Posn -> Ordering
Posn -> Posn -> Posn
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
$ccompare :: Posn -> Posn -> Ordering
compare :: Posn -> Posn -> Ordering
$c< :: Posn -> Posn -> Bool
< :: Posn -> Posn -> Bool
$c<= :: Posn -> Posn -> Bool
<= :: Posn -> Posn -> Bool
$c> :: Posn -> Posn -> Bool
> :: Posn -> Posn -> Bool
$c>= :: Posn -> Posn -> Bool
>= :: Posn -> Posn -> Bool
$cmax :: Posn -> Posn -> Posn
max :: Posn -> Posn -> Posn
$cmin :: Posn -> Posn -> Posn
min :: Posn -> Posn -> Posn
Ord)

posn0 :: Posn
posn0 :: Posn
posn0 = Int -> Int -> Int -> Posn
Posn Int
0 Int
0 Int
0

instance Show Posn where
  show :: Posn -> String
show (Posn Int
_ Int
row Int
col) = Format String (Int -> Int -> String) -> Int -> Int -> String
forall a. Format String a -> a
formatToString (Format (Int -> Int -> String) (Int -> Int -> String)
"(" Format (Int -> Int -> String) (Int -> Int -> String)
-> Format String (Int -> Int -> String)
-> Format String (Int -> Int -> String)
forall r a r'. Format r a -> Format r' r -> Format r' a
% Format (Int -> String) (Int -> Int -> String)
forall a r. Integral a => Format r (a -> r)
int Format (Int -> String) (Int -> Int -> String)
-> Format String (Int -> String)
-> Format String (Int -> Int -> String)
forall r a r'. Format r a -> Format r' r -> Format r' a
% Format (Int -> String) (Int -> String)
":" Format (Int -> String) (Int -> String)
-> Format String (Int -> String) -> Format String (Int -> String)
forall r a r'. Format r a -> Format r' r -> Format r' a
% Format String (Int -> String)
forall a r. Integral a => Format r (a -> r)
int Format String (Int -> String)
-> Format String String -> Format String (Int -> String)
forall r a r'. Format r a -> Format r' r -> Format r' a
% Format String String
")") Int
row Int
col

data Range = Range
  { Range -> Posn
start :: Posn,
    Range -> Posn
stop :: Posn
  }
  deriving (Range -> Range -> Bool
(Range -> Range -> Bool) -> (Range -> Range -> Bool) -> Eq Range
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Range -> Range -> Bool
== :: Range -> Range -> Bool
$c/= :: Range -> Range -> Bool
/= :: Range -> Range -> Bool
Eq, Eq Range
Eq Range
-> (Range -> Range -> Ordering)
-> (Range -> Range -> Bool)
-> (Range -> Range -> Bool)
-> (Range -> Range -> Bool)
-> (Range -> Range -> Bool)
-> (Range -> Range -> Range)
-> (Range -> Range -> Range)
-> Ord Range
Range -> Range -> Bool
Range -> Range -> Ordering
Range -> Range -> Range
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
$ccompare :: Range -> Range -> Ordering
compare :: Range -> Range -> Ordering
$c< :: Range -> Range -> Bool
< :: Range -> Range -> Bool
$c<= :: Range -> Range -> Bool
<= :: Range -> Range -> Bool
$c> :: Range -> Range -> Bool
> :: Range -> Range -> Bool
$c>= :: Range -> Range -> Bool
>= :: Range -> Range -> Bool
$cmax :: Range -> Range -> Range
max :: Range -> Range -> Range
$cmin :: Range -> Range -> Range
min :: Range -> Range -> Range
Ord)

range0 :: Range
range0 :: Range
range0 = Posn -> Posn -> Range
Range Posn
posn0 Posn
posn0

instance Show Range where
  show :: Range -> String
show (Range Posn
start Posn
stop) = Format String (Posn -> Posn -> String) -> Posn -> Posn -> String
forall a. Format String a -> a
formatToString (Format (Posn -> Posn -> String) (Posn -> Posn -> String)
"[" Format (Posn -> Posn -> String) (Posn -> Posn -> String)
-> Format String (Posn -> Posn -> String)
-> Format String (Posn -> Posn -> String)
forall r a r'. Format r a -> Format r' r -> Format r' a
% Format (Posn -> String) (Posn -> Posn -> String)
forall a r. Show a => Format r (a -> r)
shown Format (Posn -> String) (Posn -> Posn -> String)
-> Format String (Posn -> String)
-> Format String (Posn -> Posn -> String)
forall r a r'. Format r a -> Format r' r -> Format r' a
% Format (Posn -> String) (Posn -> String)
"-" Format (Posn -> String) (Posn -> String)
-> Format String (Posn -> String) -> Format String (Posn -> String)
forall r a r'. Format r a -> Format r' r -> Format r' a
% Format String (Posn -> String)
forall a r. Show a => Format r (a -> r)
shown Format String (Posn -> String)
-> Format String String -> Format String (Posn -> String)
forall r a r'. Format r a -> Format r' r -> Format r' a
% Format String String
"]") Posn
start Posn
stop


data Located a = LocatedAt Range a
  deriving (Int -> Located a -> ShowS
[Located a] -> ShowS
Located a -> String
(Int -> Located a -> ShowS)
-> (Located a -> String)
-> ([Located a] -> ShowS)
-> Show (Located a)
forall a. Show a => Int -> Located a -> ShowS
forall a. Show a => [Located a] -> ShowS
forall a. Show a => Located a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: forall a. Show a => Int -> Located a -> ShowS
showsPrec :: Int -> Located a -> ShowS
$cshow :: forall a. Show a => Located a -> String
show :: Located a -> String
$cshowList :: forall a. Show a => [Located a] -> ShowS
showList :: [Located a] -> ShowS
Show, (forall a b. (a -> b) -> Located a -> Located b)
-> (forall a b. a -> Located b -> Located a) -> Functor Located
forall a b. a -> Located b -> Located a
forall a b. (a -> b) -> Located a -> Located b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
$cfmap :: forall a b. (a -> b) -> Located a -> Located b
fmap :: forall a b. (a -> b) -> Located a -> Located b
$c<$ :: forall a b. a -> Located b -> Located a
<$ :: forall a b. a -> Located b -> Located a
Functor)

unLoc :: Located a -> a
unLoc :: forall a. Located a -> a
unLoc (LocatedAt Range
_ a
a) = a
a

getLoc :: Located a -> Range
getLoc :: forall a. Located a -> Range
getLoc (LocatedAt Range
r a
_) = Range
r