module Hakyllbars.Ast
  ( Template (..),
    Block (..),
    getBlockName,
    getBlockPos,
    ApplyBlock (..),
    DefaultBlock (..),
    Expression (..),
    getExpressionPos,
  )
where

import Data.Binary
import qualified Data.ByteString.Char8 as Char8
import Data.List.NonEmpty (NonEmpty)
import Data.Yaml (ToJSON (..), object, (.=))
import Data.Yaml.Pretty (defConfig, encodePretty)
import GHC.Generics (Generic)
import Hakyllbars.Common
import Text.Parsec hiding (getPosition)
import Text.Parsec.Pos

showJSON :: (ToJSON a) => a -> String
showJSON :: forall a. ToJSON a => a -> FilePath
showJSON = ByteString -> FilePath
Char8.unpack forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. ToJSON a => Config -> a -> ByteString
encodePretty Config
defConfig forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. ToJSON a => a -> Value
toJSON

data Template = Template [Block] FilePath
  deriving (forall x. Rep Template x -> Template
forall x. Template -> Rep Template x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep Template x -> Template
$cfrom :: forall x. Template -> Rep Template x
Generic)

instance Binary Template where
  get :: Get Template
get = [Block] -> FilePath -> Template
Template forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall t. Binary t => Get t
get forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall t. Binary t => Get t
get

  put :: Template -> Put
put (Template [Block]
blocks FilePath
pos) = do
    forall t. Binary t => t -> Put
put [Block]
blocks
    forall t. Binary t => t -> Put
put FilePath
pos

instance Writable Template where
  write :: FilePath -> Item Template -> IO ()
write FilePath
_ Item Template
_ = forall (m :: * -> *) a. Monad m => a -> m a
return ()

instance ToJSON Template

instance Show Template where
  show :: Template -> FilePath
show = forall a. ToJSON a => a -> FilePath
showJSON

data Block
  = TextBlock String SourcePos
  | ExpressionBlock Expression SourcePos
  | CommentBlock String SourcePos
  | ChromeBlock Expression [Block] SourcePos
  | AltBlock
      (NonEmpty ApplyBlock)
      (Maybe DefaultBlock)
      SourcePos
  deriving (forall x. Rep Block x -> Block
forall x. Block -> Rep Block x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep Block x -> Block
$cfrom :: forall x. Block -> Rep Block x
Generic)

getBlockName :: Block -> String
getBlockName :: Block -> FilePath
getBlockName = \case
  TextBlock {} -> FilePath
"TextBlock"
  ExpressionBlock {} -> FilePath
"ExpressionBlock"
  CommentBlock {} -> FilePath
"CommentBlock"
  ChromeBlock {} -> FilePath
"ChromeBlock"
  AltBlock {} -> FilePath
"AltBlock"

getBlockPos :: Block -> SourcePos
getBlockPos :: Block -> SourcePos
getBlockPos = \case
  TextBlock FilePath
_ SourcePos
pos -> SourcePos
pos
  ExpressionBlock Expression
_ SourcePos
pos -> SourcePos
pos
  CommentBlock FilePath
_ SourcePos
pos -> SourcePos
pos
  ChromeBlock Expression
_ [Block]
_ SourcePos
pos -> SourcePos
pos
  AltBlock NonEmpty ApplyBlock
_ Maybe DefaultBlock
_ SourcePos
pos -> SourcePos
pos

getBlockTag :: Block -> Int
getBlockTag :: Block -> Int
getBlockTag = \case
  TextBlock {} -> Int
1
  ExpressionBlock {} -> Int
2
  CommentBlock {} -> Int
3
  ChromeBlock {} -> Int
4
  AltBlock {} -> Int
5

instance Binary Block where
  get :: Get Block
get = do
    Int
tag <- forall t. Binary t => Get t
get :: Get Int
    SourcePos -> Block
f <- case Int
tag of
      Int
