{- |
Module      : Prosidy.Source.Units
Description : Positional units for marking source-code locations.
Copyright   : (c) James Alexander Feldman-Crough, 2019
License     : MPL-2.0
Maintainer  : alex@fldcr.com
-}
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DerivingVia #-}
{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE Safe #-}
module Prosidy.Source.Units (Line(..), Column(..), Offset(..)) where

import           Prosidy.Internal.Classes

-- | A line number.
--
-- The 'Show' instance for 'Line' counts from one, while the internal
-- implementation counts from zero.
newtype Line = Line Word
  deriving stock (Line -> Line -> Bool
(Line -> Line -> Bool) -> (Line -> Line -> Bool) -> Eq Line
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Line -> Line -> Bool
$c/= :: Line -> Line -> Bool
== :: Line -> Line -> Bool
$c== :: Line -> Line -> Bool
Eq, Eq Line
Eq Line =>
(Line -> Line -> Ordering)
-> (Line -> Line -> Bool)
-> (Line -> Line -> Bool)
-> (Line -> Line -> Bool)
-> (Line -> Line -> Bool)
-> (Line -> Line -> Line)
-> (Line -> Line -> Line)
-> Ord Line
Line -> Line -> Bool
Line -> Line -> Ordering
Line -> Line -> Line
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 :: Line -> Line -> Line
$cmin :: Line -> Line -> Line
max :: Line -> Line -> Line
$cmax :: Line -> Line -> Line
>= :: Line -> Line -> Bool
$c>= :: Line -> Line -> Bool
> :: Line -> Line -> Bool
$c> :: Line -> Line -> Bool
<= :: Line -> Line -> Bool
$c<= :: Line -> Line -> Bool
< :: Line -> Line -> Bool
$c< :: Line -> Line -> Bool
compare :: Line -> Line -> Ordering
$ccompare :: Line -> Line -> Ordering
$cp1Ord :: Eq Line
Ord, (forall x. Line -> Rep Line x)
-> (forall x. Rep Line x -> Line) -> Generic Line
forall x. Rep Line x -> Line
forall x. Line -> Rep Line x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep Line x -> Line
$cfrom :: forall x. Line -> Rep Line x
Generic, Int -> Line -> ShowS
[Line] -> ShowS
Line -> String
(Int -> Line -> ShowS)
-> (Line -> String) -> ([Line] -> ShowS) -> Show Line
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Line] -> ShowS
$cshowList :: [Line] -> ShowS
show :: Line -> String
$cshow :: Line -> String
showsPrec :: Int -> Line -> ShowS
$cshowsPrec :: Int -> Line -> ShowS
Show)
  deriving anyclass (Int -> Line -> Int
Line -> Int
(Int -> Line -> Int) -> (Line -> Int) -> Hashable Line
forall a. (Int -> a -> Int) -> (a -> Int) -> Hashable a
hash :: Line -> Int
$chash :: Line -> Int
hashWithSalt :: Int -> Line -> Int
$chashWithSalt :: Int -> Line -> Int
Hashable, Line -> ()
(Line -> ()) -> NFData Line
forall a. (a -> ()) -> NFData a
rnf :: Line -> ()
$crnf :: Line -> ()
NFData, Get Line
[Line] -> Put
Line -> Put
(Line -> Put) -> Get Line -> ([Line] -> Put) -> Binary Line
forall t. (t -> Put) -> Get t -> ([t] -> Put) -> Binary t
putList :: [Line] -> Put
$cputList :: [Line] -> Put
get :: Get Line
$cget :: Get Line
put :: Line -> Put
$cput :: Line -> Put
Binary)
  deriving ([Line] -> Encoding
[Line] -> Value
Line -> Encoding
Line -> Value
(Line -> Value)
-> (Line -> Encoding)
-> ([Line] -> Value)
-> ([Line] -> Encoding)
-> ToJSON Line
forall a.
(a -> Value)
-> (a -> Encoding)
-> ([a] -> Value)
-> ([a] -> Encoding)
-> ToJSON a
toEncodingList :: [Line] -> Encoding
$ctoEncodingList :: [Line] -> Encoding
toJSONList :: [Line] -> Value
$ctoJSONList :: [Line] -> Value
toEncoding :: Line -> Encoding
$ctoEncoding :: Line -> Encoding
toJSON :: Line -> Value
$ctoJSON :: Line -> Value
ToJSON, Value -> Parser [Line]
Value -> Parser Line
(Value -> Parser Line) -> (Value -> Parser [Line]) -> FromJSON Line
forall a.
(Value -> Parser a) -> (Value -> Parser [a]) -> FromJSON a
parseJSONList :: Value -> Parser [Line]
$cparseJSONList :: Value -> Parser [Line]
parseJSON :: Value -> Parser Line
$cparseJSON :: Value -> Parser Line
FromJSON, Int -> Line
Line -> Int
Line -> [Line]
Line -> Line
Line -> Line -> [Line]
Line -> Line -> Line -> [Line]
(Line -> Line)
-> (Line -> Line)
-> (Int -> Line)
-> (Line -> Int)
-> (Line -> [Line])
-> (Line -> Line -> [Line])
-> (Line -> Line -> [Line])
-> (Line -> Line -> Line -> [Line])
-> Enum Line
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
enumFromThenTo :: Line -> Line -> Line -> [Line]
$cenumFromThenTo :: Line -> Line -> Line -> [Line]
enumFromTo :: Line -> Line -> [Line]
$cenumFromTo :: Line -> Line -> [Line]
enumFromThen :: Line -> Line -> [Line]
$cenumFromThen :: Line -> Line -> [Line]
enumFrom :: Line -> [Line]
$cenumFrom :: Line -> [Line]
fromEnum :: Line -> Int
$cfromEnum :: Line -> Int
toEnum :: Int -> Line
$ctoEnum :: Int -> Line
pred :: Line -> Line
$cpred :: Line -> Line
succ :: Line -> Line
$csucc :: Line -> Line
Enum) via Word

