{-# 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
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. 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
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
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,
      forall t.
(forall (m :: * -> *). Quote m => t -> m Exp)
-> (forall (m :: * -> *). Quote m => t -> Code m t) -> Lift t
forall (m :: * -> *). Quote m => Position -> m Exp
forall (m :: * -> *). Quote m => Position -> Code m Position
liftTyped :: forall (m :: * -> *). Quote m => Position -> Code m Position
$cliftTyped :: forall (m :: * -> *). Quote m => Position -> Code m Position
lift :: forall (m :: * -> *). Quote m => Position -> m Exp
$clift :: forall (m :: * -> *). Quote m => Position -> m Exp
Lift
    )

instance Hashable Position where
  hashWithSalt :: Int -> Position -> Int
hashWithSalt Int
s Position
_ = forall a. Hashable a => Int -> a -> Int
hashWithSalt Int
s (Int
0 :: Int)

-- 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) = forall a. Ord a => a -> a -> Ordering
compare Int
l1 Int
l2 forall a. Semigroup a => a -> a -> a
<> 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
  { forall name. Ref name -> name
refName :: name,
    forall name. Ref name -> Position
refPosition :: Position
  }
  deriving (Int -> Ref name -> ShowS
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, forall name (m :: * -> *).
(Lift name, Quote m) =>
Ref name -> m Exp
forall name (m :: * -> *).
(Lift name, Quote m) =>
Ref name -> Code m (Ref name)
forall t.
(forall (m :: * -> *). Quote m => t -> m Exp)
-> (forall (m :: * -> *). Quote m => t -> Code m t) -> Lift t
forall (m :: * -> *). Quote m => Ref name -> m Exp
forall (m :: * -> *). Quote m => Ref name -> Code m (Ref name)
liftTyped :: forall (m :: * -> *). Quote m => Ref name -> Code m (Ref name)
$cliftTyped :: forall name (m :: * -> *).
(Lift name, Quote m) =>
Ref name -> Code m (Ref name)
lift :: forall (m :: * -> *). Quote m => Ref name -> m Exp
$clift :: forall name (m :: * -> *).
(Lift name, Quote m) =>
Ref name -> m Exp
Lift, Ref name -> Ref name -> Bool
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
_) = forall a. Ord a => a -> a -> Ordering
compare name
x name
y