module UntypedPlutusCore.MkUPlc (UVarDecl (..), uvarDeclName, uvarDeclAnn, mkVar, mkIterApp, mkIterLamAbs, Def(..), UTermDef) where

import Data.List
import PlutusCore.MkPlc (Def (..))
import UntypedPlutusCore.Core.Type

-- | A term definition as a variable.
type UTermDef name uni fun ann = Def (UVarDecl name ann) (Term name uni fun ann)

-- | Make a 'Var' referencing the given 'VarDecl'.
mkVar :: ann -> UVarDecl name ann -> Term name uni fun ann
mkVar :: ann -> UVarDecl name ann -> Term name uni fun ann
mkVar ann
ann = ann -> name -> Term name uni fun ann
forall name (uni :: * -> *) fun ann.
ann -> name -> Term name uni fun ann
Var ann
ann (name -> Term name uni fun ann)
-> (UVarDecl name ann -> name)
-> UVarDecl name ann
-> Term name uni fun ann
forall b c a. (b -> c) -> (a -> b) -> a -> c
. UVarDecl name ann -> name
forall name ann. UVarDecl name ann -> name
_uvarDeclName

-- | Make an iterated application.
mkIterApp
    :: ann
    -> Term name uni fun ann -- ^ @f@
    -> [Term name uni fun ann] -- ^@[ x0 ... xn ]@
    -> Term name uni fun ann -- ^ @[f x0 ... xn ]@
mkIterApp :: ann
-> Term name uni fun ann
-> [Term name uni fun ann]
-> Term name uni fun ann
mkIterApp ann
ann = (Term name uni fun ann
 -> Term name uni fun ann -> Term name uni fun ann)
-> Term name uni fun ann
-> [Term name uni fun ann]
-> Term name uni fun ann
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' (ann
-> Term name uni fun ann
-> Term name uni fun ann
-> Term name uni fun ann
forall name (uni :: * -> *) fun ann.
ann
-> Term name uni fun ann
-> Term name uni fun ann
-> Term name uni fun ann
Apply ann
ann)

-- | Lambda abstract a list of names.
mkIterLamAbs
    :: [UVarDecl name ann]
    -> Term name uni fun ann
    -> Term name uni fun ann
mkIterLamAbs :: [UVarDecl name ann]
-> Term name uni fun ann -> Term name uni fun ann
mkIterLamAbs [UVarDecl name ann]
args Term name uni fun ann
body =
    (UVarDecl name ann
 -> Term name uni fun ann -> Term name uni fun ann)
-> Term name uni fun ann
-> [UVarDecl name ann]
-> Term name uni fun ann
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr (\(UVarDecl ann
ann name
name ) Term name uni fun ann
acc -> ann -> name -> Term name uni fun ann -> Term name uni fun ann
forall name (uni :: * -> *) fun ann.
ann -> name -> Term name uni fun ann -> Term name uni fun ann
LamAbs ann
ann name
name Term name uni fun ann
acc) Term name uni fun ann
body [UVarDecl name ann]
args