{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE DeriveAnyClass     #-}
{-# LANGUAGE DeriveGeneric      #-}
{-# LANGUAGE FlexibleInstances  #-}
{-# LANGUAGE OverloadedStrings  #-}
{-# LANGUAGE StandaloneDeriving #-}
{-|
Module      : Language.JVM.Attribute.MethodParameters
Copyright   : (c) Christian Gram Kalhauge, 2017
License     : MIT
Maintainer  : kalhuage@cs.ucla.edu

Based on the MethodParameters Attribute, as documented
[here](http://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.7.24).
-}

module Language.JVM.Attribute.MethodParameters
  ( MethodParameters(..)
  , MethodParameter(..)
  )
where

import qualified Data.Text                     as Text

import           Language.JVM.Constant
import           Language.JVM.Attribute.Base
import           Language.JVM.Staged
import           Language.JVM.Utils
import           Language.JVM.AccessFlag

-- | 'BootstrapMethods' is an Attribute.
instance IsAttribute (MethodParameters Low) where
  attrName :: Const Text (MethodParameters Low)
attrName = Text -> Const Text (MethodParameters Low)
forall k a (b :: k). a -> Const a b
Const Text
"MethodParameters"

-- | Is a list of method parameters, one for each parameter
newtype MethodParameters r = MethodParameters
  { MethodParameters r -> SizedList8 (MethodParameter r)
methodParameters :: SizedList8 (MethodParameter r)
  }

-- | A method parameter
data MethodParameter r = MethodParameter
  { MethodParameter r -> Ref Text r
parameterName        :: !(Ref Text.Text r)
  , MethodParameter r -> BitSet16 PAccessFlag
parameterAccessFlags :: !(BitSet16 PAccessFlag)
  }

instance Staged MethodParameters where
  stage :: (forall (s' :: * -> *). Staged s' => s' r -> m (s' r'))
-> MethodParameters r -> m (MethodParameters r')
stage forall (s' :: * -> *). Staged s' => s' r -> m (s' r')
f (MethodParameters SizedList8 (MethodParameter r)
m) =
    String -> m (MethodParameters r') -> m (MethodParameters r')
forall (m :: * -> *) a. LabelM m => String -> m a -> m a
label String
"BootstrapMethods" (m (MethodParameters r') -> m (MethodParameters r'))
-> m (MethodParameters r') -> m (MethodParameters r')
forall a b. (a -> b) -> a -> b
$ SizedList8 (MethodParameter r') -> MethodParameters r'
forall r. SizedList8 (MethodParameter r) -> MethodParameters r
MethodParameters (SizedList8 (MethodParameter r') -> MethodParameters r')
-> m (SizedList8 (MethodParameter r')) -> m (MethodParameters r')
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (MethodParameter r -> m (MethodParameter r'))
-> SizedList8 (MethodParameter r)
-> m (SizedList8 (MethodParameter r'))
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM MethodParameter r -> m (MethodParameter r')
forall (s' :: * -> *). Staged s' => s' r -> m (s' r')
f SizedList8 (MethodParameter r)
m

instance Staged MethodParameter where
  evolve :: MethodParameter Low -> m (MethodParameter High)
evolve (MethodParameter Ref Text Low
a BitSet16 PAccessFlag
m) = Text -> BitSet16 PAccessFlag -> MethodParameter High
forall r. Ref Text r -> BitSet16 PAccessFlag -> MethodParameter r
MethodParameter (Text -> BitSet16 PAccessFlag -> MethodParameter High)
-> m Text -> m (BitSet16 PAccessFlag -> MethodParameter High)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Index -> m Text
forall (m :: * -> *) r.
(EvolveM m, Referenceable r) =>
Index -> m r
link Index
Ref Text Low
a m (BitSet16 PAccessFlag -> MethodParameter High)
-> m (BitSet16 PAccessFlag) -> m (MethodParameter High)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> BitSet16 PAccessFlag -> m (BitSet16 PAccessFlag)
forall (f :: * -> *) a. Applicative f => a -> f a
pure BitSet16 PAccessFlag
m

  devolve :: MethodParameter High -> m (MethodParameter Low)
devolve (MethodParameter Ref Text High
a BitSet16 PAccessFlag
m) = Index -> BitSet16 PAccessFlag -> MethodParameter Low
forall r. Ref Text r -> BitSet16 PAccessFlag -> MethodParameter r
MethodParameter (Index -> BitSet16 PAccessFlag -> MethodParameter Low)
-> m Index -> m (BitSet16 PAccessFlag -> MethodParameter Low)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Text -> m Index
forall (m :: * -> *) r.
(DevolveM m, Referenceable r) =>
r -> m Index
unlink Text
Ref Text High
a m (BitSet16 PAccessFlag -> MethodParameter Low)
-> m (BitSet16 PAccessFlag) -> m (MethodParameter Low)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> BitSet16 PAccessFlag -> m (BitSet16 PAccessFlag)
forall (f :: * -> *) a. Applicative f => a -> f a
pure BitSet16 PAccessFlag
m

$(deriveBaseWithBinary ''MethodParameter)
$(deriveBaseWithBinary ''MethodParameters)