{-# LANGUAGE LambdaCase #-}

module UntypedPlutusCore.Core (
  module Export,
  splitParams,
  splitApplication,
) where

import UntypedPlutusCore.Core.Instance as Export
import UntypedPlutusCore.Core.Plated as Export
import UntypedPlutusCore.Core.Type as Export

import Data.Bifunctor

-- | Strips off lambda binders.
splitParams :: Term name uni fun a -> ([name], Term name uni fun a)
splitParams :: forall name (uni :: * -> *) fun a.
Term name uni fun a -> ([name], Term name uni fun a)
splitParams = \case
  LamAbs a
_ name
n Term name uni fun a
t -> ([name] -> [name])
-> ([name], Term name uni fun a) -> ([name], Term name uni fun a)
forall a b c. (a -> b) -> (a, c) -> (b, c)
forall (p :: * -> * -> *) a b c.
Bifunctor p =>
(a -> b) -> p a c -> p b c
first (name
n name -> [name] -> [name]
forall a. a -> [a] -> [a]
:) (Term name uni fun a -> ([name], Term name uni fun a)
forall name (uni :: * -> *) fun a.
Term name uni fun a -> ([name], Term name uni fun a)
splitParams Term name uni fun a
t)
  Term name uni fun a
t            -> ([], Term name uni fun a
t)

-- | Strip off arguments
splitApplication :: Term name uni fun a -> (Term name uni fun a, [(a, Term name uni fun a)])
splitApplication :: forall name (uni :: * -> *) fun a.
Term name uni fun a
-> (Term name uni fun a, [(a, Term name uni fun a)])
splitApplication = [(a, Term name uni fun a)]
-> Term name uni fun a
-> (Term name uni fun a, [(a, Term name uni fun a)])
forall {a} {name} {uni :: * -> *} {fun}.
[(a, Term name uni fun a)]
-> Term name uni fun a
-> (Term name uni fun a, [(a, Term name uni fun a)])
go []
  where
    go :: [(a, Term name uni fun a)]
-> Term name uni fun a
-> (Term name uni fun a, [(a, Term name uni fun a)])
go [(a, Term name uni fun a)]
acc = \case
      Apply a
ann Term name uni fun a
fun Term name uni fun a
arg -> [(a, Term name uni fun a)]
-> Term name uni fun a
-> (Term name uni fun a, [(a, Term name uni fun a)])
go ((a
ann, Term name uni fun a
arg) (a, Term name uni fun a)
-> [(a, Term name uni fun a)] -> [(a, Term name uni fun a)]
forall a. a -> [a] -> [a]
: [(a, Term name uni fun a)]
acc) Term name uni fun a
fun
      Term name uni fun a
t                 -> (Term name uni fun a
t, [(a, Term name uni fun a)]
acc)