module PlutusIR.AstSize (
  AstSize (..),
  kindAstSize,
  typeAstSize,
  tyVarDeclAstSize,
  termAstSize,
  varDeclAstSize,
) where

import PlutusPrelude

import PlutusIR.Core

import PlutusCore.AstSize (AstSize (..), kindAstSize, tyVarDeclAstSize, typeAstSize, varDeclAstSize)

import Control.Lens

-- | Count the number of AST nodes in a term.
termAstSize :: Term tyname name uni fun ann -> AstSize
termAstSize :: forall tyname name (uni :: * -> *) fun ann.
Term tyname name uni fun ann -> AstSize
termAstSize Term tyname name uni fun ann
term =
  [AstSize] -> AstSize
forall m. Monoid m => [m] -> m
forall (t :: * -> *) m. (Foldable t, Monoid m) => t m -> m
fold
    [ Integer -> AstSize
AstSize Integer
1
    , Term tyname name uni fun ann
term Term tyname name uni fun ann
-> Getting AstSize (Term tyname name uni fun ann) AstSize
-> AstSize
forall s a. s -> Getting a s a -> a
^. (Kind ann -> Const AstSize (Kind ann))
-> Term tyname name uni fun ann
-> Const AstSize (Term tyname name uni fun ann)
forall tyname name (uni :: * -> *) fun ann (f :: * -> *).
Applicative f =>
(Kind ann -> f (Kind ann))
-> Term tyname name uni fun ann -> f (Term tyname name uni fun ann)
termSubkinds ((Kind ann -> Const AstSize (Kind ann))
 -> Term tyname name uni fun ann
 -> Const AstSize (Term tyname name uni fun ann))
-> ((AstSize -> Const AstSize AstSize)
    -> Kind ann -> Const AstSize (Kind ann))
-> Getting AstSize (Term tyname name uni fun ann) AstSize
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Kind ann -> AstSize)
-> (AstSize -> Const AstSize AstSize)
-> Kind ann
-> Const AstSize (Kind ann)
forall (p :: * -> * -> *) (f :: * -> *) s a.
(Profunctor p, Contravariant f) =>
(s -> a) -> Optic' p f s a
to Kind ann -> AstSize
forall a. Kind a -> AstSize
kindAstSize
    , Term tyname name uni fun ann
term Term tyname name uni fun ann
-> Getting AstSize (Term tyname name uni fun ann) AstSize
-> AstSize
forall s a. s -> Getting a s a -> a
^. (Type tyname uni ann -> Const AstSize (Type tyname uni ann))
-> Term tyname name uni fun ann
-> Const AstSize (Term tyname name uni fun ann)
forall tyname name (uni :: * -> *) fun a (f :: * -> *).
Applicative f =>
(Type tyname uni a -> f (Type tyname uni a))
-> Term tyname name uni fun a -> f (Term tyname name uni fun a)
termSubtypes ((Type tyname uni ann -> Const AstSize (Type tyname uni ann))
 -> Term tyname name uni fun ann
 -> Const AstSize (Term tyname name uni fun ann))
-> ((AstSize -> Const AstSize AstSize)
    -> Type tyname uni ann -> Const AstSize (Type tyname uni ann))
-> Getting AstSize (Term tyname name uni fun ann) AstSize
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Type tyname uni ann -> AstSize)
-> (AstSize -> Const AstSize AstSize)
-> Type tyname uni ann
-> Const AstSize (Type tyname uni ann)
forall (p :: * -> * -> *) (f :: * -> *) s a.
(Profunctor p, Contravariant f) =>
(s -> a) -> Optic' p f s a
to Type tyname uni ann -> AstSize
forall tyname (uni :: * -> *) ann. Type tyname uni ann -> AstSize
typeAstSize
    , Term tyname name uni fun ann
term Term tyname name uni fun ann
-> Getting AstSize (Term tyname name uni fun ann) AstSize
-> AstSize
forall s a. s -> Getting a s a -> a
^. (Term tyname name uni fun ann
 -> Const AstSize (Term tyname name uni fun ann))
-> Term tyname name uni fun ann
-> Const AstSize (Term tyname name uni fun ann)
forall tyname name (uni :: * -> *) fun a (f :: * -> *).
Applicative f =>
(Term tyname name uni fun a -> f (Term tyname name uni fun a))
-> Term tyname name uni fun a -> f (Term tyname name uni fun a)
termSubterms ((Term tyname name uni fun ann
  -> Const AstSize (Term tyname name uni fun ann))
 -> Term tyname name uni fun ann
 -> Const AstSize (Term tyname name uni fun ann))
-> Getting AstSize (Term tyname name uni fun ann) AstSize
-> Getting AstSize (Term tyname name uni fun ann) AstSize
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Term tyname name uni fun ann -> AstSize)
-> Getting AstSize (Term tyname name uni fun ann) AstSize
forall (p :: * -> * -> *) (f :: * -> *) s a.
(Profunctor p, Contravariant f) =>
(s -> a) -> Optic' p f s a
to Term tyname name uni fun ann -> AstSize
forall tyname name (uni :: * -> *) fun ann.
Term tyname name uni fun ann -> AstSize
termAstSize
    ]