content: {-|
  Copyright:    (C) 2022 Google Inc.
  License:      BSD2 (see the file LICENSE)
  Maintainer:   QBayLogic B.V. <devops@qbaylogic.com>
  -}
  
  {-# LANGUAGE TypeFamilies #-}
  
  module Clash.FFI.VPI.Error.State
    ( ErrorState(..)
    , UnknownErrorState(..)
    ) where
  
  import           Control.Exception (Exception, throwIO)
  import           Foreign.C.Types (CInt)
  import           GHC.Stack (CallStack, callStack, prettyCallStack)
  
  import           Clash.FFI.View (CRepr, Receive(..))
  
  -- | The state of the simulator when an error occurred. This specifies whether
  -- the error occurred before a simulation started, while in a PLI/VPI call, or
  -- while the simulation was running.
  --
  data ErrorState
    = CompileError
    | PliError
    | RunError
    deriving stock (Eq, Show)
  
  -- | An exception thrown when decoding an error state if an invalid value is
  -- given for the C enum that specifies the constructor of 'ErrorState'.
  --
  data UnknownErrorState
    = UnknownErrorState CInt CallStack
    deriving anyclass (Exception)
  
  instance Show UnknownErrorState where
    show = \case
      UnknownErrorState x c -> mconcat
        [ "Unknown error state: "
        , show x
        , "\n"
        , prettyCallStack c
        ]
  
  type instance CRepr ErrorState = CInt
  
  instance Receive ErrorState where
    receive = \case
      1 -> pure CompileError
      2 -> pure PliError
      3 -> pure RunError
      n -> throwIO $ UnknownErrorState n callStack
  