1 -> FilePath -> SourcePos -> Block
TextBlock forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall t. Binary t => Get t
get
      Int
2 -> Expression -> SourcePos -> Block
ExpressionBlock forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall t. Binary t => Get t
get
      Int
3 -> FilePath -> SourcePos -> Block
CommentBlock forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall t. Binary t => Get t
get
      Int
4 -> Expression -> [Block] -> SourcePos -> Block
ChromeBlock forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall t. Binary t => Get t
get forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall t. Binary t => Get t
get
      Int
5 -> NonEmpty ApplyBlock -> Maybe DefaultBlock -> SourcePos -> Block
AltBlock forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall t. Binary t => Get t
get forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall t. Binary t => Get t
get
      Int
_ -> forall a. HasCallStack => FilePath -> a
error forall a b. (a -> b) -> a -> b
$ FilePath
"Unrecognized block tag " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> FilePath
show Int
tag
    BinaryPos
binaryPos <- forall t. Binary t => Get t
get :: Get BinaryPos
    forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ SourcePos -> Block
f (BinaryPos -> SourcePos
unBinaryPos BinaryPos
binaryPos)

  put :: Block -> Put
put Block
block = do
    forall t. Binary t => t -> Put
put forall a b. (a -> b) -> a -> b
$ Block -> Int
getBlockTag Block
block
    case Block
block of
      TextBlock FilePath
text SourcePos
_ -> forall t. Binary t => t -> Put
put FilePath
text
      ExpressionBlock Expression
expression SourcePos
_ -> forall t. Binary t => t -> Put
put Expression
expression
      CommentBlock FilePath
text SourcePos
_ -> forall t. Binary t => t -> Put
put FilePath
text
      ChromeBlock Expression
expression [Block]
blocks SourcePos
_ -> forall t. Binary t => t -> Put
put Expression
expression forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> forall t. Binary t => t -> Put
put [Block]
blocks
      AltBlock NonEmpty ApplyBlock
blocks Maybe DefaultBlock
default' SourcePos
_ -> forall t. Binary t => t -> Put
put NonEmpty ApplyBlock
blocks forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> forall t. Binary t => t -> Put
put Maybe DefaultBlock
default'
    forall t. Binary t => t -> Put
put forall a b. (a -> b) -> a -> b
$ SourcePos -> BinaryPos
BinaryPos (Block -> SourcePos
getBlockPos Block
block)

instance ToJSON Block where
  toJSON :: Block -> Value
toJSON = \case
    TextBlock FilePath
text SourcePos
pos ->
      [Pair] -> Value
object
        [ Key
"type" forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= (FilePath
"TextBlock" :: String),
          Key
"text" forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= FilePath
text,
          Key
"pos" forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= forall a. Show a => a -> FilePath
show SourcePos
pos
        ]
    ExpressionBlock Expression
expression SourcePos
pos ->
      [Pair] -> Value
object
        [ Key
"type" forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= (FilePath
"ExpressionBlock" :: String),
          Key
"expression" forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= Expression
expression,
          Key
"pos" forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= forall a. Show a => a -> FilePath
show SourcePos
pos
        ]
    CommentBlock FilePath
text SourcePos
pos ->
      [Pair] -> Value
object
        [ Key
"type" forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= (FilePath
"CommentBlock" :: String),
          Key
"text" forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= FilePath
text,
          Key
"pos" forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= forall a. Show a => a -> FilePath
show SourcePos
pos
        ]
    ChromeBlock Expression
expression [Block]
blocks SourcePos
_ ->
      [Pair] -> Value
object
        [ Key
"type" forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= (FilePath
"ChromeBlock" :: String),
          Key
"expression" forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= Expression
expression,
          Key
"blocks" forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= [Block]
blocks
        ]
    AltBlock NonEmpty ApplyBlock
blocks Maybe DefaultBlock
default' SourcePos
_ ->
      [Pair] -> Value
