module UntypedPlutusCore (
    module Export
    , Term (..)
    , Program (..)
    , applyProgram
    , parseScoped
    , PLC.DefaultUni
    , PLC.DefaultFun
    ) where

import UntypedPlutusCore.Check.Scope as Export
import UntypedPlutusCore.Core as Export
import UntypedPlutusCore.DeBruijn as Export
import UntypedPlutusCore.Parser as Parser (parseScoped)
import UntypedPlutusCore.Simplify as Export
import UntypedPlutusCore.Size as Export
import UntypedPlutusCore.Subst as Export

import PlutusCore.Default qualified as PLC
import PlutusCore.Error (ApplyProgramError (MkApplyProgramError))
import PlutusCore.Name.Unique as Export

import Control.Monad.Except

-- | Applies one program to another. Fails if the versions do not match
-- and tries to merge annotations.
applyProgram
    :: (MonadError ApplyProgramError m, Semigroup a)
    => Program name uni fun a
    -> Program name uni fun a
    -> m (Program name uni fun a)
applyProgram :: forall (m :: * -> *) a name (uni :: * -> *) fun.
(MonadError ApplyProgramError m, Semigroup a) =>
Program name uni fun a
-> Program name uni fun a -> m (Program name uni fun a)
applyProgram (Program a
a1 Version
v1 Term name uni fun a
t1) (Program a
a2 Version
v2 Term name uni fun a
t2) | Version
v1 Version -> Version -> Bool
forall a. Eq a => a -> a -> Bool
== Version
v2
  = Program name uni fun a -> m (Program name uni fun a)
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Program name uni fun a -> m (Program name uni fun a))
-> Program name uni fun a -> m (Program name uni fun a)
forall a b. (a -> b) -> a -> b
$ a -> Version -> Term name uni fun a -> Program name uni fun a
forall name (uni :: * -> *) fun ann.
ann -> Version -> Term name uni fun ann -> Program name uni fun ann
Program (a
a1 a -> a -> a
forall a. Semigroup a => a -> a -> a
<> a
a2) Version
v1 (a
-> Term name uni fun a
-> Term name uni fun a
-> Term name uni fun a
forall name (uni :: * -> *) fun ann.
ann
-> Term name uni fun ann
-> Term name uni fun ann
-> Term name uni fun ann
Apply (Term name uni fun a -> a
forall name (uni :: * -> *) fun ann. Term name uni fun ann -> ann
termAnn Term name uni fun a
t1 a -> a -> a
forall a. Semigroup a => a -> a -> a
<> Term name uni fun a -> a
forall name (uni :: * -> *) fun ann. Term name uni fun ann -> ann
termAnn Term name uni fun a
t2) Term name uni fun a
t1 Term name uni fun a
t2)
applyProgram (Program a
_a1 Version
v1 Term name uni fun a
_t1) (Program a
_a2 Version
v2 Term name uni fun a
_t2) =
    ApplyProgramError -> m (Program name uni fun a)
forall a. ApplyProgramError -> m a
forall e (m :: * -> *) a. MonadError e m => e -> m a
throwError (ApplyProgramError -> m (Program name uni fun a))
-> ApplyProgramError -> m (Program name uni fun a)
forall a b. (a -> b) -> a -> b
$ Version -> Version -> ApplyProgramError
MkApplyProgramError Version
v1 Version
v2