{- |
Copyright: (c) 2018-2020 Kowainik
SPDX-License-Identifier: MPL-2.0
Maintainer: Kowainik <xrom.xkov@gmail.com>

This module introduces EDSL for manually specifying 'TOML' data types.

Consider the following raw TOML:

@
key1 = 1
key2 = true

[meme-quotes]
  quote1 = [ \"Oh\", \"Hi\", \"Mark\" ]

[[arrayName]]
  elem1 = "yes"

[[arrayName]]
  [arrayName.elem2]
    deep = 7

[[arrayName]]
@

using functions from this module you can specify the above TOML in safer way:

@
exampleToml :: 'TOML'
exampleToml = 'mkToml' $ __do__
    \"key1\" '=:' 1
    \"key2\" '=:' Bool True
    'table' \"meme-quotes\" $
        \"quote1\" '=:' Array [\"Oh\", \"Hi\", \"Mark\"]
    'tableArray' \"arrayName\" $
        \"elem1\" '=:' \"yes\" :|
        [ 'table' \"elem2\" $ \"deep\" '=:' Integer 7
        , 'empty'
        ]
@

@since 0.3
-}

module Toml.Type.Edsl
       ( TDSL
       , mkToml
       , empty
       , (=:)
       , table
       , tableArray
       ) where

import Control.Monad.State (State, execState, modify, put)
import Data.List.NonEmpty (NonEmpty)

import Toml.Type.Key (Key)
import Toml.Type.TOML (TOML (..), insertKeyVal, insertTable, insertTableArrays)
import Toml.Type.Value (Value)


{- | Monad for creating TOML.

@since 0.3
-}
type TDSL = State TOML ()

{- | Creates 'TOML' from the 'TDSL'.

@since 0.3
-}
mkToml :: TDSL -> TOML
mkToml :: TDSL -> TOML
mkToml env :: TDSL
env = TDSL -> TOML -> TOML
forall s a. State s a -> s -> s
execState TDSL
env TOML
forall a. Monoid a => a
mempty
{-# INLINE mkToml #-}

{- | Creates an empty 'TDSL'.

@since 0.3
-}
empty :: TDSL
empty :: TDSL
empty = TOML -> TDSL
forall s (m :: * -> *). MonadState s m => s -> m ()
put TOML
forall a. Monoid a => a
mempty
{-# INLINE empty #-}

{- | Adds key-value pair to the 'TDSL'.

@since 0.3
-}
(=:) :: Key -> Value a -> TDSL
=: :: Key -> Value a -> TDSL
(=:) k :: Key
k v :: Value a
v = (TOML -> TOML) -> TDSL
forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
modify ((TOML -> TOML) -> TDSL) -> (TOML -> TOML) -> TDSL
forall a b. (a -> b) -> a -> b
$ Key -> Value a -> TOML -> TOML
forall (a :: TValue). Key -> Value a -> TOML -> TOML
insertKeyVal Key
k Value a
v
{-# INLINE (=:) #-}

{- | Adds table to the 'TDSL'.

@since 0.3
-}
table :: Key -> TDSL -> TDSL
table :: Key -> TDSL -> TDSL
table k :: Key
k = (TOML -> TOML) -> TDSL
forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
modify ((TOML -> TOML) -> TDSL) -> (TDSL -> TOML -> TOML) -> TDSL -> TDSL
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Key -> TOML -> TOML -> TOML
insertTable Key
k (TOML -> TOML -> TOML) -> (TDSL -> TOML) -> TDSL -> TOML -> TOML
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TDSL -> TOML
mkToml
{-# INLINE table #-}

{- | Adds array of tables to the 'TDSL'.

@since 1.0.0
-}
tableArray :: Key -> NonEmpty TDSL -> TDSL
tableArray :: Key -> NonEmpty TDSL -> TDSL
tableArray k :: Key
k = (TOML -> TOML) -> TDSL
forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
modify ((TOML -> TOML) -> TDSL)
-> (NonEmpty TDSL -> TOML -> TOML) -> NonEmpty TDSL -> TDSL
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Key -> NonEmpty TOML -> TOML -> TOML
insertTableArrays Key
k (NonEmpty TOML -> TOML -> TOML)
-> (NonEmpty TDSL -> NonEmpty TOML)
-> NonEmpty TDSL
-> TOML
-> TOML
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (TDSL -> TOML) -> NonEmpty TDSL -> NonEmpty TOML
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap TDSL -> TOML
mkToml
{-# INLINE tableArray #-}