packages feed

spectacle-1.0.0: src/Language/Spectacle/Interaction.hs

{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE OverloadedStrings #-}

-- | CLI interaction.
--
-- @since 1.0.0
module Language.Spectacle.Interaction
  ( -- * CLI
    interaction,
    handleInteraction,
  )
where

import Control.Monad (when)
import Control.Monad.IO.Class (liftIO)
import Control.Monad.Reader (asks)
import Data.Either (isRight)
import Data.Hashable (Hashable)
import Data.Text.Prettyprint.Doc (line)

import Data.Functor.Tree (Tree)
import Data.Type.Rec (HasDict)
import Data.World (World)
import Language.Spectacle.Interaction.CLI (CLI, ContextCLI (ctxOpts), cliPutDoc, cliResultDoc, runCLI)
import Language.Spectacle.Interaction.Diagram (diagramFull, runDiagram)
import Language.Spectacle.Interaction.Options (OptsCLI (optsLogGraph, optsOnlyTrace))
import qualified Language.Spectacle.Interaction.Options as Opts
import Language.Spectacle.Interaction.Paths (toPointSet)
import Language.Spectacle.Model (modelcheck, modeltrace)
import Language.Spectacle.Model.ModelError (ModelError, ppModelError)
import Language.Spectacle.Specification (Specification)

-- ---------------------------------------------------------------------------------------------------------------------

interaction :: (HasDict Hashable ctx, HasDict Show ctx) => Specification ctx acts form -> IO ()
interaction spec = do
  opts <- Opts.execOptsCLI
  result <-
    if optsOnlyTrace opts
      then modeltrace spec
      else modelcheck spec

  runCLI (handleInteraction result) opts

handleInteraction :: HasDict Show ctx => Either (ModelError ctx) [Tree (World ctx)] -> CLI ()
handleInteraction result =
  let status = isRight result
   in case result of
        Left err -> do
          cliPutDoc =<< cliResultDoc status
          cliPutDoc (ppModelError err)
          cliPutDoc line
        Right trees -> do
          isLogging <- asks (optsLogGraph . ctxOpts)
          when isLogging do
            let pointSet = foldMap toPointSet trees
            diagramDoc <- liftIO (runDiagram $ diagramFull pointSet)
            cliPutDoc (diagramDoc <> line)
          cliPutDoc =<< cliResultDoc status