jvm-binary-0.1.0: src/Language/JVM/Attribute/LineNumberTable.hs
{-# 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)