{-# LANGUAGE DeriveGeneric #-}

module Dhall.Syntax.Binding
    ( Binding(..)
    , makeBinding

      -- * Optics
    , bindingExprs
    ) where

import                Data.Text         (Text)
import {-# SOURCE #-} Dhall.Syntax.Expr (Expr)
import                GHC.Generics      (Generic)

-- | Record the binding part of a @let@ expression.
--
-- For example,
--
-- > let {- A -} x {- B -} : {- C -} Bool = {- D -} True in x
--
-- … will be instantiated as follows:
--
-- * @bindingSrc0@ corresponds to the @A@ comment.
-- * @variable@ is @"x"@
-- * @bindingSrc1@ corresponds to the @B@ comment.
-- * @annotation@ is 'Just' a pair, corresponding to the @C@ comment and @Bool@.
-- * @bindingSrc2@ corresponds to the @D@ comment.
-- * @value@ corresponds to @True@.
data Binding s a = Binding
    { forall s a. Binding s a -> Maybe s
bindingSrc0 :: Maybe s
    , forall s a. Binding s a -> Text
variable    :: Text
    , forall s a. Binding s a -> Maybe s
bindingSrc1 :: Maybe s
    , forall s a. Binding s a -> Maybe (Maybe s, Expr s a)
annotation  :: Maybe (Maybe s, Expr s a)
    , forall s a. Binding s a -> Maybe s
bindingSrc2 :: Maybe s
    , forall s a. Binding s a -> Expr s a
value       :: Expr s a
    } deriving forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall s a x. Rep (Binding s a) x -> Binding s a
forall s a x. Binding s a -> Rep (Binding s a) x
$cto :: forall s a x. Rep (Binding s a) x -> Binding s a
$cfrom :: forall s a x. Binding s a -> Rep (Binding s a) x
Generic

{-| Construct a 'Binding' with no source information and no type annotation.
-}
makeBinding :: Text -> Expr s a -> Binding s a
makeBinding :: forall s a. Text -> Expr s a -> Binding s a
makeBinding Text
name = forall s a.
Maybe s
-> Text
-> Maybe s
-> Maybe (Maybe s, Expr s a)
-> Maybe s
-> Expr s a
-> Binding s a
Binding forall a. Maybe a
Nothing Text
name forall a. Maybe a
Nothing forall a. Maybe a
Nothing forall a. Maybe a
Nothing

{-| Traverse over the immediate 'Expr' children in a 'Binding'.
-}
bindingExprs
  :: (Applicative f)
  => (Expr s a -> f (Expr s b))
  -> Binding s a -> f (Binding s b)
bindingExprs :: forall (f :: * -> *) s a b.
Applicative f =>
(Expr s a -> f (Expr s b)) -> Binding s a -> f (Binding s b)
bindingExprs Expr s a -> f (Expr s b)
f (Binding Maybe s
s0 Text
n Maybe s
s1 Maybe (Maybe s, Expr s a)
t Maybe s
s2 Expr s a
v) =
  forall s a.
Maybe s
-> Text
-> Maybe s
-> Maybe (Maybe s, Expr s a)
-> Maybe s
-> Expr s a
-> Binding s a
Binding
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (f :: * -> *) a. Applicative f => a -> f a
pure Maybe s
s0
    forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall (f :: * -> *) a. Applicative f => a -> f a
pure Text
n
    forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall (f :: * -> *) a. Applicative f => a -> f a
pure Maybe s
s1
    forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse (forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse Expr s a -> f (Expr s b)
f) Maybe (Maybe s, Expr s a)
t
    forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall (f :: * -> *) a. Applicative f => a -> f a
pure Maybe s
s2
    forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Expr s a -> f (Expr s b)
f Expr s a
v
{-# INLINABLE bindingExprs #-}