Clean up metadata

This commit also changes the metadata file format. Documentation coming soon™
This commit is contained in:
Joscha 2020-03-27 12:08:26 +00:00
parent a0dcb37e12
commit 976b2b5d4d
2 changed files with 83 additions and 83 deletions

View file

@ -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
View 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)
]