object
        [ Key
"type" forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= (FilePath
"AltBlock" :: String),
          Key
"blocks" forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= NonEmpty ApplyBlock
blocks,
          Key
"default" forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= Maybe DefaultBlock
default'
        ]

instance Show Block where
  show :: Block -> FilePath
show = forall a. ToJSON a => a -> FilePath
showJSON

newtype BinaryPos = BinaryPos SourcePos
  deriving (Int -> BinaryPos -> ShowS
[BinaryPos] -> ShowS
BinaryPos -> FilePath
forall a.
(Int -> a -> ShowS) -> (a -> FilePath) -> ([a] -> ShowS) -> Show a
showList :: [BinaryPos] -> ShowS
$cshowList :: [BinaryPos] -> ShowS
show :: BinaryPos -> FilePath
$cshow :: BinaryPos -> FilePath
showsPrec :: Int -> BinaryPos -> ShowS
$cshowsPrec :: Int -> BinaryPos -> ShowS
Show)

unBinaryPos :: BinaryPos -> SourcePos
unBinaryPos :: BinaryPos -> SourcePos
unBinaryPos (BinaryPos SourcePos
pos) = SourcePos
pos

instance Binary BinaryPos where
  get :: Get BinaryPos
get = SourcePos -> BinaryPos
BinaryPos forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (FilePath -> Int -> Int -> SourcePos
newPos forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall t. Binary t => Get t
get forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall t. Binary t => Get t
get forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall t. Binary t => Get t
get)
  put :: BinaryPos -> Put
put BinaryPos
binaryPos = do
    let pos :: SourcePos
pos = BinaryPos -> SourcePos
unBinaryPos BinaryPos
binaryPos
    forall t. Binary t => t -> Put
put forall a b. (a -> b) -> a -> b
$ SourcePos -> FilePath
sourceName SourcePos
pos
    forall t. Binary t => t -> Put
put forall a b. (a -> b) -> a -> b
$ SourcePos -> Int
sourceLine SourcePos
pos
    forall t. Binary t => t -> Put
put forall a b. (a -> b) -> a -> b
$ SourcePos -> Int
sourceColumn SourcePos
pos

data ApplyBlock = ApplyBlock Expression [Block] SourcePos
  deriving (forall x. Rep ApplyBlock x -> ApplyBlock
forall x. ApplyBlock -> Rep ApplyBlock x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep ApplyBlock x -> ApplyBlock
$cfrom :: forall x. ApplyBlock -> Rep ApplyBlock x
Generic)

instance Binary ApplyBlock where
  get :: Get ApplyBlock
get = do
    SourcePos -> ApplyBlock
f <- Expression -> [Block] -> SourcePos -> ApplyBlock
ApplyBlock forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall t. Binary t => Get t
get forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall t. Binary t => Get t
get
    BinaryPos
binaryPos <- forall t. Binary t => Get t
get :: Get BinaryPos
    forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ SourcePos -> ApplyBlock
f (BinaryPos -> SourcePos
unBinaryPos BinaryPos
binaryPos)

  put :: ApplyBlock -> Put
put (ApplyBlock Expression
expression [Block]
blocks SourcePos
pos) = do
    forall t. Binary t => t -> Put
put Expression
expression
    forall t. Binary t => t -> Put
put [Block]
blocks
    forall t. Binary t => t -> Put
put forall a b. (a -> b) -> a -> b
$ SourcePos -> BinaryPos
BinaryPos SourcePos
pos

instance ToJSON ApplyBlock where
  toJSON :: ApplyBlock -> Value
toJSON (ApplyBlock Expression
expression [Block]
blocks SourcePos
pos) =
    [Pair] -> Value
object
      [ Key
"type" forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= (FilePath
"ApplyBlock" :: String),
        Key
"expression" forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= Expression
expression,
        Key
"blocks" forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= [Block]
blocks,
        Key
"pos" forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= forall a. Show a => a -> FilePath
show SourcePos
pos
      ]

