{-# LANGUAGE CPP #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DeriveLift #-}
{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE NoImplicitPrelude #-}

module Data.Morpheus.Types.Internal.AST.Base
  ( Ref (..),
    Position (..),
    Description,
    Token,
    TRUE,
    FALSE,
  )
where

import Data.Aeson
  ( FromJSON,
    ToJSON (..),
  )
import Language.Haskell.TH.Syntax
  ( Lift (..),
  )
import Relude hiding
  ( ByteString,
    decodeUtf8,
    intercalate,
  )

type TRUE = 'True

type FALSE = 'False

-- Strings
type Token = Text

-- Description
type Description = Text

data Position = Position
  { Position -> Int
line :: Int,
    Position -> Int
column :: Int
  }
  deriving
    ( Int -> Position -> ShowS
[Position] -> ShowS
Position -> String
(Int -> Position -> ShowS)
-> (Position -> String) -> ([Position] -> ShowS) -> Show Position
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Position] -> ShowS
$cshowList :: [Position] -> ShowS
show :: Position -> String
$cshow :: Position -> String
showsPrec :: Int -> Position -> ShowS
$cshowsPrec :: Int -> Position -> ShowS
Show,
      (forall x. Position -> Rep Position x)
-> (forall x. Rep Position x -> Position) -> Generic Position
forall x. Rep Position x -> Position
forall x. Position -> Rep Position x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep Position x -> Position
$cfrom :: forall x. Position -> Rep Position x
Generic,
      Value -> Parser [Position]
Value -> Parser Position
(Value -> Parser Position)
-> (Value -> Parser [Position]) -> FromJSON Position
forall a.
(Value -> Parser a) -> (Value -> Parser [a]) -> FromJSON a
parseJSONList :: Value -> Parser [Position]
$cparseJSONList :: Value -> Parser [Position]
parseJSON :: Value -> Parser Position
$cparseJSON :: Value -> Parser Position
FromJSON,
      [Position] -> Encoding
[Position] -> Value
Position -> Encoding
Position -> Value
(Position -> Value)
-> (Position -> Encoding)
-> ([Position] -> Value)
-> ([Position] -> Encoding)
-> ToJSON Position
forall a.
(a -> Value)
-> (a -> Encoding)
-> ([a] -> Value)
-> ([a] -> Encoding)
-> ToJSON a
toEncodingList :: [Position] -> Encoding
$ctoEncodingList :: [Position] -> Encoding
toJSONList :: [Position] -> Value
$ctoJSONList :: [Position] -> Value
toEncoding :: Position -> Encoding
$ctoEncoding :: Position -> Encoding
toJSON :: Position -> Value
$ctoJSON :: Position -> Value
ToJSON,
      Position -> Q Exp
Position -> Q (TExp Position)
(Position -> Q Exp)
-> (Position -> Q (TExp Position)) -> Lift Position
forall t. (t -> Q Exp) -> (t -> Q (TExp t)) -> Lift t
liftTyped :: Position -> Q (TExp Position)
$cliftTyped :: Position -> Q (TExp Position)
lift :: Position -> Q Exp
$clift :: Position -> Q Exp
Lift
    )

-- Positions 2 Value with same structure
-- but different Positions should be Equal
instance Eq Position where
  Position
_ == :: Position -> Position -> Bool
== Position
_ = Bool
True

instance Ord Position where
  compare :: Position -> Position -> Ordering
compare (Position Int
l1 Int
c1) (Position Int
l2 Int
c2) = Int -> Int -> Ordering
forall a. Ord a => a -> a -> Ordering
compare Int
l1 Int
l2 Ordering -> Ordering -> Ordering
forall a. Semigroup a => a -> a -> a
<> Int -> Int -> Ordering
forall a. Ord a => a -> a -> Ordering
compare Int
c1 Int
c2

-- | Document Reference with its Position
--
-- Position is used only for error messages. that means:
--
-- Ref "a" 1 === Ref "a" 3
data Ref name = Ref
  { Ref name -> name
refName :: name,
    Ref name -> Position
refPosition :: Position
  }
  deriving (Int -> Ref name -> ShowS
[Ref name] -> ShowS
Ref name -> String
(Int -> Ref name -> ShowS)
-> (Ref name -> String) -> ([Ref name] -> ShowS) -> Show (Ref name)
forall name. Show name => Int -> Ref name -> ShowS
forall name. Show name => [Ref name] -> ShowS
forall name. Show name => Ref name -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Ref name] -> ShowS
$cshowList :: forall name. Show name => [Ref name] -> ShowS
show :: Ref name -> String
$cshow :: forall name. Show name => Ref name -> String
showsPrec :: Int -> Ref name -> ShowS
$cshowsPrec :: forall name. Show name => Int -> Ref name -> ShowS
Show, Ref name -> Q Exp
Ref name -> Q (TExp (Ref name))
(Ref name -> Q Exp)
-> (Ref name -> Q (TExp (Ref name))) -> Lift (Ref name)
forall name. Lift name => Ref name -> Q Exp
forall name. Lift name => Ref name -> Q (TExp (Ref name))
forall t. (t -> Q Exp) -> (t -> Q (TExp t)) -> Lift t
liftTyped :: Ref name -> Q (TExp (Ref name))
$cliftTyped :: forall name. Lift name => Ref name -> Q (TExp (Ref name))
lift :: Ref name -> Q Exp
$clift :: forall name. Lift name => Ref name -> Q Exp
Lift, Ref name -> Ref name -> Bool
(Ref name -> Ref name -> Bool)
-> (Ref name -> Ref name -> Bool) -> Eq (Ref name)
forall name. Eq name => Ref name -> Ref name -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Ref name -> Ref name -> Bool
$c/= :: forall name. Eq name => Ref name -> Ref name -> Bool
== :: Ref name -> Ref name -> Bool
$c== :: forall name. Eq name => Ref name -> Ref name -> Bool
Eq)

instance Ord name => Ord (Ref name) where
  compare :: Ref name -> Ref name -> Ordering
compare (Ref name
x Position
_) (Ref name
y Position
_) = name -> name -> Ordering
forall a. Ord a => a -> a -> Ordering
compare name
x name
y