Clean up metadata
This commit also changes the metadata file format. Documentation coming soon™
This commit is contained in:
parent
a0dcb37e12
commit
976b2b5d4d
2 changed files with 83 additions and 83 deletions
|
|
@ -1,83 +0,0 @@
|
|||
{-# LANGUAGE NamedFieldPuns #-}
|
||||
{-# LANGUAGE OverloadedStrings #-}
|
||||
|
||||
module Mima.Vm.MetaFileParser
|
||||
( Metadata(..)
|
||||
, AddressRange(..)
|
||||
, Range(..)
|
||||
) where
|
||||
|
||||
import Control.Applicative
|
||||
import Control.Monad
|
||||
import Data.Aeson
|
||||
import Data.Aeson.Types
|
||||
import qualified Data.HashMap.Strict as HM
|
||||
import qualified Data.Map.Strict as Map
|
||||
import qualified Data.Text as T
|
||||
|
||||
import Mima.Format
|
||||
import Mima.Vm.Word
|
||||
|
||||
data Metadata = Metadata
|
||||
{ global :: Map.Map T.Text Value
|
||||
, local :: [Range]
|
||||
} deriving Show
|
||||
|
||||
data AddressRange
|
||||
= RangeFromTo MimaAddress MimaAddress
|
||||
| RangeAt MimaAddress
|
||||
deriving Show
|
||||
|
||||
data Range = Range AddressRange (Map.Map T.Text Value)
|
||||
deriving Show
|
||||
|
||||
instance FromJSON AddressRange where
|
||||
parseJSON = withObject "address range" $ \obj -> at obj <|> range obj
|
||||
where
|
||||
at obj = RangeAt <$> ((obj .: "at") >>= boundedAddress)
|
||||
range obj = do
|
||||
start <- obj .: "start" >>= boundedAddress
|
||||
stop <- obj .: "stop" >>= boundedAddress
|
||||
when (start > stop) (fail "start must be <= stop")
|
||||
return $ RangeFromTo start stop
|
||||
|
||||
instance ToJSON AddressRange where
|
||||
toJSON = Object . addressRangeToMap
|
||||
|
||||
addressRangeToMap :: AddressRange -> Object
|
||||
addressRangeToMap (RangeAt addr) = HM.fromList ["at" .= T.unpack (toHex addr)]
|
||||
addressRangeToMap (RangeFromTo start stop) = HM.fromList
|
||||
[ "start" .= T.unpack (toHex start)
|
||||
, "stop" .= T.unpack (toHex stop)
|
||||
]
|
||||
|
||||
instance FromJSON Range where
|
||||
parseJSON value = do
|
||||
addressRange <- parseJSON value
|
||||
obj <- parseJSON value :: Parser Object
|
||||
values <- obj .: "values"
|
||||
pure $ Range addressRange values
|
||||
|
||||
instance ToJSON Range where
|
||||
toJSON (Range addressRange value) = Object (addressRangeToMap addressRange <> HM.fromList (Map.toList value))
|
||||
|
||||
instance FromJSON Metadata where
|
||||
parseJSON = withObject "metadata" $ \obj ->
|
||||
Metadata <$> obj .: "global" <*> obj .: "local"
|
||||
|
||||
instance ToJSON Metadata where
|
||||
toJSON Metadata{local, global} = object
|
||||
[ "global" .= toJSON global
|
||||
, "local" .= toJSON local
|
||||
]
|
||||
|
||||
boundedAddress :: Value -> Parser MimaAddress
|
||||
boundedAddress value = do
|
||||
n <- parseJSON value :: Parser Integer
|
||||
unless (n >= minVal && n <= maxVal) $
|
||||
fail $ T.unpack $
|
||||
"Value '" <> toHex n <> "' out of bounds for an address."
|
||||
pure $ fromIntegral n
|
||||
where
|
||||
maxVal = fromIntegral (maxBound :: MimaAddress)
|
||||
minVal = fromIntegral (minBound :: MimaAddress)
|
||||
83
src/Mima/Vm/Metadata.hs
Normal file
83
src/Mima/Vm/Metadata.hs
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
{-# LANGUAGE OverloadedStrings #-}
|
||||
|
||||
module Mima.Vm.Metadata
|
||||
( MetaInfo
|
||||
, Range(..)
|
||||
, getMetaInfo
|
||||
, Metadata(..)
|
||||
) where
|
||||
|
||||
import Control.Applicative
|
||||
import Control.Monad
|
||||
import Data.Aeson
|
||||
import Data.Aeson.Types
|
||||
import qualified Data.Map.Strict as Map
|
||||
import qualified Data.Text as T
|
||||
|
||||
import Mima.Vm.Word
|
||||
|
||||
type MetaInfo = Map.Map T.Text Value
|
||||
|
||||
data Range
|
||||
= RangeAt MetaInfo MimaAddress
|
||||
| RangeFromTo MetaInfo MimaAddress MimaAddress
|
||||
deriving Show
|
||||
|
||||
getMetaInfo :: Range -> MetaInfo
|
||||
getMetaInfo (RangeAt info _) = info
|
||||
getMetaInfo (RangeFromTo info _ _) = info
|
||||
|
||||
data Metadata = Metadata
|
||||
{ mdGlobal :: MetaInfo
|
||||
, mdLocal :: [Range]
|
||||
} deriving Show
|
||||
|
||||
instance Semigroup Metadata where
|
||||
md1 <> md2 =
|
||||
Metadata (mdGlobal md1 <> mdGlobal md2) (mdLocal md1 <> mdLocal md2)
|
||||
|
||||
instance Monoid Metadata where
|
||||
mempty = Metadata mempty mempty
|
||||
|
||||
boundedAddress :: Parser Value -> Parser MimaAddress
|
||||
boundedAddress p = do
|
||||
n <- parseJSON =<< p :: Parser Integer
|
||||
unless (n >= minVal && n <= maxVal) $
|
||||
fail $ "value " ++ show n ++ " out of bounds for an address"
|
||||
pure $ fromIntegral n
|
||||
where
|
||||
maxVal = fromIntegral (maxBound :: MimaAddress)
|
||||
minVal = fromIntegral (minBound :: MimaAddress)
|
||||
|
||||
instance FromJSON Range where
|
||||
parseJSON = withObject "range" $ \o -> do
|
||||
info <- parseJSON =<< o .: "info"
|
||||
rangeAt info o <|> rangeFromTo info o
|
||||
where
|
||||
rangeAt info o = RangeAt info <$> boundedAddress (o .: "at")
|
||||
rangeFromTo info o = do
|
||||
start <- boundedAddress (o .: "start")
|
||||
stop <- boundedAddress (o .: "stop")
|
||||
when (start > stop) (fail "start must not be greater than stop")
|
||||
pure $ RangeFromTo info start stop
|
||||
|
||||
instance ToJSON Range where
|
||||
toJSON (RangeAt info at) = object
|
||||
[ "at" .= toJSON (toInteger at)
|
||||
, "info" .= toJSON info
|
||||
]
|
||||
toJSON (RangeFromTo info start stop) = object
|
||||
[ "start" .= toJSON (toInteger start)
|
||||
, "stop" .= toJSON (toInteger stop)
|
||||
, "info" .= toJSON info
|
||||
]
|
||||
|
||||
instance FromJSON Metadata where
|
||||
parseJSON = withObject "metadata" $ \obj ->
|
||||
Metadata <$> obj .: "global" <*> obj .: "local"
|
||||
|
||||
instance ToJSON Metadata where
|
||||
toJSON md = object
|
||||
[ "global" .= toJSON (mdGlobal md)
|
||||
, "local" .= toJSON (mdLocal md)
|
||||
]
|
||||
Loading…
Add table
Add a link
Reference in a new issue