    {-|
      Copyright  :  (C) 2012-2016, University of Twente,
                             2017, Google Inc.
                             2022, QBayLogic B.V.
      License    :  BSD2 (see the file LICENSE)
      Maintainer :  QBayLogic B.V. <devops@qbaylogic.com>

      Types used in Normalize modules
    -}

    {-# LANGUAGE TemplateHaskell #-}

    module Clash.Normalize.Types where

    import qualified Control.Lens as Lens
    import Control.Monad.State.Strict (State)
    import Data.Map                   (Map)
    import Data.Set                   (Set)
    import Data.Text                  (Text)

    import Clash.Core.Term        (Term)
    import Clash.Core.Type        (Type)
    import Clash.Core.Var         (Id)
    import Clash.Core.VarEnv      (VarEnv)
    import Clash.Driver.Types     (BindingMap)
    import Clash.Rewrite.Types    (Rewrite, RewriteMonad)

    -- | State of the 'NormalizeMonad'
    data NormalizeState
      = NormalizeState
      { NormalizeState -> BindingMap
    _normalized          :: BindingMap
      -- ^ Global binders
      , NormalizeState -> Map (Id, Int, Either Term Type) Id
    _specialisationCache :: Map (Id,Int,Either Term Type) Id
      -- ^ Cache of previously specialized functions:
      --
      -- * Key: (name of the original function, argument position, specialized term/type)
      --
      -- * Elem: (name of specialized function,type of specialized function)
      , NormalizeState -> VarEnv Int
    _specialisationHistory :: VarEnv Int
      -- ^ Cache of how many times a function was specialized
      , NormalizeState -> VarEnv (VarEnv Int)
    _inlineHistory   :: VarEnv (VarEnv Int)
      -- ^ Cache of function where inlining took place:
      --
      -- * Key: function where inlining took place
      --
      -- * Elem: (functions which were inlined, number of times inlined)
      , NormalizeState -> Map Text (Set Int)
    _primitiveArgs :: Map Text (Set Int)
      -- ^ Cache for looking up constantness of blackbox arguments
      , NormalizeState -> VarEnv Bool
    _recursiveComponents :: VarEnv Bool
      -- ^ Map telling whether a components is recursively defined.
      --
      -- NB: there are only no mutually-recursive component, only self-recursive
      -- ones.
      }

    Lens.makeLenses ''NormalizeState

    -- | State monad that stores specialisation and inlining information
    type NormalizeMonad = State NormalizeState

    -- | RewriteSession with extra Normalisation information
    type NormalizeSession = RewriteMonad NormalizeState

    -- | A 'Transform' action in the context of the 'RewriteMonad' and 'NormalizeMonad'
    type NormRewrite = Rewrite NormalizeState

    -- | Description of a @Term@ in terms of the type "components" the @Term@ has.
    --
    -- Is used as a performance/size metric.
    data TermClassification
      = TermClassification
      { TermClassification -> Int
    _function   :: !Int -- ^ Number of functions
      , TermClassification -> Int
    _primitive  :: !Int -- ^ Number of primitives
      , TermClassification -> Int
    _selection  :: !Int -- ^ Number of selections/multiplexers
      }
      deriving Int -> TermClassification -> ShowS
    [TermClassification] -> ShowS
    TermClassification -> String
    (Int -> TermClassification -> ShowS)
    -> (TermClassification -> String)
    -> ([TermClassification] -> ShowS)
    -> Show TermClassification
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> TermClassification -> ShowS
    showsPrec :: Int -> TermClassification -> ShowS
    $cshow :: TermClassification -> String
    show :: TermClassification -> String
    $cshowList :: [TermClassification] -> ShowS
    showList :: [TermClassification] -> ShowS
    Show

    Lens.makeLenses ''TermClassification