-- | The user-facing API of the normalizer.

module PlutusCore.Normalize
    ( normalizeType
    , normalizeTypesIn
    , normalizeTypesInProgram
    ) where

import PlutusCore.Core
import PlutusCore.Name
import PlutusCore.Normalize.Internal
import PlutusCore.Quote
import PlutusCore.Rename

import Control.Monad ((>=>))
import Universe

-- See Note [Normalization].
-- | Normalize a 'Type'.
normalizeType
    :: (HasUnique tyname TypeUnique, MonadQuote m, HasUniApply uni)
    => Type tyname uni ann -> m (Normalized (Type tyname uni ann))
normalizeType :: Type tyname uni ann -> m (Normalized (Type tyname uni ann))
normalizeType = Type tyname uni ann -> m (Type tyname uni ann)
forall a (m :: * -> *). (Rename a, MonadQuote m) => a -> m a
rename (Type tyname uni ann -> m (Type tyname uni ann))
-> (Type tyname uni ann -> m (Normalized (Type tyname uni ann)))
-> Type tyname uni ann
-> m (Normalized (Type tyname uni ann))
forall (m :: * -> *) a b c.
Monad m =>
(a -> m b) -> (b -> m c) -> a -> m c
>=> NormalizeTypeT m tyname uni ann (Normalized (Type tyname uni ann))
-> m (Normalized (Type tyname uni ann))
forall (m :: * -> *) tyname (uni :: * -> *) ann a.
NormalizeTypeT m tyname uni ann a -> m a
runNormalizeTypeM (NormalizeTypeT m tyname uni ann (Normalized (Type tyname uni ann))
 -> m (Normalized (Type tyname uni ann)))
-> (Type tyname uni ann
    -> NormalizeTypeT
         m tyname uni ann (Normalized (Type tyname uni ann)))
-> Type tyname uni ann
-> m (Normalized (Type tyname uni ann))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Type tyname uni ann
-> NormalizeTypeT
     m tyname uni ann (Normalized (Type tyname uni ann))
forall tyname (m :: * -> *) (uni :: * -> *) ann.
(HasUnique tyname TypeUnique, MonadQuote m, HasUniApply uni) =>
Type tyname uni ann
-> NormalizeTypeT
     m tyname uni ann (Normalized (Type tyname uni ann))
normalizeTypeM

-- | Normalize every 'Type' in a 'Term'.
normalizeTypesIn
    :: (HasUnique tyname TypeUnique, HasUnique name TermUnique, MonadQuote m, HasUniApply uni)
    => Term tyname name uni fun ann -> m (Term tyname name uni fun ann)
normalizeTypesIn :: Term tyname name uni fun ann -> m (Term tyname name uni fun ann)
normalizeTypesIn = Term tyname name uni fun ann -> m (Term tyname name uni fun ann)
forall a (m :: * -> *). (Rename a, MonadQuote m) => a -> m a
rename (Term tyname name uni fun ann -> m (Term tyname name uni fun ann))
-> (Term tyname name uni fun ann
    -> m (Term tyname name uni fun ann))
-> Term tyname name uni fun ann
-> m (Term tyname name uni fun ann)
forall (m :: * -> *) a b c.
Monad m =>
(a -> m b) -> (b -> m c) -> a -> m c
>=> NormalizeTypeT m tyname uni ann (Term tyname name uni fun ann)
-> m (Term tyname name uni fun ann)
forall (m :: * -> *) tyname (uni :: * -> *) ann a.
NormalizeTypeT m tyname uni ann a -> m a
runNormalizeTypeM (NormalizeTypeT m tyname uni ann (Term tyname name uni fun ann)
 -> m (Term tyname name uni fun ann))
-> (Term tyname name uni fun ann
    -> NormalizeTypeT m tyname uni ann (Term tyname name uni fun ann))
-> Term tyname name uni fun ann
-> m (Term tyname name uni fun ann)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Term tyname name uni fun ann
-> NormalizeTypeT m tyname uni ann (Term tyname name uni fun ann)
forall tyname (m :: * -> *) (uni :: * -> *) name fun ann.
(HasUnique tyname TypeUnique, MonadQuote m, HasUniApply uni) =>
Term tyname name uni fun ann
-> NormalizeTypeT m tyname uni ann (Term tyname name uni fun ann)
normalizeTypesInM

-- | Normalize every 'Type' in a 'Program'.
normalizeTypesInProgram
    :: (HasUnique tyname TypeUnique, HasUnique name TermUnique, MonadQuote m, HasUniApply uni)
    => Program tyname name uni fun ann -> m (Program tyname name uni fun ann)
normalizeTypesInProgram :: Program tyname name uni fun ann
-> m (Program tyname name uni fun ann)
normalizeTypesInProgram (Program ann
x Version ann
v Term tyname name uni fun ann
t) = ann
-> Version ann
-> Term tyname name uni fun ann
-> Program tyname name uni fun ann
forall tyname name (uni :: * -> *) fun ann.
ann
-> Version ann
-> Term tyname name uni fun ann
-> Program tyname name uni fun ann
Program ann
x Version ann
v (Term tyname name uni fun ann -> Program tyname name uni fun ann)
-> m (Term tyname name uni fun ann)
-> m (Program tyname name uni fun ann)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Term tyname name uni fun ann -> m (Term tyname name uni fun ann)
forall tyname name (m :: * -> *) (uni :: * -> *) fun ann.
(HasUnique tyname TypeUnique, HasUnique name TermUnique,
 MonadQuote m, HasUniApply uni) =>
Term tyname name uni fun ann -> m (Term tyname name uni fun ann)
normalizeTypesIn Term tyname name uni fun ann
t