feat: partial classfile staging
This commit is contained in:
parent
d692c3a6c0
commit
00898b18dc
10 changed files with 136 additions and 35 deletions
|
@ -1,5 +1,6 @@
|
||||||
{-# LANGUAGE ImportQualifiedPost #-}
|
{-# LANGUAGE ImportQualifiedPost #-}
|
||||||
{-# LANGUAGE TypeApplications #-}
|
{-# LANGUAGE TypeApplications #-}
|
||||||
|
{-# LANGUAGE DataKinds #-}
|
||||||
module Main (main) where
|
module Main (main) where
|
||||||
|
|
||||||
import Data.ByteString.Lazy qualified as ByteString
|
import Data.ByteString.Lazy qualified as ByteString
|
||||||
|
@ -7,8 +8,9 @@ import Data.ByteString.Lazy qualified as ByteString
|
||||||
import Language.Java.Classfile (Classfile)
|
import Language.Java.Classfile (Classfile)
|
||||||
import Language.Java.Classfile.Extract (runExtract)
|
import Language.Java.Classfile.Extract (runExtract)
|
||||||
import Language.Java.Classfile.Extractable (extract)
|
import Language.Java.Classfile.Extractable (extract)
|
||||||
|
import Language.Java.Classfile.Stage (Stage(Parse))
|
||||||
|
|
||||||
main :: IO ()
|
main :: IO ()
|
||||||
main = do
|
main = do
|
||||||
input <- ByteString.getContents
|
input <- ByteString.getContents
|
||||||
print $ runExtract input (extract @Classfile)
|
print $ runExtract input (extract @(Classfile Parse))
|
||||||
|
|
|
@ -35,6 +35,7 @@ library
|
||||||
Language.Java.Classfile.ConstantPool.References
|
Language.Java.Classfile.ConstantPool.References
|
||||||
Language.Java.Classfile.Extract
|
Language.Java.Classfile.Extract
|
||||||
Language.Java.Classfile.Extractable
|
Language.Java.Classfile.Extractable
|
||||||
|
Language.Java.Classfile.Extractable.AsTag
|
||||||
Language.Java.Classfile.Extractable.SizedBytes
|
Language.Java.Classfile.Extractable.SizedBytes
|
||||||
Language.Java.Classfile.Extractable.WithTag
|
Language.Java.Classfile.Extractable.WithTag
|
||||||
Language.Java.Classfile.Fields
|
Language.Java.Classfile.Fields
|
||||||
|
@ -44,6 +45,7 @@ library
|
||||||
Language.Java.Classfile.Interfaces
|
Language.Java.Classfile.Interfaces
|
||||||
Language.Java.Classfile.Magic
|
Language.Java.Classfile.Magic
|
||||||
Language.Java.Classfile.Methods
|
Language.Java.Classfile.Methods
|
||||||
|
Language.Java.Classfile.Stage
|
||||||
Language.Java.Classfile.Version
|
Language.Java.Classfile.Version
|
||||||
other-modules:
|
other-modules:
|
||||||
Paths_java_classfile
|
Paths_java_classfile
|
||||||
|
|
|
@ -1,9 +1,19 @@
|
||||||
{-# LANGUAGE DerivingVia #-}
|
{-# LANGUAGE DerivingVia #-}
|
||||||
{-# LANGUAGE DeriveGeneric #-}
|
{-# LANGUAGE DeriveGeneric #-}
|
||||||
|
{-# LANGUAGE StandaloneKindSignatures #-}
|
||||||
|
{-# LANGUAGE DataKinds #-}
|
||||||
|
{-# LANGUAGE StandaloneDeriving #-}
|
||||||
|
{-# LANGUAGE FlexibleContexts #-}
|
||||||
|
{-# LANGUAGE FlexibleInstances #-}
|
||||||
|
{-# LANGUAGE UndecidableInstances #-}
|
||||||
|
{-# LANGUAGE TypeFamilies #-}
|
||||||
module Language.Java.Classfile (Classfile(..)) where
|
module Language.Java.Classfile (Classfile(..)) where
|
||||||
|
|
||||||
import GHC.Generics (Generic, Generically(Generically))
|
import GHC.Generics (Generic, Generically(Generically))
|
||||||
|
|
||||||
|
import Data.Kind (Type)
|
||||||
|
|
||||||
|
import Language.Java.Classfile.Stage (Stage(Parse))
|
||||||
import Language.Java.Classfile.Version (Version)
|
import Language.Java.Classfile.Version (Version)
|
||||||
import Language.Java.Classfile.Magic (Magic)
|
import Language.Java.Classfile.Magic (Magic)
|
||||||
import Language.Java.Classfile.Extractable (Extractable)
|
import Language.Java.Classfile.Extractable (Extractable)
|
||||||
|
@ -17,11 +27,12 @@ import Language.Java.Classfile.Methods (Methods)
|
||||||
import Language.Java.Classfile.Attributes (Attributes)
|
import Language.Java.Classfile.Attributes (Attributes)
|
||||||
|
|
||||||
|
|
||||||
data Classfile = Classfile
|
type Classfile :: Stage -> Type
|
||||||
{ magic :: Magic
|
data Classfile stage = Classfile
|
||||||
|
{ magic :: Magic stage
|
||||||
, version :: Version
|
, version :: Version
|
||||||
, constantPool :: ConstantPool
|
, constantPool :: ConstantPool stage
|
||||||
, accessFlags :: Flags ClassFlag
|
, accessFlags :: ClassFlags stage
|
||||||
, this :: ClassReference
|
, this :: ClassReference
|
||||||
, super :: ClassReference
|
, super :: ClassReference
|
||||||
, interfaces :: Interfaces
|
, interfaces :: Interfaces
|
||||||
|
@ -29,5 +40,14 @@ data Classfile = Classfile
|
||||||
, methods :: Methods
|
, methods :: Methods
|
||||||
, attributes :: Attributes
|
, attributes :: Attributes
|
||||||
}
|
}
|
||||||
|
deriving stock (Generic)
|
||||||
|
|
||||||
|
deriving instance (Show (Magic stage), Show (ConstantPool stage), Show (ClassFlags stage)) => Show (Classfile stage)
|
||||||
|
deriving via Generically (Classfile Parse) instance (Extractable (Classfile Parse))
|
||||||
|
|
||||||
|
type ClassFlags :: Stage -> Type
|
||||||
|
data family ClassFlags stage
|
||||||
|
|
||||||
|
newtype instance ClassFlags Parse = ClassFlags (Flags ClassFlag)
|
||||||
deriving stock (Show, Generic)
|
deriving stock (Show, Generic)
|
||||||
deriving Extractable via Generically Classfile
|
deriving Extractable via Generically (ClassFlags Parse)
|
||||||
|
|
|
@ -2,6 +2,10 @@
|
||||||
{-# LANGUAGE InstanceSigs #-}
|
{-# LANGUAGE InstanceSigs #-}
|
||||||
{-# LANGUAGE TypeApplications #-}
|
{-# LANGUAGE TypeApplications #-}
|
||||||
{-# LANGUAGE OverloadedStrings #-}
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
|
{-# LANGUAGE StandaloneKindSignatures #-}
|
||||||
|
{-# LANGUAGE DataKinds #-}
|
||||||
|
{-# LANGUAGE TypeFamilies #-}
|
||||||
|
{-# LANGUAGE FlexibleInstances #-}
|
||||||
module Language.Java.Classfile.ConstantPool (ConstantPool(..)) where
|
module Language.Java.Classfile.ConstantPool (ConstantPool(..)) where
|
||||||
import Data.Word (Word16)
|
import Data.Word (Word16)
|
||||||
import Data.Array.IArray (Array, listArray)
|
import Data.Array.IArray (Array, listArray)
|
||||||
|
@ -9,12 +13,19 @@ import Language.Java.Classfile.ConstantPool.Entry (Entry, StorageCount (..), sto
|
||||||
import Language.Java.Classfile.Extractable (Extractable (extract))
|
import Language.Java.Classfile.Extractable (Extractable (extract))
|
||||||
import Language.Java.Classfile.Extract (Extract, traceIndex, traceType)
|
import Language.Java.Classfile.Extract (Extract, traceIndex, traceType)
|
||||||
import qualified Data.Text as Text
|
import qualified Data.Text as Text
|
||||||
|
import Language.Java.Classfile.Stage (Stage(..))
|
||||||
|
import Data.Kind (Type)
|
||||||
|
|
||||||
newtype ConstantPool = ConstantPool (Array Word16 Entry)
|
type ConstantPool :: Stage -> Type
|
||||||
|
data family ConstantPool stage
|
||||||
|
|
||||||
|
newtype instance ConstantPool Parse = ConstantPool (Array Word16 Entry)
|
||||||
deriving stock (Show)
|
deriving stock (Show)
|
||||||
|
|
||||||
instance Extractable ConstantPool where
|
data instance ConstantPool Resolve = NoPool
|
||||||
extract :: Extract ConstantPool
|
|
||||||
|
instance Extractable (ConstantPool Parse) where
|
||||||
|
extract :: Extract (ConstantPool Parse)
|
||||||
extract = do
|
extract = do
|
||||||
count <- extract @Word16
|
count <- extract @Word16
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,14 @@
|
||||||
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
|
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
|
||||||
{-# LANGUAGE DataKinds #-}
|
{-# LANGUAGE DataKinds #-}
|
||||||
{-# LANGUAGE DerivingVia #-}
|
{-# LANGUAGE DerivingVia #-}
|
||||||
{-# LANGUAGE DeriveGeneric #-}
|
{-# LANGUAGE TypeFamilies #-}
|
||||||
|
{-# LANGUAGE InstanceSigs #-}
|
||||||
|
{-# LANGUAGE LambdaCase #-}
|
||||||
module Language.Java.Classfile.ConstantPool.References (Utf8Reference(..), ClassReference(..), NameAndTypeReference(..), MethodHandleReferenceKind(..), OpaqueReference(..), BootstrapMethodIndex(..)) where
|
module Language.Java.Classfile.ConstantPool.References (Utf8Reference(..), ClassReference(..), NameAndTypeReference(..), MethodHandleReferenceKind(..), OpaqueReference(..), BootstrapMethodIndex(..)) where
|
||||||
import Data.Word (Word16)
|
import Data.Word (Word16, Word8)
|
||||||
import Language.Java.Classfile.Extractable (Extractable)
|
import Language.Java.Classfile.Extractable (Extractable)
|
||||||
import Language.Java.Classfile.Extractable.WithTag (Word8Tag)
|
import Language.Java.Classfile.Extractable.AsTag
|
||||||
import GHC.Generics (Generically(..), Generic)
|
( TagValue(..), AsTag, AsTag(..) )
|
||||||
|
|
||||||
newtype Utf8Reference = Utf8Reference Word16
|
newtype Utf8Reference = Utf8Reference Word16
|
||||||
deriving stock (Show)
|
deriving stock (Show)
|
||||||
|
@ -29,14 +31,28 @@ newtype BootstrapMethodIndex = BootstrapMethodIndex Word16
|
||||||
deriving newtype Extractable
|
deriving newtype Extractable
|
||||||
|
|
||||||
data MethodHandleReferenceKind
|
data MethodHandleReferenceKind
|
||||||
= GetField (Word8Tag 1 ()) -- I kind of want to redo this
|
= GetField
|
||||||
| GetStatic (Word8Tag 2 ())
|
| GetStatic
|
||||||
| PutField (Word8Tag 3 ())
|
| PutField
|
||||||
| PutStatic (Word8Tag 4 ())
|
| PutStatic
|
||||||
| InvokeVirtual (Word8Tag 5 ())
|
| InvokeVirtual
|
||||||
| InvokeStatic (Word8Tag 6 ())
|
| InvokeStatic
|
||||||
| InvokeSpecial (Word8Tag 7 ())
|
| InvokeSpecial
|
||||||
| NewInvokeSpecial (Word8Tag 8 ())
|
| NewInvokeSpecial
|
||||||
| InvokeInterface (Word8Tag 9 ())
|
| InvokeInterface
|
||||||
deriving stock (Show, Generic)
|
deriving stock (Show, Enum, Bounded)
|
||||||
deriving Extractable via Generically MethodHandleReferenceKind
|
deriving Extractable via AsTag MethodHandleReferenceKind
|
||||||
|
|
||||||
|
instance TagValue MethodHandleReferenceKind where
|
||||||
|
type TagType MethodHandleReferenceKind = Word8
|
||||||
|
tagOf :: MethodHandleReferenceKind -> TagType MethodHandleReferenceKind
|
||||||
|
tagOf = \case
|
||||||
|
GetField -> 1
|
||||||
|
GetStatic -> 2
|
||||||
|
PutField -> 3
|
||||||
|
PutStatic -> 4
|
||||||
|
InvokeVirtual -> 5
|
||||||
|
InvokeStatic -> 6
|
||||||
|
InvokeSpecial -> 7
|
||||||
|
NewInvokeSpecial -> 8
|
||||||
|
InvokeInterface -> 9
|
||||||
|
|
30
src/Language/Java/Classfile/Extractable/AsTag.hs
Normal file
30
src/Language/Java/Classfile/Extractable/AsTag.hs
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
{-# LANGUAGE TypeFamilies #-}
|
||||||
|
{-# LANGUAGE InstanceSigs #-}
|
||||||
|
{-# LANGUAGE TypeApplications #-}
|
||||||
|
{-# LANGUAGE ScopedTypeVariables #-}
|
||||||
|
{-# LANGUAGE FlexibleContexts #-}
|
||||||
|
{-# LANGUAGE UndecidableInstances #-}
|
||||||
|
module Language.Java.Classfile.Extractable.AsTag (AsTag(..), TagValue(..)) where
|
||||||
|
import Data.Kind (Type)
|
||||||
|
import Language.Java.Classfile.Extractable (Extractable (extract), expectConstant)
|
||||||
|
import Language.Java.Classfile.Extract (Extract)
|
||||||
|
import Data.Enum.Util (enumerate)
|
||||||
|
import Control.Applicative (asum)
|
||||||
|
import Data.Functor (($>))
|
||||||
|
import Data.Typeable ( Typeable )
|
||||||
|
|
||||||
|
newtype AsTag a = AsTag a
|
||||||
|
deriving Show
|
||||||
|
|
||||||
|
instance (Extractable (TagType a), Bounded a, Enum a, Eq (TagType a), Show (TagType a), Typeable (TagType a), TagValue a ) => Extractable (AsTag a) where
|
||||||
|
extract :: Extract (AsTag a)
|
||||||
|
extract = do
|
||||||
|
let expectTag con = expectConstant (tagOf con) $> con
|
||||||
|
let allConstructors = expectTag <$> enumerate @a
|
||||||
|
|
||||||
|
AsTag <$> asum allConstructors
|
||||||
|
|
||||||
|
|
||||||
|
class TagValue a where
|
||||||
|
type TagType a :: Type
|
||||||
|
tagOf :: a -> TagType a
|
|
@ -5,13 +5,16 @@
|
||||||
{-# LANGUAGE UndecidableInstances #-}
|
{-# LANGUAGE UndecidableInstances #-}
|
||||||
module Language.Java.Classfile.Flags (Flags(..)) where
|
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((.&.)))
|
import Data.Bits (Bits((.&.)))
|
||||||
|
import Data.Enum.Util (enumerate)
|
||||||
|
import Data.Set (Set)
|
||||||
|
|
||||||
|
import qualified Data.Set as Set
|
||||||
|
|
||||||
|
import Language.Java.Classfile.Extract (Extract)
|
||||||
|
import Language.Java.Classfile.Extractable (Extractable (extract))
|
||||||
|
import Language.Java.Classfile.Flag (FlagMask(..))
|
||||||
|
|
||||||
newtype Flags a = Flags (Set a)
|
newtype Flags a = Flags (Set a)
|
||||||
deriving (Show)
|
deriving (Show)
|
||||||
|
|
|
@ -1,19 +1,31 @@
|
||||||
{-# LANGUAGE InstanceSigs #-}
|
{-# LANGUAGE InstanceSigs #-}
|
||||||
|
{-# LANGUAGE TypeFamilies #-}
|
||||||
|
{-# LANGUAGE DataKinds #-}
|
||||||
|
{-# LANGUAGE StandaloneKindSignatures #-}
|
||||||
|
{-# LANGUAGE FlexibleInstances #-}
|
||||||
module Language.Java.Classfile.Magic (Magic(..)) where
|
module Language.Java.Classfile.Magic (Magic(..)) where
|
||||||
import Data.Word (Word32)
|
import Data.Word (Word32)
|
||||||
import Language.Java.Classfile.Extractable (Extractable, extract, expectConstant)
|
import Language.Java.Classfile.Extractable (Extractable, extract, expectConstant)
|
||||||
import Language.Java.Classfile.Extract (Extract)
|
import Language.Java.Classfile.Extract (Extract)
|
||||||
import Data.Hex (Hex (Hex))
|
import Data.Hex (Hex (Hex))
|
||||||
|
import Language.Java.Classfile.Stage (Stage(Parse, Resolve))
|
||||||
|
import Data.Kind (Type)
|
||||||
|
|
||||||
newtype Magic = Magic (Hex Word32)
|
type Magic :: Stage -> Type
|
||||||
|
data family Magic stage
|
||||||
|
|
||||||
|
newtype instance Magic Parse = Magic (Hex Word32)
|
||||||
deriving Show
|
deriving Show
|
||||||
|
|
||||||
instance Extractable Magic where
|
data instance Magic Resolve = Cafebabe
|
||||||
extract :: Extract Magic
|
deriving Show
|
||||||
|
|
||||||
|
instance Extractable (Magic Parse) where
|
||||||
|
extract :: Extract (Magic Parse)
|
||||||
extract = Magic . Hex <$> expectConstant 0xCAFEBABE
|
extract = Magic . Hex <$> expectConstant 0xCAFEBABE
|
||||||
|
|
||||||
-- >>> :set -XOverloadedLists
|
-- >>> :set -XOverloadedLists
|
||||||
-- >>> import Language.Java.Classfile.Extract (runExtract)
|
-- >>> import Language.Java.Classfile.Extract (runExtract)
|
||||||
-- >>> runExtract [0xCA, 0xFE, 0xBA, 0xBE] (Hex <$> (extract :: Extract (Word32)))
|
-- >>> runExtract [0xCA, 0xFE, 0xBA, 0xBE] (Hex <$> (extract :: Extract (Word32)))
|
||||||
-- Just ("",Hex 0xbebafeca)
|
-- Right ("",Hex 0xcafebabe)
|
||||||
|
|
||||||
|
|
6
src/Language/Java/Classfile/Stage.hs
Normal file
6
src/Language/Java/Classfile/Stage.hs
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
{-# LANGUAGE DataKinds #-}
|
||||||
|
module Language.Java.Classfile.Stage (Stage(..)) where
|
||||||
|
|
||||||
|
data Stage
|
||||||
|
= Parse
|
||||||
|
| Resolve
|
|
@ -1,4 +1,3 @@
|
||||||
{-# LANGUAGE DerivingStrategies #-}
|
|
||||||
{-# LANGUAGE DeriveGeneric #-}
|
{-# LANGUAGE DeriveGeneric #-}
|
||||||
{-# LANGUAGE DerivingVia #-}
|
{-# LANGUAGE DerivingVia #-}
|
||||||
module Language.Java.Classfile.Version (Version(..)) where
|
module Language.Java.Classfile.Version (Version(..)) where
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue