module Michelson.TypeCheck.TypeCheck
( TcInstrHandler
, TcOriginatedContracts
, TcResult
, TypeCheckEnv (..)
, TypeCheck
, runTypeCheck
, TypeCheckInstr
, runTypeCheckIsolated
, runTypeCheckInstrIsolated
, mapTCError
, tcExtFramesL
, tcModeL
, TypeCheckMode(..)
, SomeParamType(..)
, mkSomeParamType
, mkSomeParamTypeUnsafe
) where
import Control.Monad.Except (withExceptT)
import Control.Monad.Reader (mapReaderT)
import Data.Default (def)
import Data.Singletons (Sing)
import Fmt (Buildable, build, pretty)
import qualified Text.Show
import Michelson.ErrorPos (InstrCallStack)
import Michelson.TypeCheck.Error (TCError(..), TCTypeError(..))
import Michelson.TypeCheck.Types
import qualified Michelson.Typed as T
import qualified Michelson.Untyped as U
import Tezos.Address (ContractHash)
import Util.Lens
type TypeCheck =
ExceptT TCError
(State TypeCheckEnv)
data SomeParamType = forall t. (T.ParameterScope t) =>
SomeParamType (Sing t) (T.ParamNotes t)
instance Show SomeParamType where
show :: SomeParamType -> String
show = ParameterType -> String
forall b a. (Show a, IsString b) => a -> b
show (ParameterType -> String)
-> (SomeParamType -> ParameterType) -> SomeParamType -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SomeParamType -> ParameterType
someParamToParameterType
instance Eq SomeParamType where
s1 :: SomeParamType
s1 == :: SomeParamType -> SomeParamType -> Bool
== s2 :: SomeParamType
s2 = SomeParamType -> ParameterType
someParamToParameterType SomeParamType
s1 ParameterType -> ParameterType -> Bool
forall a. Eq a => a -> a -> Bool
== SomeParamType -> ParameterType
someParamToParameterType SomeParamType
s2
instance Buildable SomeParamType where
build :: SomeParamType -> Builder
build = ParameterType -> Builder
forall p. Buildable p => p -> Builder
build (ParameterType -> Builder)
-> (SomeParamType -> ParameterType) -> SomeParamType -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SomeParamType -> ParameterType
someParamToParameterType
someParamToParameterType :: SomeParamType -> U.ParameterType
someParamToParameterType :: SomeParamType -> ParameterType
someParamToParameterType (SomeParamType s :: Sing t
s T.ParamNotesUnsafe{..}) =
Type -> RootAnn -> ParameterType
U.ParameterType (Sing t -> Notes t -> Type
forall (t :: T). KnownT t => Sing t -> Notes t -> Type
T.AsUTypeExt Sing t
s Notes t
pnNotes) RootAnn
pnRootAnn
mkSomeParamTypeUnsafe :: HasCallStack => U.ParameterType -> SomeParamType
mkSomeParamTypeUnsafe :: ParameterType -> SomeParamType
mkSomeParamTypeUnsafe p :: ParameterType
p =
case ParameterType -> Either TCError SomeParamType
mkSomeParamType ParameterType
p of
Right sp :: SomeParamType
sp -> SomeParamType
sp
Left err :: TCError
err -> Text -> SomeParamType
forall a. HasCallStack => Text -> a
error (Text -> SomeParamType) -> Text -> SomeParamType
forall a b. (a -> b) -> a -> b
$ "Illegal type in parameter of env contract: " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> TCError -> Text
forall a b. (Buildable a, FromBuilder b) => a -> b
pretty TCError
err
mkSomeParamType :: U.ParameterType -> Either TCError SomeParamType
mkSomeParamType :: ParameterType -> Either TCError SomeParamType
mkSomeParamType (U.ParameterType t :: Type
t ann :: RootAnn
ann) =
Type
-> (forall (t :: T).
KnownT t =>
Notes t -> Either TCError SomeParamType)
-> Either TCError SomeParamType
forall r. Type -> (forall (t :: T). KnownT t => Notes t -> r) -> r
T.withUType Type
t ((forall (t :: T).
KnownT t =>
Notes t -> Either TCError SomeParamType)
-> Either TCError SomeParamType)
-> (forall (t :: T).
KnownT t =>
Notes t -> Either TCError SomeParamType)
-> Either TCError SomeParamType
forall a b. (a -> b) -> a -> b
$ \(Notes t
notescp :: T.Notes t) -> do
case CheckScope (ParameterScope t) =>
Either BadTypeForScope (Dict (ParameterScope t))
forall (c :: Constraint).
CheckScope c =>
Either BadTypeForScope (Dict c)
T.checkScope @(T.ParameterScope t) of
Right T.Dict ->
case Notes t -> RootAnn -> Either ParamEpError (ParamNotes t)
forall (t :: T).
Notes t -> RootAnn -> Either ParamEpError (ParamNotes t)
T.mkParamNotes Notes t
notescp RootAnn
ann of
Right paramNotes :: ParamNotes t
paramNotes -> SomeParamType -> Either TCError SomeParamType
forall a b. b -> Either a b
Right (SomeParamType -> Either TCError SomeParamType)
-> SomeParamType -> Either TCError SomeParamType
forall a b. (a -> b) -> a -> b
$ Sing t -> ParamNotes t -> SomeParamType
forall (t :: T).
ParameterScope t =>
Sing t -> ParamNotes t -> SomeParamType
SomeParamType Sing t
forall k (a :: k). SingI a => Sing a
T.sing ParamNotes t
paramNotes
Left err :: ParamEpError
err ->
TCError -> Either TCError SomeParamType
forall a b. a -> Either a b
Left (TCError -> Either TCError SomeParamType)
-> TCError -> Either TCError SomeParamType
forall a b. (a -> b) -> a -> b
$ Text -> Maybe TCTypeError -> TCError
TCContractError "invalid parameter declaration: " (Maybe TCTypeError -> TCError) -> Maybe TCTypeError -> TCError
forall a b. (a -> b) -> a -> b
$ TCTypeError -> Maybe TCTypeError
forall a. a -> Maybe a
Just (TCTypeError -> Maybe TCTypeError)
-> TCTypeError -> Maybe TCTypeError
forall a b. (a -> b) -> a -> b
$ ParamEpError -> TCTypeError
IllegalParamDecl ParamEpError
err
Left err :: BadTypeForScope
err -> TCError -> Either TCError SomeParamType
forall a b. a -> Either a b
Left (TCError -> Either TCError SomeParamType)
-> TCError -> Either TCError SomeParamType
forall a b. (a -> b) -> a -> b
$ Text -> Maybe TCTypeError -> TCError
TCContractError ("Parameter type is invalid: " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> BadTypeForScope -> Text
forall a b. (Buildable a, FromBuilder b) => a -> b
pretty BadTypeForScope
err) Maybe TCTypeError
forall a. Maybe a
Nothing
type TcOriginatedContracts = Map ContractHash SomeParamType
data TypeCheckMode
= TypeCheckValue (U.Value, T.T)
| TypeCheckContract SomeParamType
| TypeCheckTest
| TypeCheckPack
data TypeCheckEnv = TypeCheckEnv
{ TypeCheckEnv -> TcExtFrames
tcExtFrames :: ~TcExtFrames
, TypeCheckEnv -> TypeCheckMode
tcMode :: ~TypeCheckMode
}
makeLensesWith postfixLFields ''TypeCheckEnv
runTypeCheck :: TypeCheckMode -> TypeCheck a -> Either TCError a
runTypeCheck :: TypeCheckMode -> TypeCheck a -> Either TCError a
runTypeCheck mode :: TypeCheckMode
mode = TypeCheckEnv
-> State TypeCheckEnv (Either TCError a) -> Either TCError a
forall s a. s -> State s a -> a
evaluatingState (TcExtFrames -> TypeCheckMode -> TypeCheckEnv
TypeCheckEnv [] TypeCheckMode
mode) (State TypeCheckEnv (Either TCError a) -> Either TCError a)
-> (TypeCheck a -> State TypeCheckEnv (Either TCError a))
-> TypeCheck a
-> Either TCError a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TypeCheck a -> State TypeCheckEnv (Either TCError a)
forall e (m :: * -> *) a. ExceptT e m a -> m (Either e a)
runExceptT
runTypeCheckIsolated :: TypeCheck a -> Either TCError a
runTypeCheckIsolated :: TypeCheck a -> Either TCError a
runTypeCheckIsolated = TypeCheckMode -> TypeCheck a -> Either TCError a
forall a. TypeCheckMode -> TypeCheck a -> Either TCError a
runTypeCheck TypeCheckMode
TypeCheckTest
type TcResult inp = Either TCError (SomeInstr inp)
type TypeCheckInstr =
ReaderT InstrCallStack TypeCheck
runTypeCheckInstrIsolated :: TypeCheckInstr a -> Either TCError a
runTypeCheckInstrIsolated :: TypeCheckInstr a -> Either TCError a
runTypeCheckInstrIsolated =
TypeCheck a -> Either TCError a
forall a. TypeCheck a -> Either TCError a
runTypeCheckIsolated (TypeCheck a -> Either TCError a)
-> (TypeCheckInstr a -> TypeCheck a)
-> TypeCheckInstr a
-> Either TCError a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (TypeCheckInstr a -> InstrCallStack -> TypeCheck a)
-> InstrCallStack -> TypeCheckInstr a -> TypeCheck a
forall a b c. (a -> b -> c) -> b -> a -> c
flip TypeCheckInstr a -> InstrCallStack -> TypeCheck a
forall r (m :: * -> *) a. ReaderT r m a -> r -> m a
runReaderT InstrCallStack
forall a. Default a => a
def
mapTCError :: (TCError -> TCError) -> TypeCheckInstr a -> TypeCheckInstr a
mapTCError :: (TCError -> TCError) -> TypeCheckInstr a -> TypeCheckInstr a
mapTCError f :: TCError -> TCError
f = (ExceptT TCError (State TypeCheckEnv) a
-> ExceptT TCError (State TypeCheckEnv) a)
-> TypeCheckInstr a -> TypeCheckInstr a
forall (m :: * -> *) a (n :: * -> *) b r.
(m a -> n b) -> ReaderT r m a -> ReaderT r n b
mapReaderT ((TCError -> TCError)
-> ExceptT TCError (State TypeCheckEnv) a
-> ExceptT TCError (State TypeCheckEnv) a
forall (m :: * -> *) e e' a.
Functor m =>
(e -> e') -> ExceptT e m a -> ExceptT e' m a
withExceptT TCError -> TCError
f)
type TcInstrHandler
= forall inp. (Typeable inp, HasCallStack)
=> U.ExpandedInstr
-> HST inp
-> TypeCheckInstr (SomeInstr inp)