From d692c3a6c005f80f69f632a146b654f58ee37f54 Mon Sep 17 00:00:00 2001 From: VegOwOtenks Date: Sat, 12 Jul 2025 23:38:43 +0200 Subject: [PATCH] feat: parse the entire classfile --- java-classfile.cabal | 1 + src/Language/Java/Classfile.hs | 9 ++- src/Language/Java/Classfile/ConstantPool.hs | 1 - .../Java/Classfile/ConstantPool/Entry.hs | 4 +- src/Language/Java/Classfile/Methods.hs | 67 +++++++++++++++++++ 5 files changed, 77 insertions(+), 5 deletions(-) create mode 100644 src/Language/Java/Classfile/Methods.hs diff --git a/java-classfile.cabal b/java-classfile.cabal index 873be6e..85f9259 100644 --- a/java-classfile.cabal +++ b/java-classfile.cabal @@ -43,6 +43,7 @@ library Language.Java.Classfile.FromBigEndian Language.Java.Classfile.Interfaces Language.Java.Classfile.Magic + Language.Java.Classfile.Methods Language.Java.Classfile.Version other-modules: Paths_java_classfile diff --git a/src/Language/Java/Classfile.hs b/src/Language/Java/Classfile.hs index 3b89665..68b3dba 100644 --- a/src/Language/Java/Classfile.hs +++ b/src/Language/Java/Classfile.hs @@ -1,9 +1,11 @@ {-# LANGUAGE DerivingVia #-} {-# LANGUAGE DeriveGeneric #-} module Language.Java.Classfile (Classfile(..)) where + +import GHC.Generics (Generic, Generically(Generically)) + import Language.Java.Classfile.Version (Version) import Language.Java.Classfile.Magic (Magic) -import GHC.Generics (Generic, Generically(Generically)) import Language.Java.Classfile.Extractable (Extractable) import Language.Java.Classfile.ConstantPool (ConstantPool) import Language.Java.Classfile.Flags (Flags) @@ -11,6 +13,9 @@ import Language.Java.Classfile.ClassFlag (ClassFlag) import Language.Java.Classfile.ConstantPool.References (ClassReference) import Language.Java.Classfile.Interfaces (Interfaces) import Language.Java.Classfile.Fields (Fields) +import Language.Java.Classfile.Methods (Methods) +import Language.Java.Classfile.Attributes (Attributes) + data Classfile = Classfile { magic :: Magic @@ -21,6 +26,8 @@ data Classfile = Classfile , super :: ClassReference , interfaces :: Interfaces , fields :: Fields + , methods :: Methods + , attributes :: Attributes } deriving stock (Show, Generic) deriving Extractable via Generically Classfile diff --git a/src/Language/Java/Classfile/ConstantPool.hs b/src/Language/Java/Classfile/ConstantPool.hs index 38a35d9..7040d65 100644 --- a/src/Language/Java/Classfile/ConstantPool.hs +++ b/src/Language/Java/Classfile/ConstantPool.hs @@ -8,7 +8,6 @@ import Data.Array.IArray (Array, listArray) import Language.Java.Classfile.ConstantPool.Entry (Entry, StorageCount (..), storageCount) import Language.Java.Classfile.Extractable (Extractable (extract)) import Language.Java.Classfile.Extract (Extract, traceIndex, traceType) -import Control.Monad (forM) import qualified Data.Text as Text newtype ConstantPool = ConstantPool (Array Word16 Entry) diff --git a/src/Language/Java/Classfile/ConstantPool/Entry.hs b/src/Language/Java/Classfile/ConstantPool/Entry.hs index 804a9a4..cae736d 100644 --- a/src/Language/Java/Classfile/ConstantPool/Entry.hs +++ b/src/Language/Java/Classfile/ConstantPool/Entry.hs @@ -10,7 +10,7 @@ module Language.Java.Classfile.ConstantPool.Entry (Entry(..), StorageCount(..), import GHC.Generics (Generic, Generically(..)) import Language.Java.Classfile.Extractable (Extractable (extract)) import Language.Java.Classfile.Extractable.WithTag (Word8Tag) -import Language.Java.Classfile.ConstantPool.References (Utf8Reference, ClassReference, NameAndTypeReference, MethodHandleReferenceKind, OpaqueReference, BootstrapMethodIndex) +import Language.Java.Classfile.ConstantPool.References (ClassReference, NameAndTypeReference, MethodHandleReferenceKind, OpaqueReference, BootstrapMethodIndex, Utf8Reference) import Data.Int (Int32, Int64) import Data.Word (Word16) import Data.Text (Text) @@ -63,5 +63,3 @@ storageCount :: Entry -> StorageCount storageCount = \case (Double _ ; Long _) -> Twice _ -> Once - - diff --git a/src/Language/Java/Classfile/Methods.hs b/src/Language/Java/Classfile/Methods.hs new file mode 100644 index 0000000..38faced --- /dev/null +++ b/src/Language/Java/Classfile/Methods.hs @@ -0,0 +1,67 @@ +{-# LANGUAGE GeneralizedNewtypeDeriving #-} +{-# LANGUAGE DerivingVia #-} +{-# LANGUAGE DeriveGeneric #-} +{-# LANGUAGE InstanceSigs #-} +{-# LANGUAGE LambdaCase #-} +{-# LANGUAGE TypeFamilies #-} +module Language.Java.Classfile.Methods (Methods(..), Method(..), MethodFlag(..)) where +import Data.Array.IArray (Array) +import Data.Word (Word16) +import Language.Java.Classfile.Flags (Flags) +import Language.Java.Classfile.Extractable (Extractable) +import Language.Java.Classfile.Flag (FlagMask (..)) +import GHC.Generics ( Generically, Generic, Generically(..) ) +import Language.Java.Classfile.ConstantPool.References (Utf8Reference) +import Language.Java.Classfile.Attributes (Attributes) + +-- | Alias for the methods structure from the constant-pool. + +newtype Methods = Methods (Array Word16 Method) + deriving stock (Show) + deriving newtype Extractable + +-- | A single method record, contains attributes, name and access flags. + +data Method = Method + { flags :: Flags MethodFlag + , name :: Utf8Reference + , descriptor :: Utf8Reference + , attributes :: Attributes + } + deriving stock (Show, Generic) + deriving Extractable via Generically Method + +-- | Flags for the method, such as abstract, public or static. + +data MethodFlag + = Public + | Private + | Protected + | Static + | Final + | Synchronized + | Bridge + | Varargs + | Native + | Abstract + | Strict + | Synthetic + deriving stock (Show, Eq, Ord, Enum, Bounded) + +instance FlagMask MethodFlag where + type FlagType MethodFlag = Word16 + + maskOf :: MethodFlag -> FlagType MethodFlag + maskOf = \case + Public -> 0x0001 + Private -> 0x0002 + Protected -> 0x0004 + Static -> 0x0008 + Final -> 0x0010 + Synchronized -> 0x0020 + Bridge -> 0x0040 + Varargs -> 0x0080 + Native -> 0x0100 + Abstract -> 0x0400 + Strict -> 0x0800 + Synthetic -> 0x1000