{-# LANGUAGE CPP                      #-}
{-# LANGUAGE DefaultSignatures        #-}
{-# LANGUAGE FlexibleInstances        #-}
{-# LANGUAGE FunctionalDependencies   #-}
{-# LANGUAGE StandaloneKindSignatures #-}
{-# LANGUAGE TypeFamilies             #-}
{-# LANGUAGE TypeOperators            #-}
{-# LANGUAGE UndecidableInstances     #-}
{-# OPTIONS_GHC -Wno-orphans #-}
{-# OPTIONS_GHC -fno-omit-interface-pragmas #-}
{-# OPTIONS_GHC -fno-specialise #-}
{-# LANGUAGE DerivingStrategies       #-}

module PlutusTx.Builtins.HasOpaque where

import Control.DeepSeq (NFData (..))
import PlutusCore.Pretty (Pretty (..))
import PlutusTx.Base (id, ($))
import PlutusTx.Bool (Bool (..))
import PlutusTx.Builtins.Internal (BuiltinBLS12_381_G1_Element, BuiltinBLS12_381_G2_Element,
                                   BuiltinBLS12_381_MlResult, BuiltinBool, BuiltinByteString (..),
                                   BuiltinData, BuiltinInteger, BuiltinList (..), BuiltinPair,
                                   BuiltinString (..), BuiltinUnit, caseList', chooseUnit, false,
                                   fst, ifThenElse, mkCons, mkPairData, snd, true, unitval)

import Codec.Serialise (Serialise)
import Data.ByteArray qualified as BA
import Data.ByteString.Base16 qualified as Base16
import Data.Hashable (Hashable (..))
import Data.Kind qualified as GHC
import Data.String (IsString (..))
import Data.Text qualified as Text
import Data.Text.Encoding qualified as Text
import Prelude qualified as Haskell
#if MIN_VERSION_base(4,20,0)
import Prelude (type (~))
#endif

-- plutus-tx-plugin has a special case for this function,
-- replacing its unfolding with something else.
stringToBuiltinByteString :: Haskell.String -> BuiltinByteString
stringToBuiltinByteString :: String -> BuiltinByteString
stringToBuiltinByteString String
str = ByteString -> BuiltinByteString
BuiltinByteString (String -> ByteString
forall a. IsString a => String -> a
fromString String
str)
{-# OPAQUE stringToBuiltinByteString #-}

-- plutus-tx-plugin has a special case for this function,
-- replacing its unfolding with something else.
stringToBuiltinString :: Haskell.String -> BuiltinString
stringToBuiltinString :: String -> BuiltinString
stringToBuiltinString String
str = Text -> BuiltinString
BuiltinString (String -> Text
Text.pack String
str)
{-# OPAQUE stringToBuiltinString #-}

instance IsString BuiltinByteString where
  -- Try and make sure the dictionary selector goes away, it's simpler to match on
  -- the application of 'stringToBuiltinByteString'
  fromString :: String -> BuiltinByteString
fromString = String -> BuiltinByteString
stringToBuiltinByteString
  {-# INLINE fromString #-}

-- We can't put this in `Builtins.hs`, since that force `O0` deliberately, which prevents
-- the unfoldings from going in. So we just stick it here. Fiddly.
instance IsString BuiltinString where
  -- Try and make sure the dictionary selector goes away, it's simpler to match on
  -- the application of 'stringToBuiltinString'
  fromString :: String -> BuiltinString
fromString = String -> BuiltinString
stringToBuiltinString
  {-# INLINE fromString #-}

{- Note [IsString instances and UTF-8 encoded string literals]

GHC Core encodes string literals in UTF-8 by default.
Plugin handles GHC Core expressions representing such literals specially:
in compile type it undoes the UTF-8 encoding when string literal is used to construct
a value of type 'BuiltinByteString' and preserves the UTF-8 encoding to construct 'BuiltinString'.

Sometimes we need to construct 'BuiltinByteString' values preserving the UTF-8 encoding, e.g. when
constructing a 'TokenName' value from a 'BuiltinByteString' value. In such cases we can use
'BuiltinByteStringUtf8' newtype:

  TokenName (unBuiltinByteStringUtf8 "привет")

-}
newtype BuiltinByteStringUtf8 = BuiltinByteStringUtf8
  { BuiltinByteStringUtf8 -> BuiltinByteString
unBuiltinByteStringUtf8 :: BuiltinByteString
  }
  deriving newtype
    ( BuiltinByteStringUtf8 -> BuiltinByteStringUtf8 -> Bool
(BuiltinByteStringUtf8 -> BuiltinByteStringUtf8 -> Bool)
-> (BuiltinByteStringUtf8 -> BuiltinByteStringUtf8 -> Bool)
-> Eq BuiltinByteStringUtf8
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: BuiltinByteStringUtf8 -> BuiltinByteStringUtf8 -> Bool
== :: BuiltinByteStringUtf8 -> BuiltinByteStringUtf8 -> Bool
$c/= :: BuiltinByteStringUtf8 -> BuiltinByteStringUtf8 -> Bool
/= :: BuiltinByteStringUtf8 -> BuiltinByteStringUtf8 -> Bool
Haskell.Eq
    , Eq BuiltinByteStringUtf8
Eq BuiltinByteStringUtf8 =>
(BuiltinByteStringUtf8 -> BuiltinByteStringUtf8 -> Ordering)
-> (BuiltinByteStringUtf8 -> BuiltinByteStringUtf8 -> Bool)
-> (BuiltinByteStringUtf8 -> BuiltinByteStringUtf8 -> Bool)
-> (BuiltinByteStringUtf8 -> BuiltinByteStringUtf8 -> Bool)
-> (BuiltinByteStringUtf8 -> BuiltinByteStringUtf8 -> Bool)
-> (BuiltinByteStringUtf8
    -> BuiltinByteStringUtf8 -> BuiltinByteStringUtf8)
-> (BuiltinByteStringUtf8
    -> BuiltinByteStringUtf8 -> BuiltinByteStringUtf8)
-> Ord BuiltinByteStringUtf8
BuiltinByteStringUtf8 -> BuiltinByteStringUtf8 -> Bool
BuiltinByteStringUtf8 -> BuiltinByteStringUtf8 -> Ordering
BuiltinByteStringUtf8
-> BuiltinByteStringUtf8 -> BuiltinByteStringUtf8
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: BuiltinByteStringUtf8 -> BuiltinByteStringUtf8 -> Ordering
compare :: BuiltinByteStringUtf8 -> BuiltinByteStringUtf8 -> Ordering
$c< :: BuiltinByteStringUtf8 -> BuiltinByteStringUtf8 -> Bool
< :: BuiltinByteStringUtf8 -> BuiltinByteStringUtf8 -> Bool
$c<= :: BuiltinByteStringUtf8 -> BuiltinByteStringUtf8 -> Bool
<= :: BuiltinByteStringUtf8 -> BuiltinByteStringUtf8 -> Bool
$c> :: BuiltinByteStringUtf8 -> BuiltinByteStringUtf8 -> Bool
> :: BuiltinByteStringUtf8 -> BuiltinByteStringUtf8 -> Bool
$c>= :: BuiltinByteStringUtf8 -> BuiltinByteStringUtf8 -> Bool
>= :: BuiltinByteStringUtf8 -> BuiltinByteStringUtf8 -> Bool
$cmax :: BuiltinByteStringUtf8
-> BuiltinByteStringUtf8 -> BuiltinByteStringUtf8
max :: BuiltinByteStringUtf8
-> BuiltinByteStringUtf8 -> BuiltinByteStringUtf8
$cmin :: BuiltinByteStringUtf8
-> BuiltinByteStringUtf8 -> BuiltinByteStringUtf8
min :: BuiltinByteStringUtf8
-> BuiltinByteStringUtf8 -> BuiltinByteStringUtf8
Haskell.Ord
    , Int -> BuiltinByteStringUtf8 -> ShowS
[BuiltinByteStringUtf8] -> ShowS
BuiltinByteStringUtf8 -> String
(Int -> BuiltinByteStringUtf8 -> ShowS)
-> (BuiltinByteStringUtf8 -> String)
-> ([BuiltinByteStringUtf8] -> ShowS)
-> Show BuiltinByteStringUtf8
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> BuiltinByteStringUtf8 -> ShowS
showsPrec :: Int -> BuiltinByteStringUtf8 -> ShowS
$cshow :: BuiltinByteStringUtf8 -> String
show :: BuiltinByteStringUtf8 -> String
$cshowList :: [BuiltinByteStringUtf8] -> ShowS
showList :: [BuiltinByteStringUtf8] -> ShowS
Haskell.Show
    , NonEmpty BuiltinByteStringUtf8 -> BuiltinByteStringUtf8
BuiltinByteStringUtf8
-> BuiltinByteStringUtf8 -> BuiltinByteStringUtf8
(BuiltinByteStringUtf8
 -> BuiltinByteStringUtf8 -> BuiltinByteStringUtf8)
-> (NonEmpty BuiltinByteStringUtf8 -> BuiltinByteStringUtf8)
-> (forall b.
    Integral b =>
    b -> BuiltinByteStringUtf8 -> BuiltinByteStringUtf8)
-> Semigroup BuiltinByteStringUtf8
forall b.
Integral b =>
b -> BuiltinByteStringUtf8 -> BuiltinByteStringUtf8
forall a.
(a -> a -> a)
-> (NonEmpty a -> a)
-> (forall b. Integral b => b -> a -> a)
-> Semigroup a
$c<> :: BuiltinByteStringUtf8
-> BuiltinByteStringUtf8 -> BuiltinByteStringUtf8
<> :: BuiltinByteStringUtf8
-> BuiltinByteStringUtf8 -> BuiltinByteStringUtf8
$csconcat :: NonEmpty BuiltinByteStringUtf8 -> BuiltinByteStringUtf8
sconcat :: NonEmpty BuiltinByteStringUtf8 -> BuiltinByteStringUtf8
$cstimes :: forall b.
Integral b =>
b -> BuiltinByteStringUtf8 -> BuiltinByteStringUtf8
stimes :: forall b.
Integral b =>
b -> BuiltinByteStringUtf8 -> BuiltinByteStringUtf8
Haskell.Semigroup
    , Semigroup BuiltinByteStringUtf8
BuiltinByteStringUtf8
Semigroup BuiltinByteStringUtf8 =>
BuiltinByteStringUtf8
-> (BuiltinByteStringUtf8
    -> BuiltinByteStringUtf8 -> BuiltinByteStringUtf8)
-> ([BuiltinByteStringUtf8] -> BuiltinByteStringUtf8)
-> Monoid BuiltinByteStringUtf8
[BuiltinByteStringUtf8] -> BuiltinByteStringUtf8
BuiltinByteStringUtf8
-> BuiltinByteStringUtf8 -> BuiltinByteStringUtf8
forall a.
Semigroup a =>
a -> (a -> a -> a) -> ([a] -> a) -> Monoid a
$cmempty :: BuiltinByteStringUtf8
mempty :: BuiltinByteStringUtf8
$cmappend :: BuiltinByteStringUtf8
-> BuiltinByteStringUtf8 -> BuiltinByteStringUtf8
mappend :: BuiltinByteStringUtf8
-> BuiltinByteStringUtf8 -> BuiltinByteStringUtf8
$cmconcat :: [BuiltinByteStringUtf8] -> BuiltinByteStringUtf8
mconcat :: [BuiltinByteStringUtf8] -> BuiltinByteStringUtf8
Haskell.Monoid
    , Eq BuiltinByteStringUtf8
Eq BuiltinByteStringUtf8 =>
(Int -> BuiltinByteStringUtf8 -> Int)
-> (BuiltinByteStringUtf8 -> Int) -> Hashable BuiltinByteStringUtf8
Int -> BuiltinByteStringUtf8 -> Int
BuiltinByteStringUtf8 -> Int
forall a. Eq a => (Int -> a -> Int) -> (a -> Int) -> Hashable a
$chashWithSalt :: Int -> BuiltinByteStringUtf8 -> Int
hashWithSalt :: Int -> BuiltinByteStringUtf8 -> Int
$chash :: BuiltinByteStringUtf8 -> Int
hash :: BuiltinByteStringUtf8 -> Int
Hashable
    , [BuiltinByteStringUtf8] -> Encoding
BuiltinByteStringUtf8 -> Encoding
(BuiltinByteStringUtf8 -> Encoding)
-> (forall s. Decoder s BuiltinByteStringUtf8)
-> ([BuiltinByteStringUtf8] -> Encoding)
-> (forall s. Decoder s [BuiltinByteStringUtf8])
-> Serialise BuiltinByteStringUtf8
forall s. Decoder s [BuiltinByteStringUtf8]
forall s. Decoder s BuiltinByteStringUtf8
forall a.
(a -> Encoding)
-> (forall s. Decoder s a)
-> ([a] -> Encoding)
-> (forall s. Decoder s [a])
-> Serialise a
$cencode :: BuiltinByteStringUtf8 -> Encoding
encode :: BuiltinByteStringUtf8 -> Encoding
$cdecode :: forall s. Decoder s BuiltinByteStringUtf8
decode :: forall s. Decoder s BuiltinByteStringUtf8
$cencodeList :: [BuiltinByteStringUtf8] -> Encoding
encodeList :: [BuiltinByteStringUtf8] -> Encoding
$cdecodeList :: forall s. Decoder s [BuiltinByteStringUtf8]
decodeList :: forall s. Decoder s [BuiltinByteStringUtf8]
Serialise
    , BuiltinByteStringUtf8 -> ()
(BuiltinByteStringUtf8 -> ()) -> NFData BuiltinByteStringUtf8
forall a. (a -> ()) -> NFData a
$crnf :: BuiltinByteStringUtf8 -> ()
rnf :: BuiltinByteStringUtf8 -> ()
NFData
    , BuiltinByteStringUtf8 -> Int
(BuiltinByteStringUtf8 -> Int)
-> (forall p a. BuiltinByteStringUtf8 -> (Ptr p -> IO a) -> IO a)
-> (forall p. BuiltinByteStringUtf8 -> Ptr p -> IO ())
-> ByteArrayAccess BuiltinByteStringUtf8
forall p. BuiltinByteStringUtf8 -> Ptr p -> IO ()
forall ba.
(ba -> Int)
-> (forall p a. ba -> (Ptr p -> IO a) -> IO a)
-> (forall p. ba -> Ptr p -> IO ())
-> ByteArrayAccess ba
forall p a. BuiltinByteStringUtf8 -> (Ptr p -> IO a) -> IO a
$clength :: BuiltinByteStringUtf8 -> Int
length :: BuiltinByteStringUtf8 -> Int
$cwithByteArray :: forall p a. BuiltinByteStringUtf8 -> (Ptr p -> IO a) -> IO a
withByteArray :: forall p a. BuiltinByteStringUtf8 -> (Ptr p -> IO a) -> IO a
$ccopyByteArrayToPtr :: forall p. BuiltinByteStringUtf8 -> Ptr p -> IO ()
copyByteArrayToPtr :: forall p. BuiltinByteStringUtf8 -> Ptr p -> IO ()
BA.ByteArrayAccess
    , Eq BuiltinByteStringUtf8
Ord BuiltinByteStringUtf8
Monoid BuiltinByteStringUtf8
ByteArrayAccess BuiltinByteStringUtf8
(Eq BuiltinByteStringUtf8, Ord BuiltinByteStringUtf8,
 Monoid BuiltinByteStringUtf8,
 ByteArrayAccess BuiltinByteStringUtf8) =>
(forall p a.
 Int -> (Ptr p -> IO a) -> IO (a, BuiltinByteStringUtf8))
-> ByteArray BuiltinByteStringUtf8
forall ba.
(Eq ba, Ord ba, Monoid ba, ByteArrayAccess ba) =>
(forall p a. Int -> (Ptr p -> IO a) -> IO (a, ba)) -> ByteArray ba
forall p a. Int -> (Ptr p -> IO a) -> IO (a, BuiltinByteStringUtf8)
$callocRet :: forall p a. Int -> (Ptr p -> IO a) -> IO (a, BuiltinByteStringUtf8)
allocRet :: forall p a. Int -> (Ptr p -> IO a) -> IO (a, BuiltinByteStringUtf8)
BA.ByteArray
    , (forall ann. BuiltinByteStringUtf8 -> Doc ann)
-> (forall ann. [BuiltinByteStringUtf8] -> Doc ann)
-> Pretty BuiltinByteStringUtf8
forall ann. [BuiltinByteStringUtf8] -> Doc ann
forall ann. BuiltinByteStringUtf8 -> Doc ann
forall a.
(forall ann. a -> Doc ann)
-> (forall ann. [a] -> Doc ann) -> Pretty a
$cpretty :: forall ann. BuiltinByteStringUtf8 -> Doc ann
pretty :: forall ann. BuiltinByteStringUtf8 -> Doc ann
$cprettyList :: forall ann. [BuiltinByteStringUtf8] -> Doc ann
prettyList :: forall ann. [BuiltinByteStringUtf8] -> Doc ann
Pretty
    )

instance IsString BuiltinByteStringUtf8 where
  fromString :: String -> BuiltinByteStringUtf8
fromString String
s = BuiltinByteString -> BuiltinByteStringUtf8
BuiltinByteStringUtf8 (String -> BuiltinByteString
stringToBuiltinByteStringUtf8 String
s)
  {-# INLINE fromString #-}

-- plutus-tx-plugin has a special case for this function,
-- replacing its unfolding with something else.
stringToBuiltinByteStringUtf8 :: Haskell.String -> BuiltinByteString
stringToBuiltinByteStringUtf8 :: String -> BuiltinByteString
stringToBuiltinByteStringUtf8 String
str = ByteString -> BuiltinByteString
BuiltinByteString (Text -> ByteString
Text.encodeUtf8 (String -> Text
Text.pack String
str))
{-# OPAQUE stringToBuiltinByteStringUtf8 #-}

newtype BuiltinByteStringHex = BuiltinByteStringHex
  { BuiltinByteStringHex -> BuiltinByteString
unBuiltinByteStringHex :: BuiltinByteString
  }
  deriving newtype
    ( BuiltinByteStringHex -> BuiltinByteStringHex -> Bool
(BuiltinByteStringHex -> BuiltinByteStringHex -> Bool)
-> (BuiltinByteStringHex -> BuiltinByteStringHex -> Bool)
-> Eq BuiltinByteStringHex
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: BuiltinByteStringHex -> BuiltinByteStringHex -> Bool
== :: BuiltinByteStringHex -> BuiltinByteStringHex -> Bool
$c/= :: BuiltinByteStringHex -> BuiltinByteStringHex -> Bool
/= :: BuiltinByteStringHex -> BuiltinByteStringHex -> Bool
Haskell.Eq
    , Eq BuiltinByteStringHex
Eq BuiltinByteStringHex =>
(BuiltinByteStringHex -> BuiltinByteStringHex -> Ordering)
-> (BuiltinByteStringHex -> BuiltinByteStringHex -> Bool)
-> (BuiltinByteStringHex -> BuiltinByteStringHex -> Bool)
-> (BuiltinByteStringHex -> BuiltinByteStringHex -> Bool)
-> (BuiltinByteStringHex -> BuiltinByteStringHex -> Bool)
-> (BuiltinByteStringHex
    -> BuiltinByteStringHex -> BuiltinByteStringHex)
-> (BuiltinByteStringHex
    -> BuiltinByteStringHex -> BuiltinByteStringHex)
-> Ord BuiltinByteStringHex
BuiltinByteStringHex -> BuiltinByteStringHex -> Bool
BuiltinByteStringHex -> BuiltinByteStringHex -> Ordering
BuiltinByteStringHex
-> BuiltinByteStringHex -> BuiltinByteStringHex
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: BuiltinByteStringHex -> BuiltinByteStringHex -> Ordering
compare :: BuiltinByteStringHex -> BuiltinByteStringHex -> Ordering
$c< :: BuiltinByteStringHex -> BuiltinByteStringHex -> Bool
< :: BuiltinByteStringHex -> BuiltinByteStringHex -> Bool
$c<= :: BuiltinByteStringHex -> BuiltinByteStringHex -> Bool
<= :: BuiltinByteStringHex -> BuiltinByteStringHex -> Bool
$c> :: BuiltinByteStringHex -> BuiltinByteStringHex -> Bool
> :: BuiltinByteStringHex -> BuiltinByteStringHex -> Bool
$c>= :: BuiltinByteStringHex -> BuiltinByteStringHex -> Bool
>= :: BuiltinByteStringHex -> BuiltinByteStringHex -> Bool
$cmax :: BuiltinByteStringHex
-> BuiltinByteStringHex -> BuiltinByteStringHex
max :: BuiltinByteStringHex
-> BuiltinByteStringHex -> BuiltinByteStringHex
$cmin :: BuiltinByteStringHex
-> BuiltinByteStringHex -> BuiltinByteStringHex
min :: BuiltinByteStringHex
-> BuiltinByteStringHex -> BuiltinByteStringHex
Haskell.Ord
    , Int -> BuiltinByteStringHex -> ShowS
[BuiltinByteStringHex] -> ShowS
BuiltinByteStringHex -> String
(Int -> BuiltinByteStringHex -> ShowS)
-> (BuiltinByteStringHex -> String)
-> ([BuiltinByteStringHex] -> ShowS)
-> Show BuiltinByteStringHex
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> BuiltinByteStringHex -> ShowS
showsPrec :: Int -> BuiltinByteStringHex -> ShowS
$cshow :: BuiltinByteStringHex -> String
show :: BuiltinByteStringHex -> String
$cshowList :: [BuiltinByteStringHex] -> ShowS
showList :: [BuiltinByteStringHex] -> ShowS
Haskell.Show
    , NonEmpty BuiltinByteStringHex -> BuiltinByteStringHex
BuiltinByteStringHex
-> BuiltinByteStringHex -> BuiltinByteStringHex
(BuiltinByteStringHex
 -> BuiltinByteStringHex -> BuiltinByteStringHex)
-> (NonEmpty BuiltinByteStringHex -> BuiltinByteStringHex)
-> (forall b.
    Integral b =>
    b -> BuiltinByteStringHex -> BuiltinByteStringHex)
-> Semigroup BuiltinByteStringHex
forall b.
Integral b =>
b -> BuiltinByteStringHex -> BuiltinByteStringHex
forall a.
(a -> a -> a)
-> (NonEmpty a -> a)
-> (forall b. Integral b => b -> a -> a)
-> Semigroup a
$c<> :: BuiltinByteStringHex
-> BuiltinByteStringHex -> BuiltinByteStringHex
<> :: BuiltinByteStringHex
-> BuiltinByteStringHex -> BuiltinByteStringHex
$csconcat :: NonEmpty BuiltinByteStringHex -> BuiltinByteStringHex
sconcat :: NonEmpty BuiltinByteStringHex -> BuiltinByteStringHex
$cstimes :: forall b.
Integral b =>
b -> BuiltinByteStringHex -> BuiltinByteStringHex
stimes :: forall b.
Integral b =>
b -> BuiltinByteStringHex -> BuiltinByteStringHex
Haskell.Semigroup
    , Semigroup BuiltinByteStringHex
BuiltinByteStringHex
Semigroup BuiltinByteStringHex =>
BuiltinByteStringHex
-> (BuiltinByteStringHex
    -> BuiltinByteStringHex -> BuiltinByteStringHex)
-> ([BuiltinByteStringHex] -> BuiltinByteStringHex)
-> Monoid BuiltinByteStringHex
[BuiltinByteStringHex] -> BuiltinByteStringHex
BuiltinByteStringHex
-> BuiltinByteStringHex -> BuiltinByteStringHex
forall a.
Semigroup a =>
a -> (a -> a -> a) -> ([a] -> a) -> Monoid a
$cmempty :: BuiltinByteStringHex
mempty :: BuiltinByteStringHex
$cmappend :: BuiltinByteStringHex
-> BuiltinByteStringHex -> BuiltinByteStringHex
mappend :: BuiltinByteStringHex
-> BuiltinByteStringHex -> BuiltinByteStringHex
$cmconcat :: [BuiltinByteStringHex] -> BuiltinByteStringHex
mconcat :: [BuiltinByteStringHex] -> BuiltinByteStringHex
Haskell.Monoid
    , Eq BuiltinByteStringHex
Eq BuiltinByteStringHex =>
(Int -> BuiltinByteStringHex -> Int)
-> (BuiltinByteStringHex -> Int) -> Hashable BuiltinByteStringHex
Int -> BuiltinByteStringHex -> Int
BuiltinByteStringHex -> Int
forall a. Eq a => (Int -> a -> Int) -> (a -> Int) -> Hashable a
$chashWithSalt :: Int -> BuiltinByteStringHex -> Int
hashWithSalt :: Int -> BuiltinByteStringHex -> Int
$chash :: BuiltinByteStringHex -> Int
hash :: BuiltinByteStringHex -> Int
Hashable
    , [BuiltinByteStringHex] -> Encoding
BuiltinByteStringHex -> Encoding
(BuiltinByteStringHex -> Encoding)
-> (forall s. Decoder s BuiltinByteStringHex)
-> ([BuiltinByteStringHex] -> Encoding)
-> (forall s. Decoder s [BuiltinByteStringHex])
-> Serialise BuiltinByteStringHex
forall s. Decoder s [BuiltinByteStringHex]
forall s. Decoder s BuiltinByteStringHex
forall a.
(a -> Encoding)
-> (forall s. Decoder s a)
-> ([a] -> Encoding)
-> (forall s. Decoder s [a])
-> Serialise a
$cencode :: BuiltinByteStringHex -> Encoding
encode :: BuiltinByteStringHex -> Encoding
$cdecode :: forall s. Decoder s BuiltinByteStringHex
decode :: forall s. Decoder s BuiltinByteStringHex
$cencodeList :: [BuiltinByteStringHex] -> Encoding
encodeList :: [BuiltinByteStringHex] -> Encoding
$cdecodeList :: forall s. Decoder s [BuiltinByteStringHex]
decodeList :: forall s. Decoder s [BuiltinByteStringHex]
Serialise
    , BuiltinByteStringHex -> ()
(BuiltinByteStringHex -> ()) -> NFData BuiltinByteStringHex
forall a. (a -> ()) -> NFData a
$crnf :: BuiltinByteStringHex -> ()
rnf :: BuiltinByteStringHex -> ()
NFData
    , BuiltinByteStringHex -> Int
(BuiltinByteStringHex -> Int)
-> (forall p a. BuiltinByteStringHex -> (Ptr p -> IO a) -> IO a)
-> (forall p. BuiltinByteStringHex -> Ptr p -> IO ())
-> ByteArrayAccess BuiltinByteStringHex
forall p. BuiltinByteStringHex -> Ptr p -> IO ()
forall ba.
(ba -> Int)
-> (forall p a. ba -> (Ptr p -> IO a) -> IO a)
-> (forall p. ba -> Ptr p -> IO ())
-> ByteArrayAccess ba
forall p a. BuiltinByteStringHex -> (Ptr p -> IO a) -> IO a
$clength :: BuiltinByteStringHex -> Int
length :: BuiltinByteStringHex -> Int
$cwithByteArray :: forall p a. BuiltinByteStringHex -> (Ptr p -> IO a) -> IO a
withByteArray :: forall p a. BuiltinByteStringHex -> (Ptr p -> IO a) -> IO a
$ccopyByteArrayToPtr :: forall p. BuiltinByteStringHex -> Ptr p -> IO ()
copyByteArrayToPtr :: forall p. BuiltinByteStringHex -> Ptr p -> IO ()
BA.ByteArrayAccess
    , Eq BuiltinByteStringHex
Ord BuiltinByteStringHex
Monoid BuiltinByteStringHex
ByteArrayAccess BuiltinByteStringHex
(Eq BuiltinByteStringHex, Ord BuiltinByteStringHex,
 Monoid BuiltinByteStringHex,
 ByteArrayAccess BuiltinByteStringHex) =>
(forall p a.
 Int -> (Ptr p -> IO a) -> IO (a, BuiltinByteStringHex))
-> ByteArray BuiltinByteStringHex
forall ba.
(Eq ba, Ord ba, Monoid ba, ByteArrayAccess ba) =>
(forall p a. Int -> (Ptr p -> IO a) -> IO (a, ba)) -> ByteArray ba
forall p a. Int -> (Ptr p -> IO a) -> IO (a, BuiltinByteStringHex)
$callocRet :: forall p a. Int -> (Ptr p -> IO a) -> IO (a, BuiltinByteStringHex)
allocRet :: forall p a. Int -> (Ptr p -> IO a) -> IO (a, BuiltinByteStringHex)
BA.ByteArray
    , (forall ann. BuiltinByteStringHex -> Doc ann)
-> (forall ann. [BuiltinByteStringHex] -> Doc ann)
-> Pretty BuiltinByteStringHex
forall ann. [BuiltinByteStringHex] -> Doc ann
forall ann. BuiltinByteStringHex -> Doc ann
forall a.
(forall ann. a -> Doc ann)
-> (forall ann. [a] -> Doc ann) -> Pretty a
$cpretty :: forall ann. BuiltinByteStringHex -> Doc ann
pretty :: forall ann. BuiltinByteStringHex -> Doc ann
$cprettyList :: forall ann. [BuiltinByteStringHex] -> Doc ann
prettyList :: forall ann. [BuiltinByteStringHex] -> Doc ann
Pretty
    )

instance IsString BuiltinByteStringHex where
  fromString :: String -> BuiltinByteStringHex
fromString String
s = BuiltinByteString -> BuiltinByteStringHex
BuiltinByteStringHex (String -> BuiltinByteString
stringToBuiltinByteStringHex String
s)
  {-# INLINE fromString #-}

-- plutus-tx-plugin has a special case for this function,
-- replacing its unfolding with something else.
stringToBuiltinByteStringHex :: Haskell.String -> BuiltinByteString
stringToBuiltinByteStringHex :: String -> BuiltinByteString
stringToBuiltinByteStringHex String
str =
  ByteString -> BuiltinByteString
BuiltinByteString (ByteString -> ByteString
Base16.decodeLenient (String -> ByteString
forall a. IsString a => String -> a
fromString String
str))
{-# OPAQUE stringToBuiltinByteStringHex #-}

{- Note [Built-in types and their Haskell counterparts]
'HasToBuiltin' allows us to convert a value of a built-in type such as 'ByteString' to its Plutus
Tx counterpart, 'BuiltinByteString' in this case. The idea is the same for all built-in types: just
take the Haskell version and make it the Plutus Tx one.

'HasToOpaque' is different, we use it for converting values of only those built-in types that exist
in the Plutus Tx realm, within the Plutus Tx realm. I.e. we cannot convert a 'ByteString', since
'ByteString's don't exist in Plutus Tx, only 'BuiltinByteString's do.

Consider, say, the built-in pair type. In Plutus Tx, we have an (opaque) type for this. It's opaque
because you can't actually pattern match on it, instead you can only in fact use the specific
functions that are available as builtins.

We _also_ have the normal Haskell pair type. This is very different: you can pattern match on it,
and you can use whatever user-defined functions you like on it.

Users would really like to use the latter, and not the former. So we often want to _wrap_ our
built-in functions with little adapters that convert between the opaque "version" of a
type and the "normal Haskell" "version" of a type.

This is what the 'HasToOpaque' and 'HasFromOpaque' classes do. They let us write wrappers for
builtins relatively consistently by just calling 'toOpaque' on their arguments and 'fromOpaque' on
the result. They shouldn't probably be used otherwise.

Ideally, we would not have instances for types which don't have a different Haskell representation
type, such as 'Integer'. 'Integer' in Plutus Tx user code _is_ the opaque built-in type, we don't
expose a different one. So there's no conversion to do. However, this interacts badly with the
instances for polymorphic built-in types, which also convert the type _inside_ them. (This is
necessary to avoid doing multiple traversals of the type, e.g. we don't want to turn a built-in list
into a Haskell list, and then traverse it again to conver the contents). Then we _need_ instances
for all built-in types, so we provide a @default@ implementation for both 'toOpaque' and
'fromOpaque' that simply returns the argument back and use it for those types that don't require any
conversions.

Summarizing, 'toBuiltin'/'fromBuiltin' should be used to cross the boundary between Plutus Tx and
Haskell, while 'toOpaque'/'fromOpaque' should be used within Plutus Tx to convert values to/from
their @Builtin*@ representation, which we need because neither pattern matching nor standard library
functions are available for values of @Builtin*@ types that we get from built-in functions.
-}

{- Note [HasFromOpaque/HasToOpaque instances for polymorphic builtin types]
For various technical reasons
(see Note [Representable built-in functions over polymorphic built-in types])
it's not always easy to provide polymorphic constructors for built-in types, but we can usually
provide destructors.

What this means in practice is that we can write a generic 'HasFromOpaque' instance for pairs that
makes use of polymorphic @fst@/@snd@ builtins, but we can't write a polymorphic 'ToOpaque' instance
because we'd need a polymorphic version of the '(,)' constructor.

Instead we write monomorphic instances corresponding to monomorphic constructor builtins that we add
for specific purposes.
-}

{- Note [Fundeps versus type families in HasFromOpaque/HasToOpaque]
We could use a type family here to get the builtin representation of a type. After all, it's
entirely determined by the Haskell type.

However, this is harder for the plugin to deal with. It's okay to have a type variable for the
representation type that needs to be instantiated later, but it's *not* okay to have an irreducible
type application on a type variable. So fundeps are much nicer here.
-}

-- See Note [Built-in types and their Haskell counterparts].
-- See Note [HasFromOpaque/HasToOpaque instances for polymorphic builtin types].
-- See Note [Fundeps versus type families in HasFromOpaque/HasToOpaque].

{-| A class for converting values of transparent Haskell-defined built-in types (such as '()',
'Bool', '[]' etc) to their opaque Plutus Tx counterparts. Instances for built-in types that are
not transparent are provided as well, simply as identities, since those types are already opaque.
-}
type HasToOpaque :: GHC.Type -> GHC.Type -> GHC.Constraint
class HasToOpaque a arep | a -> arep where
  toOpaque :: a -> arep
  default toOpaque :: (a ~ arep) => a -> arep
  toOpaque = a -> a
a -> arep
forall a. a -> a
id
  {-# INLINEABLE toOpaque #-}

-- See Note [Built-in types and their Haskell counterparts].
-- See Note [HasFromOpaque/HasToOpaque instances for polymorphic builtin types].
-- See Note [Fundeps versus type families in HasFromOpaque/HasToOpaque].

{-| A class for converting values of opaque Plutus Tx types to their transparent Haskell-defined
counterparts (a.k.a. pattern-matchable) built-in types (such as '()', 'Bool', '[]' etc). If no
transparent counterpart exists, then the implementation is identity.
-}
type HasFromOpaque :: GHC.Type -> GHC.Type -> GHC.Constraint
class HasFromOpaque arep a | arep -> a where
  fromOpaque :: arep -> a
  default fromOpaque :: (a ~ arep) => arep -> a
  fromOpaque = arep -> arep
arep -> a
forall a. a -> a
id
  {-# INLINEABLE fromOpaque #-}

instance HasToOpaque BuiltinInteger BuiltinInteger
instance HasFromOpaque BuiltinInteger BuiltinInteger

instance HasToOpaque BuiltinByteString BuiltinByteString
instance HasFromOpaque BuiltinByteString BuiltinByteString

instance HasToOpaque BuiltinString BuiltinString
instance HasFromOpaque BuiltinString BuiltinString

{- Note [Strict conversions to/from unit]
Converting to/from unit *should* be straightforward: just `const ()`.
\*But* GHC is very good at optimizing this, and we sometimes use unit
where side effects matter, e.g. as the result of `trace`. So GHC will
tend to turn `fromOpaque (trace s)` into `()`, which is wrong.

So we want our conversions to/from unit to be strict in Haskell. This
means we need to case pointlessly on the argument, which means we need
case on unit (`chooseUnit`) as a builtin. But then it all works okay.
-}

-- See Note [Strict conversions to/from unit].
instance HasToOpaque () BuiltinUnit where
  toOpaque :: () -> BuiltinUnit
toOpaque ()
x = case ()
x of () -> BuiltinUnit
unitval
  {-# INLINEABLE toOpaque #-}
instance HasFromOpaque BuiltinUnit () where
  fromOpaque :: BuiltinUnit -> ()
fromOpaque BuiltinUnit
u = BuiltinUnit -> () -> ()
forall a. BuiltinUnit -> a -> a
chooseUnit BuiltinUnit
u ()
  {-# INLINEABLE fromOpaque #-}

instance HasToOpaque Bool BuiltinBool where
  toOpaque :: Bool -> BuiltinBool
toOpaque Bool
b = if Bool
b then BuiltinBool
true else BuiltinBool
false
  {-# INLINEABLE toOpaque #-}
instance HasFromOpaque BuiltinBool Bool where
  fromOpaque :: BuiltinBool -> Bool
fromOpaque BuiltinBool
b = BuiltinBool -> Bool -> Bool -> Bool
forall a. BuiltinBool -> a -> a -> a
ifThenElse BuiltinBool
b Bool
True Bool
False
  {-# INLINEABLE fromOpaque #-}

{-| The empty list of elements of the given type that gets spotted by the plugin (grep for
'mkNilOpaque' in the plugin code) and replaced by the actual empty list constant for types that
are supported (a subset of built-in types).
-}
mkNilOpaque :: BuiltinList a
mkNilOpaque :: forall a. BuiltinList a
mkNilOpaque = [a] -> BuiltinList a
forall a. [a] -> BuiltinList a
BuiltinList []
{-# OPAQUE mkNilOpaque #-}

class MkNil arep where
  mkNil :: BuiltinList arep
  mkNil = BuiltinList arep
forall a. BuiltinList a
mkNilOpaque
  {-# INLINEABLE mkNil #-}
instance MkNil BuiltinInteger
instance MkNil BuiltinBool
instance MkNil BuiltinData
instance MkNil (BuiltinPair BuiltinData BuiltinData)

instance (HasToOpaque a arep, MkNil arep) => HasToOpaque [a] (BuiltinList arep) where
  toOpaque :: [a] -> BuiltinList arep
toOpaque = [a] -> BuiltinList arep
goList
   where
    goList :: [a] -> BuiltinList arep
    goList :: [a] -> BuiltinList arep
goList []       = BuiltinList arep
forall arep. MkNil arep => BuiltinList arep
mkNil
    goList (a
d : [a]
ds) = arep -> BuiltinList arep -> BuiltinList arep
forall a. a -> BuiltinList a -> BuiltinList a
mkCons (a -> arep
forall a arep. HasToOpaque a arep => a -> arep
toOpaque a
d) ([a] -> BuiltinList arep
goList [a]
ds)
  {-# INLINEABLE toOpaque #-}
instance (HasFromOpaque arep a) => HasFromOpaque (BuiltinList arep) [a] where
  fromOpaque :: BuiltinList arep -> [a]
fromOpaque = BuiltinList arep -> [a]
go
   where
    -- The combination of both INLINABLE and a type signature seems to stop this getting
    -- lifted to the top level, which means it gets a proper unfolding, which means that
    -- specialization can work, which can actually help quite a bit here.
    go :: BuiltinList arep -> [a]
    go :: BuiltinList arep -> [a]
go = [a] -> (arep -> BuiltinList arep -> [a]) -> BuiltinList arep -> [a]
forall a r. r -> (a -> BuiltinList a -> r) -> BuiltinList a -> r
caseList' [] (\arep
x BuiltinList arep
xs -> arep -> a
forall arep a. HasFromOpaque arep a => arep -> a
fromOpaque arep
x a -> [a] -> [a]
forall a. a -> [a] -> [a]
: BuiltinList arep -> [a]
go BuiltinList arep
xs)
    {-# INLINEABLE go #-}
  {-# INLINEABLE fromOpaque #-}

instance HasToOpaque (BuiltinData, BuiltinData) (BuiltinPair BuiltinData BuiltinData) where
  toOpaque :: (BuiltinData, BuiltinData) -> BuiltinPair BuiltinData BuiltinData
toOpaque (BuiltinData
d1, BuiltinData
d2) = BuiltinData -> BuiltinData -> BuiltinPair BuiltinData BuiltinData
mkPairData (BuiltinData -> BuiltinData
forall a arep. HasToOpaque a arep => a -> arep
toOpaque BuiltinData
d1) (BuiltinData -> BuiltinData
forall a arep. HasToOpaque a arep => a -> arep
toOpaque BuiltinData
d2)
  {-# INLINEABLE toOpaque #-}
instance
  (HasFromOpaque arep a, HasFromOpaque brep b)
  => HasFromOpaque (BuiltinPair arep brep) (a, b)
  where
  fromOpaque :: BuiltinPair arep brep -> (a, b)
fromOpaque BuiltinPair arep brep
p = (arep -> a
forall arep a. HasFromOpaque arep a => arep -> a
fromOpaque (arep -> a) -> arep -> a
forall a b. (a -> b) -> a -> b
$ BuiltinPair arep brep -> arep
forall a b. BuiltinPair a b -> a
fst BuiltinPair arep brep
p, brep -> b
forall arep a. HasFromOpaque arep a => arep -> a
fromOpaque (brep -> b) -> brep -> b
forall a b. (a -> b) -> a -> b
$ BuiltinPair arep brep -> brep
forall a b. BuiltinPair a b -> b
snd BuiltinPair arep brep
p)
  {-# INLINEABLE fromOpaque #-}

instance HasToOpaque BuiltinData BuiltinData
instance HasFromOpaque BuiltinData BuiltinData

instance HasToOpaque BuiltinBLS12_381_G1_Element BuiltinBLS12_381_G1_Element
instance HasFromOpaque BuiltinBLS12_381_G1_Element BuiltinBLS12_381_G1_Element

instance HasToOpaque BuiltinBLS12_381_G2_Element BuiltinBLS12_381_G2_Element
instance HasFromOpaque BuiltinBLS12_381_G2_Element BuiltinBLS12_381_G2_Element

instance HasToOpaque BuiltinBLS12_381_MlResult BuiltinBLS12_381_MlResult
instance HasFromOpaque BuiltinBLS12_381_MlResult BuiltinBLS12_381_MlResult