module JVM.Data.Abstract.ClassFile.Field where

import Data.Text (Text)
import JVM.Data.Abstract.ClassFile.AccessFlags (FieldAccessFlag)
import JVM.Data.Abstract.Type (FieldType)
import JVM.Data.Pretty (Pretty (pretty), hsep, (<+>))
import JVM.Data.Raw.Types (JVMDouble, JVMFloat, JVMInt, JVMLong, JVMString)

data ClassFileField = ClassFileField
    { ClassFileField -> [FieldAccessFlag]
fieldAccessFlags :: [FieldAccessFlag]
    , ClassFileField -> Text
fieldName :: Text
    , ClassFileField -> FieldType
fieldType :: FieldType
    , ClassFileField -> [FieldAttribute]
fieldAttributes :: [FieldAttribute]
    }
    deriving (Int -> ClassFileField -> ShowS
[ClassFileField] -> ShowS
ClassFileField -> String
(Int -> ClassFileField -> ShowS)
-> (ClassFileField -> String)
-> ([ClassFileField] -> ShowS)
-> Show ClassFileField
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> ClassFileField -> ShowS
showsPrec :: Int -> ClassFileField -> ShowS
$cshow :: ClassFileField -> String
show :: ClassFileField -> String
$cshowList :: [ClassFileField] -> ShowS
showList :: [ClassFileField] -> ShowS
Show)

data FieldAttribute
    = ConstantValue ConstantValue
    | Synthetic
    deriving (Int -> FieldAttribute -> ShowS
[FieldAttribute] -> ShowS
FieldAttribute -> String
(Int -> FieldAttribute -> ShowS)
-> (FieldAttribute -> String)
-> ([FieldAttribute] -> ShowS)
-> Show FieldAttribute
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> FieldAttribute -> ShowS
showsPrec :: Int -> FieldAttribute -> ShowS
$cshow :: FieldAttribute -> String
show :: FieldAttribute -> String
$cshowList :: [FieldAttribute] -> ShowS
showList :: [FieldAttribute] -> ShowS
Show)

data ConstantValue
    = ConstantLong JVMLong
    | ConstantFloat JVMFloat
    | ConstantDouble JVMDouble
    | ConstantInteger JVMInt
    | ConstantString JVMString
    deriving (Int -> ConstantValue -> ShowS
[ConstantValue] -> ShowS
ConstantValue -> String
(Int -> ConstantValue -> ShowS)
-> (ConstantValue -> String)
-> ([ConstantValue] -> ShowS)
-> Show ConstantValue
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> ConstantValue -> ShowS
showsPrec :: Int -> ConstantValue -> ShowS
$cshow :: ConstantValue -> String
show :: ConstantValue -> String
$cshowList :: [ConstantValue] -> ShowS
showList :: [ConstantValue] -> ShowS
Show)

instance Pretty ClassFileField where
    pretty :: forall ann. ClassFileField -> Doc ann
pretty (ClassFileField [FieldAccessFlag]
accessFlags Text
name FieldType
fieldType [FieldAttribute]
attributes) =
        [Doc ann] -> Doc ann
forall ann. [Doc ann] -> Doc ann
hsep (FieldAccessFlag -> Doc ann
forall a ann. Pretty a => a -> Doc ann
forall ann. FieldAccessFlag -> Doc ann
pretty (FieldAccessFlag -> Doc ann) -> [FieldAccessFlag] -> [Doc ann]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [FieldAccessFlag]
accessFlags) Doc ann -> Doc ann -> Doc ann
forall ann. Doc ann -> Doc ann -> Doc ann
<+> FieldType -> Doc ann
forall a ann. Pretty a => a -> Doc ann
forall ann. FieldType -> Doc ann
pretty FieldType
fieldType Doc ann -> Doc ann -> Doc ann
forall a. Semigroup a => a -> a -> a
<> Doc ann
" " Doc ann -> Doc ann -> Doc ann
forall a. Semigroup a => a -> a -> a
<> Text -> Doc ann
forall a ann. Pretty a => a -> Doc ann
forall ann. Text -> Doc ann
pretty Text
name Doc ann -> Doc ann -> Doc ann
forall a. Semigroup a => a -> a -> a
<> Doc ann
" " Doc ann -> Doc ann -> Doc ann
forall a. Semigroup a => a -> a -> a
<> [FieldAttribute] -> Doc ann
forall ann. [FieldAttribute] -> Doc ann
forall a ann. Pretty a => a -> Doc ann
pretty [FieldAttribute]
attributes

instance Pretty FieldAttribute where
    pretty :: forall ann. FieldAttribute -> Doc ann
pretty (ConstantValue ConstantValue
v) = Doc ann
"ConstantValue " Doc ann -> Doc ann -> Doc ann
forall a. Semigroup a => a -> a -> a
<> ConstantValue -> Doc ann
forall a ann. Pretty a => a -> Doc ann
forall ann. ConstantValue -> Doc ann
pretty ConstantValue
v
    pretty FieldAttribute
Synthetic = Doc ann
"Synthetic"

instance Pretty ConstantValue where
    pretty :: forall ann. ConstantValue -> Doc ann
pretty (ConstantLong JVMLong
v) = Doc ann
"ConstantLong " Doc ann -> Doc ann -> Doc ann
forall a. Semigroup a => a -> a -> a
<> JVMLong -> Doc ann
forall ann. JVMLong -> Doc ann
forall a ann. Pretty a => a -> Doc ann
pretty JVMLong
v
    pretty (ConstantFloat JVMFloat
v) = Doc ann
"ConstantFloat " Doc ann -> Doc ann -> Doc ann
forall a. Semigroup a => a -> a -> a
<> JVMFloat -> Doc ann
forall ann. JVMFloat -> Doc ann
forall a ann. Pretty a => a -> Doc ann
pretty JVMFloat
v
    pretty (ConstantDouble JVMDouble
v) = Doc ann
"ConstantDouble " Doc ann -> Doc ann -> Doc ann
forall a. Semigroup a => a -> a -> a
<> JVMDouble -> Doc ann
forall ann. JVMDouble -> Doc ann
forall a ann. Pretty a => a -> Doc ann
pretty JVMDouble
v
    pretty (ConstantInteger JVMInt
v) = Doc ann
"ConstantInteger " Doc ann -> Doc ann -> Doc ann
forall a. Semigroup a => a -> a -> a
<> JVMInt -> Doc ann
forall ann. JVMInt -> Doc ann
forall a ann. Pretty a => a -> Doc ann
pretty JVMInt
v
    pretty (ConstantString Text
v) = Doc ann
"ConstantString " Doc ann -> Doc ann -> Doc ann
forall a. Semigroup a => a -> a -> a
<> Text -> Doc ann
forall a ann. Pretty a => a -> Doc ann
forall ann. Text -> Doc ann
pretty Text
v