instance Show ApplyBlock where
  show :: ApplyBlock -> FilePath
show = forall a. ToJSON a => a -> FilePath
showJSON

data DefaultBlock = DefaultBlock [Block] SourcePos
  deriving (forall x. Rep DefaultBlock x -> DefaultBlock
forall x. DefaultBlock -> Rep DefaultBlock x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep DefaultBlock x -> DefaultBlock
$cfrom :: forall x. DefaultBlock -> Rep DefaultBlock x
Generic)

instance Binary DefaultBlock where
  get :: Get DefaultBlock
get = do
    SourcePos -> DefaultBlock
f <- [Block] -> SourcePos -> DefaultBlock
DefaultBlock forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall t. Binary t => Get t
get
    BinaryPos
binaryPos <- forall t. Binary t => Get t
get :: Get BinaryPos
    forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ SourcePos -> DefaultBlock
f (BinaryPos -> SourcePos
unBinaryPos BinaryPos
binaryPos)

  put :: DefaultBlock -> Put
put (DefaultBlock [Block]
blocks SourcePos
pos) = do
    forall t. Binary t => t -> Put
put [Block]
blocks
    forall t. Binary t => t -> Put
put forall a b. (a -> b) -> a -> b
$ SourcePos -> BinaryPos
BinaryPos SourcePos
pos

instance ToJSON DefaultBlock where
  toJSON :: DefaultBlock -> Value
toJSON (DefaultBlock [Block]
blocks SourcePos
pos) =
    [Pair] -> Value
object
      [ Key
"type" forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= (FilePath
"DefaultBlock" :: String),
        Key
"blocks" forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= [Block]
blocks,
        Key
"pos" forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= forall a. Show a => a -> FilePath
show SourcePos
pos
      ]

instance Show DefaultBlock where
  show :: DefaultBlock -> FilePath
show = forall a. ToJSON a => a -> FilePath
showJSON

data Expression
  = NameExpression String SourcePos -- name, id
  | StringExpression String SourcePos -- "a string of text"
  | IntExpression Int SourcePos -- 123, 456, 2
  | DoubleExpression Double SourcePos -- 0.2, 1.45
  | BoolExpression Bool SourcePos -- true, false
  | ApplyExpression Expression Expression SourcePos -- fn arg
  | AccessExpression Expression Expression SourcePos -- target.field
  | FilterExpression Expression Expression SourcePos -- arg | fn
  | ContextExpression [(String, Expression)] SourcePos -- { name0: value0, name1: value1 }
  | ListExpression [Expression] SourcePos -- [a, b, c]
  deriving (forall x. Rep Expression x -> Expression
forall x. Expression -> Rep Expression x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep Expression x -> Expression
$cfrom :: forall x. Expression -> Rep Expression x
Generic)

getExpressionPos :: Expression -> SourcePos
getExpressionPos :: Expression -> SourcePos
getExpressionPos = \case
  NameExpression FilePath
_ SourcePos
pos -> SourcePos
pos
  StringExpression FilePath
_ SourcePos
pos -> SourcePos
pos
  IntExpression Int
_ SourcePos
pos -> SourcePos
pos
  DoubleExpression Double
_ SourcePos
pos -> SourcePos
pos
  BoolExpression Bool
_ SourcePos
pos -> SourcePos
pos
  ApplyExpression Expression
_ Expression
_ SourcePos
pos -> SourcePos
pos
  AccessExpression Expression
_ Expression
_ SourcePos
pos -> SourcePos
pos
  FilterExpression Expression
_ Expression
_ SourcePos
pos -> SourcePos
pos
  ContextExpression [(FilePath, Expression)]
_ SourcePos
pos -> SourcePos
pos
  ListExpression [Expression]
_ SourcePos
pos -> SourcePos
pos

getExpressionTag :: Expression -> Int
getExpressionTag :: Expression -> Int
getExpressionTag = \case
  NameExpression {} -> Int
