{-# LANGUAGE DeriveAnyClass #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE StandaloneDeriving #-} {-# LANGUAGE TemplateHaskell #-} {-| Module : Language.JVM.Attribute.LineNumberTable Copyright : (c) Christian Gram Kalhauge, 2018 License : MIT Maintainer : kalhuage@cs.ucla.edu Based on the LineNumberTable Attribute, as documented [here](http://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.7.12). -} module Language.JVM.Attribute.LineNumberTable ( LineNumberTable (..) , LineNumber , BinaryFormat -- * Helper functions , linenumber , linenumber' ) where import Control.DeepSeq (NFData) import Data.Binary import qualified Data.IntMap as IM import GHC.Generics (Generic) import Language.JVM.Attribute.Base import Language.JVM.ByteCode import Language.JVM.Utils import Language.JVM.Staged -- | 'Signature' is an Attribute. instance IsAttribute (LineNumberTable Low) where attrName = Const "LineNumberTable" type LineNumber = Word16 -- | The 'LineNumberTable' is just a mapping from offsets to linenumbers. newtype LineNumberTable r = LineNumberTable { lineNumberTable :: IM.IntMap LineNumber } deriving (Show, Eq, Ord, Generic, NFData) instance ByteCodeStaged LineNumberTable where evolveBC f (LineNumberTable mp) = LineNumberTable . IM.fromList <$> (mapM (\(x, y) -> do x' <- f (fromIntegral x); pure (x', y)) . IM.toList) mp devolveBC f (LineNumberTable mp) = LineNumberTable . IM.fromList <$> (mapM (\(x, y) -> do x' <- f x; pure (fromIntegral x', y)) . IM.toList) mp -- | Returns the line number of an offset. linenumber :: Int -> LineNumberTable r -> Maybe LineNumber linenumber i (LineNumberTable t) = snd <$> IM.lookupLE i t -- | Returns the line number of an offset. Helper function that also -- does the conversion from integral to int. linenumber' :: Integral a => a -> LineNumberTable r -> Maybe LineNumber linenumber' i = linenumber (fromIntegral i) type BinaryFormat = SizedList16 (Word16, LineNumber) instance Binary (LineNumberTable Low) where get = do LineNumberTable . IM.fromList . map f . unSizedList <$> (get :: Get BinaryFormat) where f (a,b) = (fromIntegral a, b) put (LineNumberTable x) = do put sl where sl :: BinaryFormat sl = SizedList . map f . IM.toList $ x f (a,b) = (fromIntegral a, b)