{-# LANGUAGE DataKinds         #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE StrictData        #-}

module UntypedPlutusCore.Evaluation.Machine.Cek.CekMachineCosts
    ( CekMachineCosts(..)
    , cekMachineCostsPrefix
    , unitCekMachineCosts
    )
where

import PlutusCore.Evaluation.Machine.ExBudget

import Data.Text qualified as Text
import Deriving.Aeson
import Language.Haskell.TH.Syntax (Lift)


-- | The prefix of the field names in the CekMachineCosts type, used for
-- extracting the CekMachineCosts component of the ledger's cost model
-- parameters. See Note [Cost model parameters] in CostModelInterface.
cekMachineCostsPrefix :: Text.Text
cekMachineCostsPrefix :: Text
cekMachineCostsPrefix = Text
"cek"

-- | Costs for evaluating AST nodes.  Times should be specified in picoseconds, memory sizes in bytes.

data CekMachineCosts =
    CekMachineCosts {
      CekMachineCosts -> ExBudget
cekStartupCost :: ExBudget  -- General overhead
    , CekMachineCosts -> ExBudget
cekVarCost     :: ExBudget
    , CekMachineCosts -> ExBudget
cekConstCost   :: ExBudget
    , CekMachineCosts -> ExBudget
cekLamCost     :: ExBudget
    , CekMachineCosts -> ExBudget
cekDelayCost   :: ExBudget
    , CekMachineCosts -> ExBudget
cekForceCost   :: ExBudget
    , CekMachineCosts -> ExBudget
cekApplyCost   :: ExBudget
    , CekMachineCosts -> ExBudget
cekBuiltinCost :: ExBudget
    -- ^ Just the cost of evaluating a Builtin node, not the builtin itself.
    -- There's no entry for Error since we'll be exiting anyway; also, what would
    -- happen if calling 'Error' caused the budget to be exceeded?
    }
    deriving (CekMachineCosts -> CekMachineCosts -> Bool
(CekMachineCosts -> CekMachineCosts -> Bool)
-> (CekMachineCosts -> CekMachineCosts -> Bool)
-> Eq CekMachineCosts
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: CekMachineCosts -> CekMachineCosts -> Bool
$c/= :: CekMachineCosts -> CekMachineCosts -> Bool
== :: CekMachineCosts -> CekMachineCosts -> Bool
$c== :: CekMachineCosts -> CekMachineCosts -> Bool
Eq, Int -> CekMachineCosts -> ShowS
[CekMachineCosts] -> ShowS
CekMachineCosts -> String
(Int -> CekMachineCosts -> ShowS)
-> (CekMachineCosts -> String)
-> ([CekMachineCosts] -> ShowS)
-> Show CekMachineCosts
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [CekMachineCosts] -> ShowS
$cshowList :: [CekMachineCosts] -> ShowS
show :: CekMachineCosts -> String
$cshow :: CekMachineCosts -> String
showsPrec :: Int -> CekMachineCosts -> ShowS
$cshowsPrec :: Int -> CekMachineCosts -> ShowS
Show, (forall x. CekMachineCosts -> Rep CekMachineCosts x)
-> (forall x. Rep CekMachineCosts x -> CekMachineCosts)
-> Generic CekMachineCosts
forall x. Rep CekMachineCosts x -> CekMachineCosts
forall x. CekMachineCosts -> Rep CekMachineCosts x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep CekMachineCosts x -> CekMachineCosts
$cfrom :: forall x. CekMachineCosts -> Rep CekMachineCosts x
Generic, CekMachineCosts -> Q Exp
CekMachineCosts -> Q (TExp CekMachineCosts)
(CekMachineCosts -> Q Exp)
-> (CekMachineCosts -> Q (TExp CekMachineCosts))
-> Lift CekMachineCosts
forall t. (t -> Q Exp) -> (t -> Q (TExp t)) -> Lift t
liftTyped :: CekMachineCosts -> Q (TExp CekMachineCosts)
$cliftTyped :: CekMachineCosts -> Q (TExp CekMachineCosts)
lift :: CekMachineCosts -> Q Exp
$clift :: CekMachineCosts -> Q Exp
Lift)
    deriving (Value -> Parser [CekMachineCosts]
Value -> Parser CekMachineCosts
(Value -> Parser CekMachineCosts)
-> (Value -> Parser [CekMachineCosts]) -> FromJSON CekMachineCosts
forall a.
(Value -> Parser a) -> (Value -> Parser [a]) -> FromJSON a
parseJSONList :: Value -> Parser [CekMachineCosts]
$cparseJSONList :: Value -> Parser [CekMachineCosts]
parseJSON :: Value -> Parser CekMachineCosts
$cparseJSON :: Value -> Parser CekMachineCosts
FromJSON, [CekMachineCosts] -> Encoding
[CekMachineCosts] -> Value
CekMachineCosts -> Encoding
CekMachineCosts -> Value
(CekMachineCosts -> Value)
-> (CekMachineCosts -> Encoding)
-> ([CekMachineCosts] -> Value)
-> ([CekMachineCosts] -> Encoding)
-> ToJSON CekMachineCosts
forall a.
(a -> Value)
-> (a -> Encoding)
-> ([a] -> Value)
-> ([a] -> Encoding)
-> ToJSON a
toEncodingList :: [CekMachineCosts] -> Encoding
$ctoEncodingList :: [CekMachineCosts] -> Encoding
toJSONList :: [CekMachineCosts] -> Value
$ctoJSONList :: [CekMachineCosts] -> Value
toEncoding :: CekMachineCosts -> Encoding
$ctoEncoding :: CekMachineCosts -> Encoding
toJSON :: CekMachineCosts -> Value
$ctoJSON :: CekMachineCosts -> Value
ToJSON) via CustomJSON '[FieldLabelModifier LowerIntialCharacter] CekMachineCosts

-- Charge a unit CPU cost for AST nodes: this allows us to count the number of
-- times each node type is evaluated.  For actual prediction/costing we use
-- a different version of CekMachineCosts: see ExBudgetingDefaults.defaultCekMachineCosts.
unitCekMachineCosts :: CekMachineCosts
unitCekMachineCosts :: CekMachineCosts
unitCekMachineCosts =
    CekMachineCosts :: ExBudget
-> ExBudget
-> ExBudget
-> ExBudget
-> ExBudget
-> ExBudget
-> ExBudget
-> ExBudget
-> CekMachineCosts
CekMachineCosts { cekStartupCost :: ExBudget
cekStartupCost = ExBudget
zeroCost
                    , cekVarCost :: ExBudget
cekVarCost     = ExBudget
unitCost
                    , cekConstCost :: ExBudget
cekConstCost   = ExBudget
unitCost
                    , cekLamCost :: ExBudget
cekLamCost     = ExBudget
unitCost
                    , cekDelayCost :: ExBudget
cekDelayCost   = ExBudget
unitCost
                    , cekForceCost :: ExBudget
cekForceCost   = ExBudget
unitCost
                    , cekApplyCost :: ExBudget
cekApplyCost   = ExBudget
unitCost
                    , cekBuiltinCost :: ExBudget
cekBuiltinCost = ExBudget
unitCost
                    }
        where
          zeroCost :: ExBudget
zeroCost = ExCPU -> ExMemory -> ExBudget
ExBudget ExCPU
0 ExMemory
0
          unitCost :: ExBudget
unitCost = ExCPU -> ExMemory -> ExBudget
ExBudget ExCPU
1 ExMemory
0