{-# LANGUAGE BlockArguments #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DefaultSignatures #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE StrictData #-}
module PlutusCore.Builtin.KnownType
( BuiltinError
, throwBuiltinErrorWithCause
, KnownBuiltinTypeIn
, KnownBuiltinType
, BuiltinResult (..)
, ReadKnownM
, MakeKnownIn (..)
, readKnownConstant
, MakeKnown
, ReadKnownIn (..)
, ReadKnown
, makeKnownOrFail
, readKnownSelf
) where
import PlutusPrelude
import PlutusCore.Builtin.HasConstant
import PlutusCore.Builtin.Polymorphism
import PlutusCore.Builtin.Result
import PlutusCore.Core
import PlutusCore.Evaluation.ErrorWithCause
import PlutusCore.Evaluation.Result
import PlutusCore.Pretty
import Data.Either.Extras
import Data.String
import GHC.Exts (inline, oneShot)
import GHC.TypeLits
import Universe
type KnownBuiltinTypeIn uni val a =
(HasConstantIn uni val, PrettyParens (SomeTypeIn uni), GEq uni, uni `HasTermLevel` a)
type KnownBuiltinType val a = KnownBuiltinTypeIn (UniOf val) val a
typeMismatchError
:: PrettyParens (SomeTypeIn uni)
=> uni (Esc a)
-> uni (Esc b)
-> UnliftingEvaluationError
typeMismatchError :: forall (uni :: * -> *) a b.
PrettyParens (SomeTypeIn uni) =>
uni (Esc a) -> uni (Esc b) -> UnliftingEvaluationError
typeMismatchError uni (Esc a)
uniExp uni (Esc b)
uniAct =
EvaluationError UnliftingError UnliftingError
-> UnliftingEvaluationError
MkUnliftingEvaluationError (EvaluationError UnliftingError UnliftingError
-> UnliftingEvaluationError)
-> ([Char] -> EvaluationError UnliftingError UnliftingError)
-> [Char]
-> UnliftingEvaluationError
forall b c a. (b -> c) -> (a -> b) -> a -> c
. UnliftingError -> EvaluationError UnliftingError UnliftingError
forall structural operational.
structural -> EvaluationError structural operational
StructuralEvaluationError (UnliftingError -> EvaluationError UnliftingError UnliftingError)
-> ([Char] -> UnliftingError)
-> [Char]
-> EvaluationError UnliftingError UnliftingError
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Char] -> UnliftingError
forall a. IsString a => [Char] -> a
fromString ([Char] -> UnliftingEvaluationError)
-> [Char] -> UnliftingEvaluationError
forall a b. (a -> b) -> a -> b
$ [[Char]] -> [Char]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat
[ [Char]
"Type mismatch: "
, [Char]
"expected: " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ RenderContext -> SomeTypeIn uni -> [Char]
forall str a config.
(PrettyBy config a, Render str) =>
config -> a -> str
displayBy RenderContext
botRenderContext (uni (Esc a) -> SomeTypeIn uni
forall (uni :: * -> *) k (a :: k). uni (Esc a) -> SomeTypeIn uni
SomeTypeIn uni (Esc a)
uniExp)
, [Char]
"; actual: " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ RenderContext -> SomeTypeIn uni -> [Char]
forall str a config.
(PrettyBy config a, Render str) =>
config -> a -> str
displayBy RenderContext
botRenderContext (uni (Esc b) -> SomeTypeIn uni
forall (uni :: * -> *) k (a :: k). uni (Esc a) -> SomeTypeIn uni
SomeTypeIn uni (Esc b)
uniAct)
]
{-# OPAQUE typeMismatchError #-}
type ReadKnownM = Either BuiltinError
readKnownConstant :: forall val a. KnownBuiltinType val a => val -> ReadKnownM a
readKnownConstant :: forall val a. KnownBuiltinType val a => val -> ReadKnownM a
readKnownConstant val
val = val -> Either BuiltinError (Some (ValueOf (UniOf val)))
forall term.
HasConstant term =>
term -> Either BuiltinError (Some (ValueOf (UniOf term)))
asConstant val
val Either BuiltinError (Some (ValueOf (UniOf val)))
-> (Some (ValueOf (UniOf val)) -> Either BuiltinError a)
-> Either BuiltinError a
forall a b.
Either BuiltinError a
-> (a -> Either BuiltinError b) -> Either BuiltinError b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (Some (ValueOf (UniOf val)) -> Either BuiltinError a)
-> Some (ValueOf (UniOf val)) -> Either BuiltinError a
forall a b. (a -> b) -> a -> b
oneShot \case
Some (ValueOf UniOf val (Esc a)
uniAct a
x) -> do
let uniExp :: UniOf val (Esc a)
uniExp = forall k (uni :: * -> *) (a :: k). Contains uni a => uni (Esc a)
knownUni @_ @(UniOf val) @a
case UniOf val (Esc a)
uniExp UniOf val (Esc a) -> UniOf val (Esc a) -> Maybe (Esc a :~: Esc a)
forall a b. UniOf val a -> UniOf val b -> Maybe (a :~: b)
forall k (f :: k -> *) (a :: k) (b :: k).
GEq f =>
f a -> f b -> Maybe (a :~: b)
`geq` UniOf val (Esc a)
uniAct of
Just Esc a :~: Esc a
Refl -> a -> Either BuiltinError a
forall a. a -> Either BuiltinError a
forall (f :: * -> *) a. Applicative f => a -> f a
pure a
a
x
Maybe (Esc a :~: Esc a)
Nothing -> AReview BuiltinError UnliftingEvaluationError
-> UnliftingEvaluationError -> Either BuiltinError a
forall e (m :: * -> *) t x.
MonadError e m =>
AReview e t -> t -> m x
throwing AReview BuiltinError UnliftingEvaluationError
forall r.
AsUnliftingEvaluationError r =>
Prism' r UnliftingEvaluationError
Prism' BuiltinError UnliftingEvaluationError
_UnliftingEvaluationError (UnliftingEvaluationError -> Either BuiltinError a)
-> UnliftingEvaluationError -> Either BuiltinError a
forall a b. (a -> b) -> a -> b
$ UniOf val (Esc a) -> UniOf val (Esc a) -> UnliftingEvaluationError
forall (uni :: * -> *) a b.
PrettyParens (SomeTypeIn uni) =>
uni (Esc a) -> uni (Esc b) -> UnliftingEvaluationError
typeMismatchError UniOf val (Esc a)
uniExp UniOf val (Esc a)
uniAct
{-# INLINE readKnownConstant #-}
class uni ~ UniOf val => MakeKnownIn uni val a where
makeKnown :: a -> BuiltinResult val
default makeKnown :: KnownBuiltinType val a => a -> BuiltinResult val
makeKnown a
x = val -> BuiltinResult val
forall a. a -> BuiltinResult a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (val -> BuiltinResult val) -> (a -> val) -> a -> BuiltinResult val
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> val
forall a term.
(HasConstant term, HasTermLevel (UniOf term) a) =>
a -> term
fromValue (a -> BuiltinResult val) -> a -> BuiltinResult val
forall a b. (a -> b) -> a -> b
$! a
x
{-# INLINE makeKnown #-}
type MakeKnown val = MakeKnownIn (UniOf val) val
class uni ~ UniOf val => ReadKnownIn uni val a where
readKnown :: val -> ReadKnownM a
default readKnown :: KnownBuiltinType val a => val -> ReadKnownM a
readKnown = (val -> ReadKnownM a) -> val -> ReadKnownM a
forall a. a -> a
inline val -> ReadKnownM a
forall val a. KnownBuiltinType val a => val -> ReadKnownM a
readKnownConstant
{-# INLINE readKnown #-}
type ReadKnown val = ReadKnownIn (UniOf val) val
makeKnownOrFail :: MakeKnownIn uni val a => a -> EvaluationResult val
makeKnownOrFail :: forall (uni :: * -> *) val a.
MakeKnownIn uni val a =>
a -> EvaluationResult val
makeKnownOrFail a
x = case a -> BuiltinResult val
forall (uni :: * -> *) val a.
MakeKnownIn uni val a =>
a -> BuiltinResult val
makeKnown a
x of
BuiltinSuccess val
val -> val -> EvaluationResult val
forall a. a -> EvaluationResult a
EvaluationSuccess val
val
BuiltinSuccessWithLogs DList Text
_ val
val -> val -> EvaluationResult val
forall a. a -> EvaluationResult a
EvaluationSuccess val
val
BuiltinFailure DList Text
_ BuiltinError
_ -> EvaluationResult val
forall a. EvaluationResult a
EvaluationFailure
{-# INLINE makeKnownOrFail #-}
readKnownSelf
:: (ReadKnown val a, AsUnliftingEvaluationError err, AsEvaluationFailure err)
=> val -> Either (ErrorWithCause err val) a
readKnownSelf :: forall val a err.
(ReadKnown val a, AsUnliftingEvaluationError err,
AsEvaluationFailure err) =>
val -> Either (ErrorWithCause err val) a
readKnownSelf val
val = (BuiltinError -> Either (ErrorWithCause err val) a)
-> Either BuiltinError a -> Either (ErrorWithCause err val) a
forall (m :: * -> *) a b.
Monad m =>
(a -> m b) -> Either a b -> m b
fromRightM (val -> BuiltinError -> Either (ErrorWithCause err val) a
forall err cause (m :: * -> *) void.
(MonadError (ErrorWithCause err cause) m,
AsUnliftingEvaluationError err, AsEvaluationFailure err) =>
cause -> BuiltinError -> m void
throwBuiltinErrorWithCause val
val) (Either BuiltinError a -> Either (ErrorWithCause err val) a)
-> Either BuiltinError a -> Either (ErrorWithCause err val) a
forall a b. (a -> b) -> a -> b
$ val -> Either BuiltinError a
forall (uni :: * -> *) val a.
ReadKnownIn uni val a =>
val -> ReadKnownM a
readKnown val
val
{-# INLINE readKnownSelf #-}
instance MakeKnownIn uni val a => MakeKnownIn uni val (BuiltinResult a) where
makeKnown :: BuiltinResult a -> BuiltinResult val
makeKnown BuiltinResult a
res = BuiltinResult a
res BuiltinResult a -> (a -> BuiltinResult val) -> BuiltinResult val
forall a b.
BuiltinResult a -> (a -> BuiltinResult b) -> BuiltinResult b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= a -> BuiltinResult val
forall (uni :: * -> *) val a.
MakeKnownIn uni val a =>
a -> BuiltinResult val
makeKnown
{-# INLINE makeKnown #-}
instance
( TypeError ('Text "‘BuiltinResult’ cannot appear in the type of an argument")
, uni ~ UniOf val
) => ReadKnownIn uni val (BuiltinResult a) where
readKnown :: val -> ReadKnownM (BuiltinResult a)
readKnown val
_ = ReadKnownM (BuiltinResult a)
forall (m :: * -> *) void. MonadError BuiltinError m => m void
throwUnderTypeError
{-# INLINE readKnown #-}
instance
( TypeError ('Text "Use ‘BuiltinResult’ instead of ‘EvaluationResult’")
, uni ~ UniOf val
) => MakeKnownIn uni val (EvaluationResult a) where
makeKnown :: EvaluationResult a -> BuiltinResult val
makeKnown EvaluationResult a
_ = BuiltinResult val
forall (m :: * -> *) void. MonadError BuiltinError m => m void
throwUnderTypeError
{-# INLINE makeKnown #-}
instance
( TypeError ('Text "Use ‘BuiltinResult’ instead of ‘EvaluationResult’")
, uni ~ UniOf val
) => ReadKnownIn uni val (EvaluationResult a) where
readKnown :: val -> ReadKnownM (EvaluationResult a)
readKnown val
_ = ReadKnownM (EvaluationResult a)
forall (m :: * -> *) void. MonadError BuiltinError m => m void
throwUnderTypeError
{-# INLINE readKnown #-}
instance HasConstantIn uni val => MakeKnownIn uni val (SomeConstant uni rep) where
makeKnown :: SomeConstant uni rep -> BuiltinResult val
makeKnown = (Some (ValueOf uni) -> BuiltinResult val)
-> SomeConstant uni rep -> BuiltinResult val
forall a b s. Coercible a b => (a -> s) -> b -> s
coerceArg ((Some (ValueOf uni) -> BuiltinResult val)
-> SomeConstant uni rep -> BuiltinResult val)
-> (Some (ValueOf uni) -> BuiltinResult val)
-> SomeConstant uni rep
-> BuiltinResult val
forall a b. (a -> b) -> a -> b
$ val -> BuiltinResult val
forall a. a -> BuiltinResult a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (val -> BuiltinResult val)
-> (Some (ValueOf uni) -> val)
-> Some (ValueOf uni)
-> BuiltinResult val
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Some (ValueOf uni) -> val
Some (ValueOf (UniOf val)) -> val
forall term.
HasConstant term =>
Some (ValueOf (UniOf term)) -> term
fromConstant
{-# INLINE makeKnown #-}
instance HasConstantIn uni val => ReadKnownIn uni val (SomeConstant uni rep) where
readKnown :: val -> ReadKnownM (SomeConstant uni rep)
readKnown = ((val -> Either BuiltinError (Some (ValueOf uni)))
-> val -> ReadKnownM (SomeConstant uni rep))
-> (val -> Either BuiltinError (Some (ValueOf uni)))
-> val
-> ReadKnownM (SomeConstant uni rep)
forall a b. Coercible a b => (a -> b) -> a -> b
coerceVia ((Some (ValueOf uni) -> SomeConstant uni rep)
-> Either BuiltinError (Some (ValueOf uni))
-> ReadKnownM (SomeConstant uni rep)
forall a b.
(a -> b) -> Either BuiltinError a -> Either BuiltinError b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Some (ValueOf uni) -> SomeConstant uni rep
forall (uni :: * -> *) rep.
Some (ValueOf uni) -> SomeConstant uni rep
SomeConstant (Either BuiltinError (Some (ValueOf uni))
-> ReadKnownM (SomeConstant uni rep))
-> (val -> Either BuiltinError (Some (ValueOf uni)))
-> val
-> ReadKnownM (SomeConstant uni rep)
forall b c a. (b -> c) -> (a -> b) -> a -> c
.) val -> Either BuiltinError (Some (ValueOf uni))
val -> Either BuiltinError (Some (ValueOf (UniOf val)))
forall term.
HasConstant term =>
term -> Either BuiltinError (Some (ValueOf (UniOf term)))
asConstant
{-# INLINE readKnown #-}
instance uni ~ UniOf val => MakeKnownIn uni val (Opaque val rep) where
makeKnown :: Opaque val rep -> BuiltinResult val
makeKnown = (val -> BuiltinResult val) -> Opaque val rep -> BuiltinResult val
forall a b s. Coercible a b => (a -> s) -> b -> s
coerceArg val -> BuiltinResult val
forall a. a -> BuiltinResult a
forall (f :: * -> *) a. Applicative f => a -> f a
pure
{-# INLINE makeKnown #-}
instance uni ~ UniOf val => ReadKnownIn uni val (Opaque val rep) where
readKnown :: val -> ReadKnownM (Opaque val rep)
readKnown = (Opaque val rep -> ReadKnownM (Opaque val rep))
-> val -> ReadKnownM (Opaque val rep)
forall a b s. Coercible a b => (a -> s) -> b -> s
coerceArg Opaque val rep -> ReadKnownM (Opaque val rep)
forall a. a -> Either BuiltinError a
forall (f :: * -> *) a. Applicative f => a -> f a
pure
{-# INLINE readKnown #-}