-- SPDX-FileCopyrightText: 2021 Oxhead Alpha -- SPDX-License-Identifier: LicenseRef-MIT-OA -- This module provides data types for representing partially typed -- instructions. module Morley.Michelson.TypeCheck.TypeCheckedOp ( TypeCheckedInstr , TypeCheckedOp(..) , IllTypedInstr(..) , someInstrToOp , someViewToOp ) where import Data.Singletons (SingI) import Morley.Michelson.Printer.Util (RenderDoc(..), renderOpsListNoBraces) import Morley.Michelson.TypeCheck.Types (HST(..), SomeInstr(..), SomeInstrOut(..)) import Morley.Michelson.Typed.Aliases import Morley.Michelson.Typed.Convert (instrToOps) import Morley.Michelson.Typed.Instr (Instr, castInstr) import Morley.Michelson.Typed.View (SomeView'(..), View'(..)) import Morley.Michelson.Untyped qualified as U import Morley.Michelson.Untyped.Instr (ExpandedOp, InstrAbstract(..)) import Morley.Util.TH (deriveGADTNFData) -- | Represents a root of a partially typed operation tree. type TypeCheckedInstr = InstrAbstract TypeCheckedOp -- | Represents nodes of a partially typed operation tree. data TypeCheckedOp where -- | Constructs well-typed node. WellTypedOp :: (SingI inp, SingI out) => Instr inp out -> TypeCheckedOp -- | Constructs ill-typed node which might in turn contain well-typed and -- non-typed operations. IllTypedOp :: IllTypedInstr -> TypeCheckedOp deriving stock instance Show TypeCheckedOp instance Eq TypeCheckedOp where WellTypedOp i1 == WellTypedOp i2 = castInstr i1 == Just i2 IllTypedOp i1 == IllTypedOp i2 = i1 == i2 _ == _ = False -- | Represents a non-well-typed operation data IllTypedInstr = SemiTypedInstr TypeCheckedInstr -- ^ Constructs a partialy typed operation. | NonTypedInstr ExpandedOp -- ^ Constructs a completely untyped operation. deriving stock (Show, Eq, Generic) deriving anyclass instance NFData TypeCheckedOp => NFData IllTypedInstr instance RenderDoc TypeCheckedOp where renderDoc _ (WellTypedOp instr) = renderOpsListNoBraces False (instrToOps instr) renderDoc pn (IllTypedOp (SemiTypedInstr instr)) = renderDoc pn instr renderDoc pn (IllTypedOp (NonTypedInstr op)) = renderDoc pn op -- | Makes a well-typed node out of `SomeInstr` someInstrToOp :: SomeInstr inp -> TypeCheckedOp someInstrToOp (hst :/ rest) = case hst of SNil -> go rest (::&){} -> go rest where go :: forall inp. SingI inp => SomeInstrOut inp -> TypeCheckedOp go (i ::: _) = WellTypedOp i go (AnyOutInstr i) = WellTypedOp (i @'[]) -- | Makes a view with well-typed code, taking the untyped and typechecked view. someViewToOp :: U.View' op -> SomeView st -> U.View' TypeCheckedOp someViewToOp U.View{..} (SomeView View{..}) = U.View { U.viewCode = [WellTypedOp vCode] , .. } $(deriveGADTNFData ''TypeCheckedOp)