    {-# LANGUAGE OverloadedStrings #-}

    -- | This module contains the implementation of the @dhall hash@ subcommand

    module Dhall.Hash
        ( -- * Hash
          hash
        ) where

    import Dhall.Binary (StandardVersion)
    import Dhall.Parser (exprFromText)
    import Dhall.Import (hashExpressionToCode, standardVersion)
    import Lens.Family (set)

    import qualified Control.Monad.Trans.State.Strict as State
    import qualified Control.Exception
    import qualified Dhall.Core
    import qualified Dhall.Import
    import qualified Dhall.TypeCheck
    import qualified Data.Text.IO

    -- | Implementation of the @dhall hash@ subcommand
    hash :: StandardVersion -> IO ()
    hash _standardVersion = do
        inText <- Data.Text.IO.getContents

        parsedExpression <- case exprFromText "(stdin)" inText of
            Left  exception        -> Control.Exception.throwIO exception
            Right parsedExpression -> return parsedExpression

        let status =
                set standardVersion _standardVersion (Dhall.Import.emptyStatus ".")

        resolvedExpression <- State.evalStateT (Dhall.Import.loadWith parsedExpression) status

        case Dhall.TypeCheck.typeOf resolvedExpression of
            Left  exception -> Control.Exception.throwIO exception
            Right _         -> return ()

        let normalizedExpression =
                Dhall.Core.alphaNormalize (Dhall.Core.normalize resolvedExpression)

        Data.Text.IO.putStrLn
            (hashExpressionToCode _standardVersion normalizedExpression)