instance Pretty Line where
    pretty :: Line -> Doc ann
pretty (Line n :: Word
n) = Word -> Doc ann
forall a ann. Pretty a => a -> Doc ann
pretty (Word -> Doc ann) -> Word -> Doc ann
forall a b. (a -> b) -> a -> b
$ Word -> Word
forall a. Enum a => a -> a
succ Word
n

-- | A column number.
newtype Column = Column Word
  deriving stock (Column -> Column -> Bool
(Column -> Column -> Bool)
-> (Column -> Column -> Bool) -> Eq Column
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Column -> Column -> Bool
$c/= :: Column -> Column -> Bool
== :: Column -> Column -> Bool
$c== :: Column -> Column -> Bool
Eq, Eq Column
Eq Column =>
(Column -> Column -> Ordering)
-> (Column -> Column -> Bool)
-> (Column -> Column -> Bool)
-> (Column -> Column -> Bool)
-> (Column -> Column -> Bool)
-> (Column -> Column -> Column)
-> (Column -> Column -> Column)
-> Ord Column
Column -> Column -> Bool
Column -> Column -> Ordering
Column -> Column -> Column
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 :: Column -> Column -> Column
$cmin :: Column -> Column -> Column
max :: Column -> Column -> Column
$cmax :: Column -> Column -> Column
>= :: Column -> Column -> Bool
$c>= :: Column -> Column -> Bool
> :: Column -> Column -> Bool
$c> :: Column -> Column -> Bool
<= :: Column -> Column -> Bool
$c<= :: Column -> Column -> Bool
< :: Column -> Column -> Bool
$c< :: Column -> Column -> Bool
compare :: Column -> Column -> Ordering
$ccompare :: Column -> Column -> Ordering
$cp1Ord :: Eq Column
Ord, (forall x. Column -> Rep Column x)
-> (forall x. Rep Column x -> Column) -> Generic Column
forall x. Rep Column x -> Column
forall x. Column -> Rep Column x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep Column x -> Column
$cfrom :: forall x. Column -> Rep Column x
Generic, Int -> Column -> ShowS
[Column] -> ShowS
Column -> String
(Int -> Column -> ShowS)
-> (Column -> String) -> ([Column] -> ShowS) -> Show Column
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Column] -> ShowS
$cshowList :: [Column] -> ShowS
show :: Column -> String
$cshow :: Column -> String
showsPrec :: Int -> Column -> ShowS
$cshowsPrec :: Int -> Column -> ShowS
Show)
  deriving anyclass (Int -> Column -> Int
Column -> Int
(Int -> Column -> Int) -> (Column -> Int) -> Hashable Column
forall a. (Int -> a -> Int) -> (a -> Int) -> Hashable a
hash :: Column -> Int
$chash :: Column -> Int
hashWithSalt :: Int -> Column -> Int
$chashWithSalt :: Int -> Column -> Int
Hashable, Column -> ()
(Column -> ()) -> NFData Column
forall a. (a -> ()) -> NFData a
rnf :: Column -> ()
$crnf :: Column -> ()
NFData, Get Column
[Column] -> Put
Column -> Put
(Column -> Put) -> Get Column -> ([Column] -> Put) -> Binary Column
forall t. (t -> Put) -> Get t -> ([t] -> Put) -> Binary t
putList :: [Column] -> Put
$cputList :: [Column] -> Put
get :: Get Column
$cget :: Get Column
put :: Column -> Put
$cput :: Column -> Put
Binary)
  deriving ([Column] -> Encoding
[Column] -> Value
Column -> Encoding
Column -> Value
(Column -> Value)
-> (Column -> Encoding)
-> ([Column] -> Value)
-> ([Column] -> Encoding)
-> ToJSON Column
forall a.
(a -> Value)
-> (a -> Encoding)
-> ([a] -> Value)
-> ([a] -> Encoding)
-> ToJSON a
toEncodingList :: [Column] -> Encoding
$ctoEncodingList :: [Column] -> Encoding
toJSONList :: [Column] -> Value
$ctoJSONList :: [Column] -> Value
toEncoding :: Column -> Encoding
$ctoEncoding :: Column -> Encoding
toJSON :: Column -> Value
$ctoJSON :: Column -> Value
ToJSON, Value -> Parser [Column]
Value -> Parser Column
(Value -> Parser Column)
-> (Value -> Parser [Column]) -> FromJSON Column
forall a.
(Value -> Parser a) -> (Value -> Parser [a]) -> FromJSON a
parseJSONList :: Value -> Parser [Column]
$cparseJSONList :: Value -> Parser [Column]
parseJSON :: Value -> Parser Column
$cparseJSON :: Value -> Parser Column
FromJSON, Int -> Column
Column -> Int
Column -> [Column]
Column -> Column
Column -> Column -> [Column]
Column -> Column -> Column -> [Column]
(Column -> Column)
-> (Column -> Column)
-> (Int -> Column)
-> (Column -> Int)
-> (Column -> [Column])
-> (Column -> Column -> [Column])
-> (Column -> Column -> [Column])
-> (Column -> Column -> Column -> [Column])
-> Enum Column
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
enumFromThenTo :: Column -> Column -> Column -> [Column]
$cenumFromThenTo :: Column -> Column -> Column -> [Column]
enumFromTo :: Column -> Column -> [Column]
$cenumFromTo :: Column -> Column -> [Column]
enumFromThen :: Column -> Column -> [Column]
$cenumFromThen :: Column -> Column -> [Column]
enumFrom :: Column -> [Column]
$cenumFrom :: Column -> [Column]
fromEnum :: Column -> Int
$cfromEnum :: Column -> Int
toEnum :: Int -> Column
$ctoEnum :: Int -> Column
pred :: Column -> Column
$cpred :: Column -> Column
succ :: Column -> Column
$csucc :: Column -> Column
Enum) via Word

