    {-# LANGUAGE DeriveGeneric #-}

    module Dhall.Syntax.RecordField
        ( RecordField(..)
        , makeRecordField

          -- * Optics
        , recordFieldExprs
        ) where

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

    -- | Record the field of a record-type and record-literal expression.
    -- The reason why we use the same ADT for both of them is because they store
    -- the same information.
    --
    -- For example,
    --
    -- > { {- A -} x {- B -} : {- C -} T }
    --
    -- ... or
    --
    -- > { {- A -} x {- B -} = {- C -} T }
    --
    -- will be instantiated as follows:
    --
    -- * @recordFieldSrc0@ corresponds to the @A@ comment.
    -- * @recordFieldValue@ is @"T"@
    -- * @recordFieldSrc1@ corresponds to the @B@ comment.
    -- * @recordFieldSrc2@ corresponds to the @C@ comment.
    --
    -- Although the @A@ comment isn't annotating the @"T"@ Record Field,
    -- this is the best place to keep these comments.
    --
    -- Note that @recordFieldSrc2@ is always 'Nothing' when the 'RecordField' is for
    -- a punned entry, because there is no @=@ sign. For example,
    --
    -- > { {- A -} x {- B -} }
    --
    -- will be instantiated as follows:
    --
    -- * @recordFieldSrc0@ corresponds to the @A@ comment.
    -- * @recordFieldValue@ corresponds to @(Var "x")@
    -- * @recordFieldSrc1@ corresponds to the @B@ comment.
    -- * @recordFieldSrc2@ will be 'Nothing'
    --
    -- The labels involved in a record using dot-syntax like in this example:
    --
    -- > { {- A -} a {- B -} . {- C -} b {- D -} . {- E -} c {- F -} = {- G -} e }
    --
    -- will be instantiated as follows:
    --
    -- * For both the @a@ and @b@ field, @recordfieldSrc2@ is 'Nothing'
    -- * For the @a@ field:
    --   * @recordFieldSrc0@ corresponds to the @A@ comment
    --   * @recordFieldSrc1@ corresponds to the @B@ comment
    -- * For the @b@ field:
    --   * @recordFieldSrc0@ corresponds to the @C@ comment
    --   * @recordFieldSrc1@ corresponds to the @D@ comment
    -- * For the @c@ field:
    --   * @recordFieldSrc0@ corresponds to the @E@ comment
    --   * @recordFieldSrc1@ corresponds to the @F@ comment
    --   * @recordFieldSrc2@ corresponds to the @G@ comment
    --
    -- That is, for every label except the last one the semantics of
    -- @recordFieldSrc0@ and @recordFieldSrc1@ are the same from a regular record
    -- label but @recordFieldSrc2@ is always 'Nothing'. For the last keyword, all
    -- srcs are 'Just'
    data RecordField s a = RecordField
        { forall s a. RecordField s a -> Maybe s
    recordFieldSrc0  :: Maybe s
        , forall s a. RecordField s a -> Expr s a
    recordFieldValue :: Expr s a
        , forall s a. RecordField s a -> Maybe s
    recordFieldSrc1  :: Maybe s
        , forall s a. RecordField s a -> Maybe s
    recordFieldSrc2  :: Maybe s
        } deriving (forall x. RecordField s a -> Rep (RecordField s a) x)
    -> (forall x. Rep (RecordField s a) x -> RecordField s a)
    -> Generic (RecordField s a)
    forall x. Rep (RecordField s a) x -> RecordField s a
    forall x. RecordField s a -> Rep (RecordField s a) x
    forall a.
    (forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
    forall s a x. Rep (RecordField s a) x -> RecordField s a
    forall s a x. RecordField s a -> Rep (RecordField s a) x
    $cfrom :: forall s a x. RecordField s a -> Rep (RecordField s a) x
    from :: forall x. RecordField s a -> Rep (RecordField s a) x
    $cto :: forall s a x. Rep (RecordField s a) x -> RecordField s a
    to :: forall x. Rep (RecordField s a) x -> RecordField s a
    Generic

    -- | Construct a 'RecordField' with no src information
    makeRecordField :: Expr s a -> RecordField s a
    makeRecordField :: forall s a. Expr s a -> RecordField s a
    makeRecordField Expr s a
    e = Maybe s -> Expr s a -> Maybe s -> Maybe s -> RecordField s a
    forall s a.
    Maybe s -> Expr s a -> Maybe s -> Maybe s -> RecordField s a
    RecordField Maybe s
    forall a. Maybe a
    Nothing Expr s a
    e Maybe s
    forall a. Maybe a
    Nothing Maybe s
    forall a. Maybe a
    Nothing

    {-| Traverse over the immediate 'Expr' children in a 'RecordField'.
    -}
    recordFieldExprs
        :: Applicative f
        => (Expr s a -> f (Expr s b))
        -> RecordField s a -> f (RecordField s b)
    recordFieldExprs :: forall (f :: * -> *) s a b.
    Applicative f =>
    (Expr s a -> f (Expr s b))
    -> RecordField s a -> f (RecordField s b)
    recordFieldExprs Expr s a -> f (Expr s b)
    f (RecordField Maybe s
    s0 Expr s a
    e Maybe s
    s1 Maybe s
    s2) =
        Maybe s -> Expr s b -> Maybe s -> Maybe s -> RecordField s b
    forall s a.
    Maybe s -> Expr s a -> Maybe s -> Maybe s -> RecordField s a
    RecordField
            (Maybe s -> Expr s b -> Maybe s -> Maybe s -> RecordField s b)
    -> f (Maybe s)
    -> f (Expr s b -> Maybe s -> Maybe s -> RecordField s b)
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Maybe s -> f (Maybe s)
    forall a. a -> f a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure Maybe s
    s0
            f (Expr s b -> Maybe s -> Maybe s -> RecordField s b)
    -> f (Expr s b) -> f (Maybe s -> Maybe s -> RecordField s b)
    forall a b. f (a -> b) -> f a -> f b
    forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
    <*> Expr s a -> f (Expr s b)
    f Expr s a
    e
            f (Maybe s -> Maybe s -> RecordField s b)
    -> f (Maybe s) -> f (Maybe s -> RecordField s b)
    forall a b. f (a -> b) -> f a -> f b
    forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
    <*> Maybe s -> f (Maybe s)
    forall a. a -> f a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure Maybe s
    s1
            f (Maybe s -> RecordField s b)
    -> f (Maybe s) -> f (RecordField s b)
    forall a b. f (a -> b) -> f a -> f b
    forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
    <*> Maybe s -> f (Maybe s)
    forall a. a -> f a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure Maybe s
    s2
    {-# INLINABLE recordFieldExprs #-}