From 10ca143163c7e067ff7e65c27f49a361419e07ee Mon Sep 17 00:00:00 2001 From: VegOwOtenks Date: Sat, 12 Jul 2025 17:52:59 +0200 Subject: [PATCH] feat: class flag parsing --- java-classfile.cabal | 2 +- src/Data/Enum/Util.hs | 5 ++++ src/Language/Java/Classfile.hs | 7 ++++- src/Language/Java/Classfile/ClassFlag.hs | 33 ++++++++++++++++++++++++ src/Language/Java/Classfile/Flag.hs | 8 ++++++ src/Language/Java/Classfile/Flags.hs | 27 +++++++++++++++++++ 6 files changed, 80 insertions(+), 2 deletions(-) create mode 100644 src/Data/Enum/Util.hs create mode 100644 src/Language/Java/Classfile/ClassFlag.hs create mode 100644 src/Language/Java/Classfile/Flag.hs create mode 100644 src/Language/Java/Classfile/Flags.hs diff --git a/java-classfile.cabal b/java-classfile.cabal index 9475193..1b1f151 100644 --- a/java-classfile.cabal +++ b/java-classfile.cabal @@ -25,7 +25,7 @@ source-repository head library exposed-modules: - Data.Bounded.Generic + Data.Enum.Util Data.Hex Language.Java.Classfile Language.Java.Classfile.ClassFlag diff --git a/src/Data/Enum/Util.hs b/src/Data/Enum/Util.hs new file mode 100644 index 0000000..eaf8c1e --- /dev/null +++ b/src/Data/Enum/Util.hs @@ -0,0 +1,5 @@ +module Data.Enum.Util (enumerate) where + +enumerate :: Bounded a => Enum a => [a] +enumerate = [minBound..maxBound] + diff --git a/src/Language/Java/Classfile.hs b/src/Language/Java/Classfile.hs index 89d6474..f115291 100644 --- a/src/Language/Java/Classfile.hs +++ b/src/Language/Java/Classfile.hs @@ -6,12 +6,17 @@ 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) +import Language.Java.Classfile.ClassFlag (ClassFlag) +import Language.Java.Classfile.ConstantPool.References (ClassReference) data Classfile = Classfile { magic :: Magic , version :: Version , constantPool :: ConstantPool - , accessFlags :: AccessFlags + , accessFlags :: Flags ClassFlag + , this :: ClassReference + , super :: ClassReference } deriving stock (Show, Generic) deriving Extractable via Generically Classfile diff --git a/src/Language/Java/Classfile/ClassFlag.hs b/src/Language/Java/Classfile/ClassFlag.hs new file mode 100644 index 0000000..cb79d9a --- /dev/null +++ b/src/Language/Java/Classfile/ClassFlag.hs @@ -0,0 +1,33 @@ +{-# LANGUAGE DataKinds #-} +{-# LANGUAGE TypeFamilies #-} +{-# LANGUAGE InstanceSigs #-} +{-# LANGUAGE LambdaCase #-} +module Language.Java.Classfile.ClassFlag (ClassFlag(..)) where +import Data.Word (Word16) +import Language.Java.Classfile.Flag (FlagMask (..)) + +data ClassFlag + = Public + | Final + | Super + | Interface + | Abstract + | Synthetic + | Annotation + | Enum + | Module + deriving (Show, Eq, Ord, Enum, Bounded) + +instance FlagMask ClassFlag where + type FlagType ClassFlag = Word16 + maskOf :: ClassFlag -> FlagType ClassFlag + maskOf = \case + Public -> 0x0001 + Final -> 0x0010 + Super -> 0x0020 + Interface -> 0x0200 + Abstract -> 0x0400 + Synthetic -> 0x1000 + Annotation -> 0x2000 + Enum -> 0x4000 + Module -> 0x8000 diff --git a/src/Language/Java/Classfile/Flag.hs b/src/Language/Java/Classfile/Flag.hs new file mode 100644 index 0000000..2d6eed5 --- /dev/null +++ b/src/Language/Java/Classfile/Flag.hs @@ -0,0 +1,8 @@ +{-# LANGUAGE TypeFamilies #-} +module Language.Java.Classfile.Flag (FlagMask(..)) where +import Data.Kind (Type) + +class FlagMask a where + type FlagType a :: Type + maskOf :: a -> FlagType a + diff --git a/src/Language/Java/Classfile/Flags.hs b/src/Language/Java/Classfile/Flags.hs new file mode 100644 index 0000000..5cbe929 --- /dev/null +++ b/src/Language/Java/Classfile/Flags.hs @@ -0,0 +1,27 @@ +{-# LANGUAGE InstanceSigs #-} +{-# LANGUAGE TypeApplications #-} +{-# LANGUAGE ScopedTypeVariables #-} +{-# LANGUAGE FlexibleContexts #-} +{-# LANGUAGE UndecidableInstances #-} +module Language.Java.Classfile.Flags (Flags(..)) where + +import Data.Set (Set) +import Language.Java.Classfile.Extractable (Extractable (extract)) +import Language.Java.Classfile.Extract (Extract) +import Language.Java.Classfile.Flag (FlagMask(..)) +import Data.Enum.Util (enumerate) +import qualified Data.Set as Set +import Data.Bits (Bits((.&.))) + +newtype Flags a = Flags (Set a) + deriving (Show) + +instance (Extractable (FlagType a), Bounded a, Enum a, Ord a, FlagMask a, Bits (FlagType a), Num (FlagType a)) => Extractable (Flags a) where + extract :: Extract (Flags a) + extract = do + flags <- extract @(FlagType a) + let allFlags = enumerate @a + let isContained flag = (maskOf flag .&. flags) /= 0 + + pure . Flags . Set.fromList $ filter isContained allFlags +