{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE ViewPatterns #-}
module PlutusIR.Transform.Beta (
beta
) where
import PlutusIR
import PlutusIR.Core.Type
import Control.Lens.Setter ((%~))
import Data.Function ((&))
import Data.List.NonEmpty qualified as NE
extractBindings :: Term tyname name uni fun a -> Maybe (NE.NonEmpty (Binding tyname name uni fun a), Term tyname name uni fun a)
= [Term tyname name uni fun a]
-> Term tyname name uni fun a
-> Maybe
(NonEmpty (Binding tyname name uni fun a),
Term tyname name uni fun a)
forall tyname name (uni :: * -> *) fun ann.
[Term tyname name uni fun ann]
-> Term tyname name uni fun ann
-> Maybe
(NonEmpty (Binding tyname name uni fun ann),
Term tyname name uni fun ann)
collectArgs []
where
collectArgs :: [Term tyname name uni fun ann]
-> Term tyname name uni fun ann
-> Maybe
(NonEmpty (Binding tyname name uni fun ann),
Term tyname name uni fun ann)
collectArgs [Term tyname name uni fun ann]
argStack (Apply ann
_ Term tyname name uni fun ann
f Term tyname name uni fun ann
arg) = [Term tyname name uni fun ann]
-> Term tyname name uni fun ann
-> Maybe
(NonEmpty (Binding tyname name uni fun ann),
Term tyname name uni fun ann)
collectArgs (Term tyname name uni fun ann
argTerm tyname name uni fun ann
-> [Term tyname name uni fun ann] -> [Term tyname name uni fun ann]
forall a. a -> [a] -> [a]
:[Term tyname name uni fun ann]
argStack) Term tyname name uni fun ann
f
collectArgs [Term tyname name uni fun ann]
argStack Term tyname name uni fun ann
t = [Term tyname name uni fun ann]
-> [Binding tyname name uni fun ann]
-> Term tyname name uni fun ann
-> Maybe
(NonEmpty (Binding tyname name uni fun ann),
Term tyname name uni fun ann)
forall tyname name (uni :: * -> *) fun ann fun.
[Term tyname name uni fun ann]
-> [Binding tyname name uni fun ann]
-> Term tyname name uni fun ann
-> Maybe
(NonEmpty (Binding tyname name uni fun ann),
Term tyname name uni fun ann)
matchArgs [Term tyname name uni fun ann]
argStack [] Term tyname name uni fun ann
t
matchArgs :: [Term tyname name uni fun ann]
-> [Binding tyname name uni fun ann]
-> Term tyname name uni fun ann
-> Maybe
(NonEmpty (Binding tyname name uni fun ann),
Term tyname name uni fun ann)
matchArgs (Term tyname name uni fun ann
arg:[Term tyname name uni fun ann]
rest) [Binding tyname name uni fun ann]
acc (LamAbs ann
a name
n Type tyname uni ann
ty Term tyname name uni fun ann
body) = [Term tyname name uni fun ann]
-> [Binding tyname name uni fun ann]
-> Term tyname name uni fun ann
-> Maybe
(NonEmpty (Binding tyname name uni fun ann),
Term tyname name uni fun ann)
matchArgs [Term tyname name uni fun ann]
rest (ann
-> Strictness
-> VarDecl tyname name uni fun ann
-> Term tyname name uni fun ann
-> Binding tyname name uni fun ann
forall tyname name (uni :: * -> *) fun a.
a
-> Strictness
-> VarDecl tyname name uni fun a
-> Term tyname name uni fun a
-> Binding tyname name uni fun a
TermBind ann
a Strictness
Strict (ann
-> name -> Type tyname uni ann -> VarDecl tyname name uni fun ann
forall k tyname name (uni :: * -> *) (fun :: k) ann.
ann
-> name -> Type tyname uni ann -> VarDecl tyname name uni fun ann
VarDecl ann
a name
n Type tyname uni ann
ty) Term tyname name uni fun ann
argBinding tyname name uni fun ann
-> [Binding tyname name uni fun ann]
-> [Binding tyname name uni fun ann]
forall a. a -> [a] -> [a]
:[Binding tyname name uni fun ann]
acc) Term tyname name uni fun ann
body
matchArgs [] [Binding tyname name uni fun ann]
acc Term tyname name uni fun ann
t =
case [Binding tyname name uni fun ann]
-> Maybe (NonEmpty (Binding tyname name uni fun ann))
forall a. [a] -> Maybe (NonEmpty a)
NE.nonEmpty ([Binding tyname name uni fun ann]
-> [Binding tyname name uni fun ann]
forall a. [a] -> [a]
reverse [Binding tyname name uni fun ann]
acc) of
Maybe (NonEmpty (Binding tyname name uni fun ann))
Nothing -> Maybe
(NonEmpty (Binding tyname name uni fun ann),
Term tyname name uni fun ann)
forall a. Maybe a
Nothing
Just NonEmpty (Binding tyname name uni fun ann)
acc' -> (NonEmpty (Binding tyname name uni fun ann),
Term tyname name uni fun ann)
-> Maybe
(NonEmpty (Binding tyname name uni fun ann),
Term tyname name uni fun ann)
forall a. a -> Maybe a
Just (NonEmpty (Binding tyname name uni fun ann)
acc', Term tyname name uni fun ann
t)
matchArgs (Term tyname name uni fun ann
_:[Term tyname name uni fun ann]
_) [Binding tyname name uni fun ann]
_ Term tyname name uni fun ann
_ = Maybe
(NonEmpty (Binding tyname name uni fun ann),
Term tyname name uni fun ann)
forall a. Maybe a
Nothing
beta
:: Term tyname name uni fun a
-> Term tyname name uni fun a
beta :: Term tyname name uni fun a -> Term tyname name uni fun a
beta = \case
(Term tyname name uni fun a
-> Maybe
(NonEmpty (Binding tyname name uni fun a),
Term tyname name uni fun a)
forall tyname name (uni :: * -> *) fun a.
Term tyname name uni fun a
-> Maybe
(NonEmpty (Binding tyname name uni fun a),
Term tyname name uni fun a)
extractBindings -> Just (NonEmpty (Binding tyname name uni fun a)
bs, Term tyname name uni fun a
t)) -> a
-> Recursivity
-> NonEmpty (Binding tyname name uni fun a)
-> Term tyname name uni fun a
-> Term tyname name uni fun a
forall tyname name (uni :: * -> *) fun a.
a
-> Recursivity
-> NonEmpty (Binding tyname name uni fun a)
-> Term tyname name uni fun a
-> Term tyname name uni fun a
Let (Term tyname name uni fun a -> a
forall tyname name (uni :: * -> *) fun a.
Term tyname name uni fun a -> a
termAnn Term tyname name uni fun a
t) Recursivity
NonRec NonEmpty (Binding tyname name uni fun a)
bs (Term tyname name uni fun a -> Term tyname name uni fun a
forall tyname name (uni :: * -> *) fun a.
Term tyname name uni fun a -> Term tyname name uni fun a
beta Term tyname name uni fun a
t)
Term tyname name uni fun a
t -> Term tyname name uni fun a
t Term tyname name uni fun a
-> (Term tyname name uni fun a -> Term tyname name uni fun a)
-> Term tyname name uni fun a
forall a b. a -> (a -> b) -> b
& (Term tyname name uni fun a
-> Identity (Term tyname name uni fun a))
-> Term tyname name uni fun a
-> Identity (Term tyname name uni fun a)
forall tyname name (uni :: * -> *) fun a.
Traversal'
(Term tyname name uni fun a) (Term tyname name uni fun a)
termSubterms ((Term tyname name uni fun a
-> Identity (Term tyname name uni fun a))
-> Term tyname name uni fun a
-> Identity (Term tyname name uni fun a))
-> (Term tyname name uni fun a -> Term tyname name uni fun a)
-> Term tyname name uni fun a
-> Term tyname name uni fun a
forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
%~ Term tyname name uni fun a -> Term tyname name uni fun a
forall tyname name (uni :: * -> *) fun a.
Term tyname name uni fun a -> Term tyname name uni fun a
beta