packages feed

data-svd-0.1.0.0: src/Data/SVD/Diff.hs

module Data.SVD.Diff where

import Data.Algorithm.Diff (Diff, PolyDiff(..))
import qualified Data.Algorithm.Diff
import qualified Data.List
import qualified Data.Maybe
import qualified Safe

import Data.SVD.Types
  ( Device(..)
  , Peripheral(..)
  , Register(..)
  , Field(..)
  )

import Data.SVD.Util
  ( fieldNames
  , registerNames
  )

diffPeriphNames
  :: Device
  -> Device
  -> [Diff String]
diffPeriphNames dev1 dev2 =
  Data.Algorithm.Diff.getDiff
    (Data.List.sort $ map periphName $ devicePeripherals dev1)
    (Data.List.sort $ map periphName $ devicePeripherals dev2)

diffRegisterNames
  :: String
  -> Device
  -> Device
  -> [Diff String]
diffRegisterNames pName dev1 dev2 =
  Data.Algorithm.Diff.getDiff
    (Data.List.sort $ registerNames pName dev1)
    (Data.List.sort $ registerNames pName dev2)

regNames :: Peripheral -> [String]
regNames = map regName . periphRegisters

diffRegNames :: Peripheral -> Peripheral -> [Diff String]
diffRegNames = diff regNames

regNameFields :: String -> Peripheral -> [Field]
regNameFields rName =
    regFields
  . Safe.headNote "regNameFields"
  . filter((==rName) . regName)
  . periphRegisters

diff
  :: Ord a
  => (t -> [a])
  -> t
  -> t
  -> [Diff a]
diff fn x y =
  Data.Algorithm.Diff.getDiff
    (Data.List.sort $ fn x)
    (Data.List.sort $ fn y)

diffFieldNames
  :: String
  -> String
  -> Device
  -> Device
  -> [Diff String]
diffFieldNames pName regName' dev1 dev2 =
  Data.Algorithm.Diff.getDiff
    (Data.List.sort $ fieldNames regName' pName dev1)
    (Data.List.sort $ fieldNames regName' pName dev2)

diffFields
  :: [Field]
  -> [Field]
  -> [PolyDiff Field Field]
diffFields as bs =
  Data.Algorithm.Diff.getDiffBy
    (\x y ->
      cmps fieldName x y
      && cmps fieldBitWidth x y
      && cmps fieldBitOffset x y
    )
  (Data.List.sortOn fieldBitOffset as)
  (Data.List.sortOn fieldBitOffset bs)
  where
    cmps fn a b = fn a == fn b

diffDistance :: [PolyDiff a b] -> Int
diffDistance x =
  sum $ map go x
  where
    go (Both _ _) = 0
    go (First  _) = 1
    go (Second _) = 1

getBoths :: [PolyDiff a b] -> [a]
getBoths = Data.Maybe.catMaybes . map ex
  where
    ex (Both x _) = Just x
    ex _ = Nothing