{-# OPTIONS_GHC -O0 #-}
{-# OPTIONS_GHC -fno-warn-orphans #-}

{-| A separate module for JSON instances, so that we can stick @-O0@ on it and avoid spending
a lot of time optimizing loads of Core whose performance doesn't matter. -}
module PlutusCore.Evaluation.Machine.CostingFun.JSON () where

import Data.Aeson
import Data.List (stripPrefix)
import Data.Maybe (fromMaybe)

import PlutusCore.Evaluation.Machine.CostingFun.Core

-- | Drop a prefix from a name, leaving the name unchanged if the prefix doesn't match.
dropPrefix :: String -> String -> String
dropPrefix :: String -> String -> String
dropPrefix String
prefix String
s = String -> Maybe String -> String
forall a. a -> Maybe a -> a
fromMaybe String
s (String -> String -> Maybe String
forall a. Eq a => [a] -> [a] -> Maybe [a]
stripPrefix String
prefix String
s)

{-| JSON options for the record types describing the shapes of costing functions: drop the
type-name prefix from the field names and convert the rest to snake_case. -}
modelOptions :: String -> Options
modelOptions :: String -> Options
modelOptions String
prefix =
  Options
defaultOptions {fieldLabelModifier = camelTo2 '_' . dropPrefix prefix}

{-| JSON options for the sum types of costing function shapes.
Without 'tagSingleConstructors' the format can change unexpectedly if
you add/remove constructors because you don't get the tags if there's
only one constructor but you do if there's more than one. -}
modelArgumentOptions :: String -> Options
modelArgumentOptions :: String -> Options
modelArgumentOptions String
prefix =
  Options
defaultOptions
    { constructorTagModifier = camelTo2 '_' . dropPrefix prefix
    , sumEncoding = TaggedObject "type" "arguments"
    , tagSingleConstructors = True
    }

instance FromJSON model => FromJSON (CostingFun model) where
  parseJSON :: Value -> Parser (CostingFun model)
parseJSON = Options -> Value -> Parser (CostingFun model)
forall a.
(Generic a, GFromJSON Zero (Rep a)) =>
Options -> Value -> Parser a
genericParseJSON (String -> Options
modelOptions String
"costingFun")

instance ToJSON model => ToJSON (CostingFun model) where
  toJSON :: CostingFun model -> Value
toJSON = Options -> CostingFun model -> Value
forall a.
(Generic a, GToJSON' Value Zero (Rep a)) =>
Options -> a -> Value
genericToJSON (String -> Options
modelOptions String
"costingFun")
  toEncoding :: CostingFun model -> Encoding
toEncoding = Options -> CostingFun model -> Encoding
forall a.
(Generic a, GToJSON' Encoding Zero (Rep a)) =>
Options -> a -> Encoding
genericToEncoding (String -> Options
modelOptions String
"costingFun")

deriving newtype instance FromJSON Intercept
deriving newtype instance ToJSON Intercept
deriving newtype instance FromJSON Slope
deriving newtype instance ToJSON Slope
deriving newtype instance FromJSON Coefficient0
deriving newtype instance ToJSON Coefficient0
deriving newtype instance FromJSON Coefficient1
deriving newtype instance ToJSON Coefficient1
deriving newtype instance FromJSON Coefficient2
deriving newtype instance ToJSON Coefficient2
deriving newtype instance FromJSON Coefficient00
deriving newtype instance ToJSON Coefficient00
deriving newtype instance FromJSON Coefficient10
deriving newtype instance ToJSON Coefficient10
deriving newtype instance FromJSON Coefficient01
deriving newtype instance ToJSON Coefficient01
deriving newtype instance FromJSON Coefficient20
deriving newtype instance ToJSON Coefficient20
deriving newtype instance FromJSON Coefficient11
deriving newtype instance ToJSON Coefficient11
deriving newtype instance FromJSON Coefficient02
deriving newtype instance ToJSON Coefficient02
deriving newtype instance FromJSON Coefficient12
deriving newtype instance ToJSON Coefficient12

instance FromJSON ModelOneArgument where
  parseJSON :: Value -> Parser ModelOneArgument
parseJSON = Options -> Value -> Parser ModelOneArgument
forall a.
(Generic a, GFromJSON Zero (Rep a)) =>
Options -> Value -> Parser a
genericParseJSON (String -> Options
modelArgumentOptions String
"ModelOneArgument")

instance ToJSON ModelOneArgument where
  toJSON :: ModelOneArgument -> Value
toJSON = Options -> ModelOneArgument -> Value
forall a.
(Generic a, GToJSON' Value Zero (Rep a)) =>
Options -> a -> Value
genericToJSON (String -> Options
modelArgumentOptions String
"ModelOneArgument")
  toEncoding :: ModelOneArgument -> Encoding
toEncoding = Options -> ModelOneArgument -> Encoding
forall a.
(Generic a, GToJSON' Encoding Zero (Rep a)) =>
Options -> a -> Encoding
genericToEncoding (String -> Options
modelArgumentOptions String
"ModelOneArgument")

instance FromJSON ModelTwoArguments where
  parseJSON :: Value -> Parser ModelTwoArguments
parseJSON = Options -> Value -> Parser ModelTwoArguments
forall a.
(Generic a, GFromJSON Zero (Rep a)) =>
Options -> Value -> Parser a
genericParseJSON (String -> Options
modelArgumentOptions String
"ModelTwoArguments")

instance ToJSON ModelTwoArguments where
  toJSON :: ModelTwoArguments -> Value
toJSON = Options -> ModelTwoArguments -> Value
forall a.
(Generic a, GToJSON' Value Zero (Rep a)) =>
Options -> a -> Value
genericToJSON (String -> Options
modelArgumentOptions String
"ModelTwoArguments")
  toEncoding :: ModelTwoArguments -> Encoding
toEncoding = Options -> ModelTwoArguments -> Encoding
forall a.
(Generic a, GToJSON' Encoding Zero (Rep a)) =>
Options -> a -> Encoding
genericToEncoding (String -> Options
modelArgumentOptions String
"ModelTwoArguments")

instance FromJSON ModelThreeArguments where
  parseJSON :: Value -> Parser ModelThreeArguments
parseJSON = Options -> Value -> Parser ModelThreeArguments
forall a.
(Generic a, GFromJSON Zero (Rep a)) =>
Options -> Value -> Parser a
genericParseJSON (String -> Options
modelArgumentOptions String
"ModelThreeArguments")

instance ToJSON ModelThreeArguments where
  toJSON :: ModelThreeArguments -> Value
toJSON = Options -> ModelThreeArguments -> Value
forall a.
(Generic a, GToJSON' Value Zero (Rep a)) =>
Options -> a -> Value
genericToJSON (String -> Options
modelArgumentOptions String
"ModelThreeArguments")
  toEncoding :: ModelThreeArguments -> Encoding
toEncoding = Options -> ModelThreeArguments -> Encoding
forall a.
(Generic a, GToJSON' Encoding Zero (Rep a)) =>
Options -> a -> Encoding
genericToEncoding (String -> Options
modelArgumentOptions String
"ModelThreeArguments")

instance FromJSON ModelFourArguments where
  parseJSON :: Value -> Parser ModelFourArguments
parseJSON = Options -> Value -> Parser ModelFourArguments
forall a.
(Generic a, GFromJSON Zero (Rep a)) =>
Options -> Value -> Parser a
genericParseJSON (String -> Options
modelArgumentOptions String
"ModelFourArguments")

instance ToJSON ModelFourArguments where
  toJSON :: ModelFourArguments -> Value
toJSON = Options -> ModelFourArguments -> Value
forall a.
(Generic a, GToJSON' Value Zero (Rep a)) =>
Options -> a -> Value
genericToJSON (String -> Options
modelArgumentOptions String
"ModelFourArguments")
  toEncoding :: ModelFourArguments -> Encoding
toEncoding = Options -> ModelFourArguments -> Encoding
forall a.
(Generic a, GToJSON' Encoding Zero (Rep a)) =>
Options -> a -> Encoding
genericToEncoding (String -> Options
modelArgumentOptions String
"ModelFourArguments")

instance FromJSON ModelFiveArguments where
  parseJSON :: Value -> Parser ModelFiveArguments
parseJSON = Options -> Value -> Parser ModelFiveArguments
forall a.
(Generic a, GFromJSON Zero (Rep a)) =>
Options -> Value -> Parser a
genericParseJSON (String -> Options
modelArgumentOptions String
"ModelFiveArguments")

instance ToJSON ModelFiveArguments where
  toJSON :: ModelFiveArguments -> Value
toJSON = Options -> ModelFiveArguments -> Value
forall a.
(Generic a, GToJSON' Value Zero (Rep a)) =>
Options -> a -> Value
genericToJSON (String -> Options
modelArgumentOptions String
"ModelFiveArguments")
  toEncoding :: ModelFiveArguments -> Encoding
toEncoding = Options -> ModelFiveArguments -> Encoding
forall a.
(Generic a, GToJSON' Encoding Zero (Rep a)) =>
Options -> a -> Encoding
genericToEncoding (String -> Options
modelArgumentOptions String
"ModelFiveArguments")

instance FromJSON ModelSixArguments where
  parseJSON :: Value -> Parser ModelSixArguments
parseJSON = Options -> Value -> Parser ModelSixArguments
forall a.
(Generic a, GFromJSON Zero (Rep a)) =>
Options -> Value -> Parser a
genericParseJSON (String -> Options
modelArgumentOptions String
"ModelSixArguments")

instance ToJSON ModelSixArguments where
  toJSON :: ModelSixArguments -> Value
toJSON = Options -> ModelSixArguments -> Value
forall a.
(Generic a, GToJSON' Value Zero (Rep a)) =>
Options -> a -> Value
genericToJSON (String -> Options
modelArgumentOptions String
"ModelSixArguments")
  toEncoding :: ModelSixArguments -> Encoding
toEncoding = Options -> ModelSixArguments -> Encoding
forall a.
(Generic a, GToJSON' Encoding Zero (Rep a)) =>
Options -> a -> Encoding
genericToEncoding (String -> Options
modelArgumentOptions String
"ModelSixArguments")

instance FromJSON ModelSubtractedSizes where
  parseJSON :: Value -> Parser ModelSubtractedSizes
parseJSON = Options -> Value -> Parser ModelSubtractedSizes
forall a.
(Generic a, GFromJSON Zero (Rep a)) =>
Options -> Value -> Parser a
genericParseJSON (String -> Options
modelOptions String
"modelSubtractedSizes")

instance ToJSON ModelSubtractedSizes where
  toJSON :: ModelSubtractedSizes -> Value
toJSON = Options -> ModelSubtractedSizes -> Value
forall a.
(Generic a, GToJSON' Value Zero (Rep a)) =>
Options -> a -> Value
genericToJSON (String -> Options
modelOptions String
"modelSubtractedSizes")
  toEncoding :: ModelSubtractedSizes -> Encoding
toEncoding = Options -> ModelSubtractedSizes -> Encoding
forall a.
(Generic a, GToJSON' Encoding Zero (Rep a)) =>
Options -> a -> Encoding
genericToEncoding (String -> Options
modelOptions String
"modelSubtractedSizes")

instance FromJSON OneVariableLinearFunction where
  parseJSON :: Value -> Parser OneVariableLinearFunction
parseJSON = Options -> Value -> Parser OneVariableLinearFunction
forall a.
(Generic a, GFromJSON Zero (Rep a)) =>
Options -> Value -> Parser a
genericParseJSON (String -> Options
modelOptions String
"oneVariableLinearFunction")

instance ToJSON OneVariableLinearFunction where
  toJSON :: OneVariableLinearFunction -> Value
toJSON = Options -> OneVariableLinearFunction -> Value
forall a.
(Generic a, GToJSON' Value Zero (Rep a)) =>
Options -> a -> Value
genericToJSON (String -> Options
modelOptions String
"oneVariableLinearFunction")
  toEncoding :: OneVariableLinearFunction -> Encoding
toEncoding = Options -> OneVariableLinearFunction -> Encoding
forall a.
(Generic a, GToJSON' Encoding Zero (Rep a)) =>
Options -> a -> Encoding
genericToEncoding (String -> Options
modelOptions String
"oneVariableLinearFunction")

instance FromJSON TwoVariableLinearFunction where
  parseJSON :: Value -> Parser TwoVariableLinearFunction
parseJSON = Options -> Value -> Parser TwoVariableLinearFunction
forall a.
(Generic a, GFromJSON Zero (Rep a)) =>
Options -> Value -> Parser a
genericParseJSON (String -> Options
modelOptions String
"twoVariableLinearFunction")

instance ToJSON TwoVariableLinearFunction where
  toJSON :: TwoVariableLinearFunction -> Value
toJSON = Options -> TwoVariableLinearFunction -> Value
forall a.
(Generic a, GToJSON' Value Zero (Rep a)) =>
Options -> a -> Value
genericToJSON (String -> Options
modelOptions String
"twoVariableLinearFunction")
  toEncoding :: TwoVariableLinearFunction -> Encoding
toEncoding = Options -> TwoVariableLinearFunction -> Encoding
forall a.
(Generic a, GToJSON' Encoding Zero (Rep a)) =>
Options -> a -> Encoding
genericToEncoding (String -> Options
modelOptions String
"twoVariableLinearFunction")

instance FromJSON OneVariableQuadraticFunction where
  parseJSON :: Value -> Parser OneVariableQuadraticFunction
parseJSON = Options -> Value -> Parser OneVariableQuadraticFunction
forall a.
(Generic a, GFromJSON Zero (Rep a)) =>
Options -> Value -> Parser a
genericParseJSON (String -> Options
modelOptions String
"oneVariableQuadraticFunction")

instance ToJSON OneVariableQuadraticFunction where
  toJSON :: OneVariableQuadraticFunction -> Value
toJSON = Options -> OneVariableQuadraticFunction -> Value
forall a.
(Generic a, GToJSON' Value Zero (Rep a)) =>
Options -> a -> Value
genericToJSON (String -> Options
modelOptions String
"oneVariableQuadraticFunction")
  toEncoding :: OneVariableQuadraticFunction -> Encoding
toEncoding = Options -> OneVariableQuadraticFunction -> Encoding
forall a.
(Generic a, GToJSON' Encoding Zero (Rep a)) =>
Options -> a -> Encoding
genericToEncoding (String -> Options
modelOptions String
"oneVariableQuadraticFunction")

instance FromJSON TwoVariableQuadraticFunction where
  parseJSON :: Value -> Parser TwoVariableQuadraticFunction
parseJSON = Options -> Value -> Parser TwoVariableQuadraticFunction
forall a.
(Generic a, GFromJSON Zero (Rep a)) =>
Options -> Value -> Parser a
genericParseJSON (String -> Options
modelOptions String
"twoVariableQuadraticFunction")

instance ToJSON TwoVariableQuadraticFunction where
  toJSON :: TwoVariableQuadraticFunction -> Value
toJSON = Options -> TwoVariableQuadraticFunction -> Value
forall a.
(Generic a, GToJSON' Value Zero (Rep a)) =>
Options -> a -> Value
genericToJSON (String -> Options
modelOptions String
"twoVariableQuadraticFunction")
  toEncoding :: TwoVariableQuadraticFunction -> Encoding
toEncoding = Options -> TwoVariableQuadraticFunction -> Encoding
forall a.
(Generic a, GToJSON' Encoding Zero (Rep a)) =>
Options -> a -> Encoding
genericToEncoding (String -> Options
modelOptions String
"twoVariableQuadraticFunction")

instance FromJSON ExpModCostingFunction where
  parseJSON :: Value -> Parser ExpModCostingFunction
parseJSON = Options -> Value -> Parser ExpModCostingFunction
forall a.
(Generic a, GFromJSON Zero (Rep a)) =>
Options -> Value -> Parser a
genericParseJSON (String -> Options
modelOptions String
"expModCostingFunction")

instance ToJSON ExpModCostingFunction where
  toJSON :: ExpModCostingFunction -> Value
toJSON = Options -> ExpModCostingFunction -> Value
forall a.
(Generic a, GToJSON' Value Zero (Rep a)) =>
Options -> a -> Value
genericToJSON (String -> Options
modelOptions String
"expModCostingFunction")
  toEncoding :: ExpModCostingFunction -> Encoding
toEncoding = Options -> ExpModCostingFunction -> Encoding
forall a.
(Generic a, GToJSON' Encoding Zero (Rep a)) =>
Options -> a -> Encoding
genericToEncoding (String -> Options
modelOptions String
"expModCostingFunction")

instance FromJSON ModelConstantOrOneArgument where
  parseJSON :: Value -> Parser ModelConstantOrOneArgument
parseJSON = Options -> Value -> Parser ModelConstantOrOneArgument
forall a.
(Generic a, GFromJSON Zero (Rep a)) =>
Options -> Value -> Parser a
genericParseJSON (String -> Options
modelOptions String
"modelConstantOrOneArgument")

instance ToJSON ModelConstantOrOneArgument where
  toJSON :: ModelConstantOrOneArgument -> Value
toJSON = Options -> ModelConstantOrOneArgument -> Value
forall a.
(Generic a, GToJSON' Value Zero (Rep a)) =>
Options -> a -> Value
genericToJSON (String -> Options
modelOptions String
"modelConstantOrOneArgument")
  toEncoding :: ModelConstantOrOneArgument -> Encoding
toEncoding = Options -> ModelConstantOrOneArgument -> Encoding
forall a.
(Generic a, GToJSON' Encoding Zero (Rep a)) =>
Options -> a -> Encoding
genericToEncoding (String -> Options
modelOptions String
"modelConstantOrOneArgument")

instance FromJSON ModelConstantOrTwoArguments where
  parseJSON :: Value -> Parser ModelConstantOrTwoArguments
parseJSON = Options -> Value -> Parser ModelConstantOrTwoArguments
forall a.
(Generic a, GFromJSON Zero (Rep a)) =>
Options -> Value -> Parser a
genericParseJSON (String -> Options
modelOptions String
"modelConstantOrTwoArguments")

instance ToJSON ModelConstantOrTwoArguments where
  toJSON :: ModelConstantOrTwoArguments -> Value
toJSON = Options -> ModelConstantOrTwoArguments -> Value
forall a.
(Generic a, GToJSON' Value Zero (Rep a)) =>
Options -> a -> Value
genericToJSON (String -> Options
modelOptions String
"modelConstantOrTwoArguments")
  toEncoding :: ModelConstantOrTwoArguments -> Encoding
toEncoding = Options -> ModelConstantOrTwoArguments -> Encoding
forall a.
(Generic a, GToJSON' Encoding Zero (Rep a)) =>
Options -> a -> Encoding
genericToEncoding (String -> Options
modelOptions String
"modelConstantOrTwoArguments")

-- See Note [Backward compatibility for costing functions] for ModelConstantOrLinear
instance FromJSON ModelConstantOrLinear where
  parseJSON :: Value -> Parser ModelConstantOrLinear
parseJSON = Options -> Value -> Parser ModelConstantOrLinear
forall a.
(Generic a, GFromJSON Zero (Rep a)) =>
Options -> Value -> Parser a
genericParseJSON (String -> Options
modelOptions String
"modelConstantOrLinear")

instance ToJSON ModelConstantOrLinear where
  toJSON :: ModelConstantOrLinear -> Value
toJSON = Options -> ModelConstantOrLinear -> Value
forall a.
(Generic a, GToJSON' Value Zero (Rep a)) =>
Options -> a -> Value
genericToJSON (String -> Options
modelOptions String
"modelConstantOrLinear")
  toEncoding :: ModelConstantOrLinear -> Encoding
toEncoding = Options -> ModelConstantOrLinear -> Encoding
forall a.
(Generic a, GToJSON' Encoding Zero (Rep a)) =>
Options -> a -> Encoding
genericToEncoding (String -> Options
modelOptions String
"modelConstantOrLinear")

instance FromJSON TwoVariableWithInteractionFunction where
  parseJSON :: Value -> Parser TwoVariableWithInteractionFunction
parseJSON = Options -> Value -> Parser TwoVariableWithInteractionFunction
forall a.
(Generic a, GFromJSON Zero (Rep a)) =>
Options -> Value -> Parser a
genericParseJSON (String -> Options
modelOptions String
"twoVariableWithInteractionFunction")

instance ToJSON TwoVariableWithInteractionFunction where
  toJSON :: TwoVariableWithInteractionFunction -> Value
toJSON = Options -> TwoVariableWithInteractionFunction -> Value
forall a.
(Generic a, GToJSON' Value Zero (Rep a)) =>
Options -> a -> Value
genericToJSON (String -> Options
modelOptions String
"twoVariableWithInteractionFunction")
  toEncoding :: TwoVariableWithInteractionFunction -> Encoding
toEncoding = Options -> TwoVariableWithInteractionFunction -> Encoding
forall a.
(Generic a, GToJSON' Encoding Zero (Rep a)) =>
Options -> a -> Encoding
genericToEncoding (String -> Options
modelOptions String
"twoVariableWithInteractionFunction")