1
  StringExpression {} -> Int
2
  IntExpression {} -> Int
3
  DoubleExpression {} -> Int
4
  BoolExpression {} -> Int
5
  ApplyExpression {} -> Int
6
  AccessExpression {} -> Int
7
  FilterExpression {} -> Int
8
  ContextExpression {} -> Int
9
  ListExpression {} -> Int
10

instance Binary Expression where
  get :: Get Expression
get = do
    Int
tag <- forall t. Binary t => Get t
get :: Get Int
    SourcePos -> Expression
f <- case Int
tag of
      Int
1 -> FilePath -> SourcePos -> Expression
NameExpression forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall t. Binary t => Get t
get
      Int
2 -> FilePath -> SourcePos -> Expression
StringExpression forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall t. Binary t => Get t
get
      Int
3 -> Int -> SourcePos -> Expression
IntExpression forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall t. Binary t => Get t
get
      Int
4 -> Double -> SourcePos -> Expression
DoubleExpression forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall t. Binary t => Get t
get
      Int
5 -> Bool -> SourcePos -> Expression
BoolExpression forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall t. Binary t => Get t
get
      Int
6 -> Expression -> Expression -> SourcePos -> Expression
ApplyExpression forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall t. Binary t => Get t
get forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall t. Binary t => Get t
get
      Int
7 -> Expression -> Expression -> SourcePos -> Expression
AccessExpression forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall t. Binary t => Get t
get forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall t. Binary t => Get t
get
      Int
8 -> Expression -> Expression -> SourcePos -> Expression
FilterExpression forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall t. Binary t => Get t
get forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall t. Binary t => Get t
get
      Int
9 -> [(FilePath, Expression)] -> SourcePos -> Expression
ContextExpression forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall t. Binary t => Get t
get
      Int
10 -> [Expression] -> SourcePos -> Expression
ListExpression forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall t. Binary t => Get t
get
      Int
_ -> forall a. HasCallStack => FilePath -> a
error forall a b. (a -> b) -> a -> b
$ FilePath
"Unrecognized expression tag " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> FilePath
show Int
tag
    BinaryPos
binaryPos <- forall t. Binary t => Get t
get :: Get BinaryPos
    forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ SourcePos -> Expression
f (BinaryPos -> SourcePos
unBinaryPos BinaryPos
binaryPos)

  put :: Expression -> Put
put Expression
expression = do
    forall t. Binary t => t -> Put
put forall a b. (a -> b) -> a -> b
$ Expression -> Int
getExpressionTag Expression
expression
    case Expression
expression of
      NameExpression FilePath
value SourcePos
_ -> forall t. Binary t => t -> Put
put FilePath
value
      StringExpression FilePath
value SourcePos
_ -> forall t. Binary t => t -> Put
put FilePath
value
      IntExpression Int
value SourcePos
_ -> forall t. Binary t => t -> Put
put Int
value
      DoubleExpression Double
value SourcePos
_ -> forall t. Binary t => t -> Put
put Double
value
      BoolExpression Bool
value SourcePos
_ -> forall t. Binary t => t -> Put
put Bool
value
      ApplyExpression Expression
fn Expression
arg SourcePos
_ -> forall t. Binary t => t -> Put
put Expression
fn forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> forall t. Binary t => t -> Put
put Expression
arg
      AccessExpression Expression
target Expression
field SourcePos
_ -> forall t. Binary t => t -> Put
put Expression
target forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> forall t. Binary t => t -> Put
put Expression
field
      FilterExpression Expression
arg Expression
fn SourcePos
_ -> forall t. Binary t => t -> Put
put Expression
arg forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> forall t. Binary t => t -> Put
put Expression
fn
      ContextExpression [(FilePath, Expression)]
pairs SourcePos
_ -> forall t. Binary t => t -> Put
put [(FilePath, Expression)]
pairs
      ListExpression [Expression]