instance Pretty Column where
    pretty :: Column -> Doc ann
pretty (Column n :: Word
n) = Word -> Doc ann
forall a ann. Pretty a => a -> Doc ann
pretty (Word -> Doc ann) -> Word -> Doc ann
forall a b. (a -> b) -> a -> b
$ Word -> Word
forall a. Enum a => a -> a
succ Word
n

-- | An offset into a 'Source', counted by UTF-8 codepoint.
newtype Offset = Offset Word
  deriving stock (Offset -> Offset -> Bool
(Offset -> Offset -> Bool)
-> (Offset -> Offset -> Bool) -> Eq Offset
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Offset -> Offset -> Bool
$c/= :: Offset -> Offset -> Bool
== :: Offset -> Offset -> Bool
$c== :: Offset -> Offset -> Bool
Eq, Int -> Offset -> ShowS
[Offset] -> ShowS
Offset -> String
(Int -> Offset -> ShowS)
-> (Offset -> String) -> ([Offset] -> ShowS) -> Show Offset
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Offset] -> ShowS
$cshowList :: [Offset] -> ShowS
show :: Offset -> String
$cshow :: Offset -> String
showsPrec :: Int -> Offset -> ShowS
$cshowsPrec :: Int -> Offset -> ShowS
Show, Eq Offset
Eq Offset =>
(Offset -> Offset -> Ordering)
-> (Offset -> Offset -> Bool)
-> (Offset -> Offset -> Bool)
-> (Offset -> Offset -> Bool)
-> (Offset -> Offset -> Bool)
-> (Offset -> Offset -> Offset)
-> (Offset -> Offset -> Offset)
-> Ord Offset
Offset -> Offset -> Bool
Offset -> Offset -> Ordering
Offset -> Offset -> Offset
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 :: Offset -> Offset -> Offset
$cmin :: Offset -> Offset -> Offset
max :: Offset -> Offset -> Offset
$cmax :: Offset -> Offset -> Offset
>= :: Offset -> Offset -> Bool
$c>= :: Offset -> Offset -> Bool
> :: Offset -> Offset -> Bool
$c> :: Offset -> Offset -> Bool
<= :: Offset -> Offset -> Bool
$c<= :: Offset -> Offset -> Bool
< :: Offset -> Offset -> Bool
$c< :: Offset -> Offset -> Bool
compare :: Offset -> Offset -> Ordering
$ccompare :: Offset -> Offset -> Ordering
$cp1Ord :: Eq Offset
Ord, (forall x. Offset -> Rep Offset x)
-> (forall x. Rep Offset x -> Offset) -> Generic Offset
forall x. Rep Offset x -> Offset
forall x. Offset -> Rep Offset x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep Offset x -> Offset
$cfrom :: forall x. Offset -> Rep Offset x
Generic)
  deriving anyclass (Int -> Offset -> Int
Offset -> Int
(Int -> Offset -> Int) -> (Offset -> Int) -> Hashable Offset
forall a. (Int -> a -> Int) -> (a -> Int) -> Hashable a
hash :: Offset -> Int
$chash :: Offset -> Int
hashWithSalt :: Int -> Offset -> Int
$chashWithSalt :: Int -> Offset -> Int
Hashable, Offset -> ()
(Offset -> ()) -> NFData Offset
forall a. (a -> ()) -> NFData a
rnf :: Offset -> ()
$crnf :: Offset -> ()
NFData, Get Offset
[Offset] -> Put
Offset -> Put
(Offset -> Put) -> Get Offset -> ([Offset] -> Put) -> Binary Offset
forall t. (t -> Put) -> Get t -> ([t] -> Put) -> Binary t
putList :: [Offset] -> Put
$cputList :: [Offset] -> Put
get :: Get Offset
$cget :: Get Offset
put :: Offset -> Put
$cput :: Offset -> Put
Binary)
  deriving ([Offset] -> Encoding
[Offset] -> Value
Offset -> Encoding
Offset -> Value
(Offset -> Value)
-> (Offset -> Encoding)
-> ([Offset] -> Value)
-> ([Offset] -> Encoding)
-> ToJSON Offset
forall a.
(a -> Value)
-> (a -> Encoding)
-> ([a] -> Value)
-> ([a] -> Encoding)
-> ToJSON a
toEncodingList :: [Offset] -> Encoding
$ctoEncodingList :: [Offset] -> Encoding
toJSONList :: [Offset] -> Value
$ctoJSONList :: [Offset] -> Value
toEncoding :: Offset -> Encoding
$ctoEncoding :: Offset -> Encoding
toJSON :: Offset -> Value
$ctoJSON :: Offset -> Value
ToJSON, Value -> Parser [Offset]
Value -> Parser Offset
(Value -> Parser Offset)
-> (Value -> Parser [Offset]) -> FromJSON Offset
forall a.
(Value -> Parser a) -> (Value -> Parser [a]) -> FromJSON a
parseJSONList :: Value -> Parser [Offset]
$cparseJSONList :: Value -> Parser [Offset]
parseJSON :: Value -> Parser Offset
$cparseJSON :: Value -> Parser Offset
FromJSON, Int -> Offset
Offset -> Int
Offset -> [Offset]
Offset -> Offset
Offset -> Offset -> [Offset]
Offset -> Offset -> Offset -> [Offset]
(Offset -> Offset)
-> (Offset -> Offset)
-> (Int -> Offset)
-> (Offset -> Int)
-> (Offset -> [Offset])
-> (Offset -> Offset -> [Offset])
-> (Offset -> Offset -> [Offset])
-> (Offset -> Offset -> Offset -> [Offset])
-> Enum Offset
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
enumFromThenTo :: Offset -> Offset -> Offset -> [Offset]
$cenumFromThenTo :: Offset -> Offset -> Offset -> [Offset]
enumFromTo :: Offset -> Offset -> [Offset]
$cenumFromTo :: Offset -> Offset -> [Offset]
enumFromThen :: Offset -> Offset -> [Offset]
$cenumFromThen :: Offset -> Offset -> [Offset]
enumFrom :: Offset -> [Offset]
$cenumFrom :: Offset -> [Offset]
fromEnum :: Offset -> Int
$cfromEnum :: Offset -> Int
toEnum :: Int -> Offset
$ctoEnum :: Int -> Offset
pred :: Offset -> Offset
$cpred :: Offset -> Offset
succ :: Offset -> Offset
$csucc :: Offset -> Offset
Enum) via Word

instance Pretty Offset where
    pretty :: Offset -> Doc ann
pretty (Offset n :: Word
n) = "+" Doc ann -> Doc ann -> Doc ann
forall a. Semigroup a => a -> a -> a
<> Word -> Doc ann
forall a ann. Pretty a => a -> Doc ann
pretty Word
n