values SourcePos
_ -> forall t. Binary t => t -> Put
put [Expression]
values
    forall t. Binary t => t -> Put
put forall a b. (a -> b) -> a -> b
$ SourcePos -> BinaryPos
BinaryPos (Expression -> SourcePos
getExpressionPos Expression
expression)

instance ToJSON Expression where
  toJSON :: Expression -> Value
toJSON = \case
    NameExpression FilePath
value SourcePos
pos ->
      [Pair] -> Value
object
        [ Key
"type" forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= (FilePath
"NameExpression" :: String),
          Key
"value" forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= FilePath
value,
          Key
"pos" forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= forall a. Show a => a -> FilePath
show SourcePos
pos
        ]
    StringExpression FilePath
value SourcePos
pos ->
      [Pair] -> Value
object
        [ Key
"type" forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= (FilePath
"StringExpression" :: String),
          Key
"value" forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= FilePath
value,
          Key
"pos" forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= forall a. Show a => a -> FilePath
show SourcePos
pos
        ]
    IntExpression Int
value SourcePos
pos ->
      [Pair] -> Value
object
        [ Key
"type" forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= (FilePath
"IntExpression" :: String),
          Key
"value" forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= Int
value,
          Key
"pos" forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= forall a. Show a => a -> FilePath
show SourcePos
pos
        ]
    DoubleExpression Double
value SourcePos
pos ->
      [Pair] -> Value
object
        [ Key
"type" forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= (FilePath
"DoubleExpression" :: String),
          Key
"value" forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= Double
value,
          Key
"pos" forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= forall a. Show a => a -> FilePath
show SourcePos
pos
        ]
    BoolExpression Bool
value SourcePos
pos ->
      [Pair] -> Value
object
        [ Key
"type" forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= (FilePath
"BoolExpression" :: String),
          Key
"value" forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= Bool
value,
          Key
"pos" forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= forall a. Show a => a -> FilePath
show SourcePos
pos
        ]
    ApplyExpression Expression
fn Expression
arg SourcePos
pos ->
      [Pair] -> Value
object
        [ Key
"type" forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= (FilePath
"ApplyExpression" :: String),
          Key
"fn" forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= Expression
fn,
          Key
"arg" forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= Expression
arg,
          Key
"pos" forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= forall a. Show a => a -> FilePath
show SourcePos
pos
        ]
    AccessExpression Expression
target Expression
field SourcePos
pos ->
      [Pair] -> Value
object
        [ Key
"type" forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= (FilePath
"AccessExpression" :: String),
          Key
"target" forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= Expression
target,
          Key
"field" forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= Expression
field,
          Key
"pos" forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= forall a. Show a => a -> FilePath
show SourcePos
pos
        ]
    FilterExpression Expression
arg Expression
fn SourcePos
pos ->
      [Pair] -> Value
object
        [ Key
"type" forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= (FilePath
"FilterExpression" :: String),
          Key
"arg" forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= Expression
arg,
          Key
"fn" forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= Expression
fn,
          Key
"pos" forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= forall a. Show a => a -> FilePath
show SourcePos
pos
        ]
    ContextExpression [(FilePath, Expression)]
pairs SourcePos
pos ->
      [Pair] -> Value
object
        [ Key
"type" forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= (FilePath
"ContextExpression" :: String),
          Key
"pairs" forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= [(FilePath, Expression)]
pairs,
          Key
"pos" forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= forall a. Show a => a -> FilePath
show SourcePos
pos
        ]
    ListExpression [Expression]
values SourcePos
pos ->
      [Pair] -> Value
object
        [ Key
"type" forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= (FilePath
"ListExpression" :: String),
          Key
"values" forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= [Expression]
values,
          Key
"pos" forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= forall a. Show a => a -> FilePath
show SourcePos
pos
        ]

instance Show Expression where
  show :: Expression -> FilePath
show = forall a. ToJSON a => a -> FilePath
showJSON