Skip to content

Commit 09f8d16

Browse files
committed
fix(scripts): clean up lint-diskio-complexities
1 parent 063e6f5 commit 09f8d16

File tree

1 file changed

+71
-76
lines changed

1 file changed

+71
-76
lines changed

scripts/lint-diskio-complexities.hs

Lines changed: 71 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ build-depends:
1717
{-# LANGUAGE TypeApplications #-}
1818

1919
import Control.Applicative (Alternative (..))
20+
import Control.Monad (unless)
2021
import qualified Data.ByteString.Lazy as BSL
2122
import Data.Csv
2223
import Data.List (zip4)
@@ -32,33 +33,9 @@ import qualified Data.Text.IO as TIO
3233
import Data.Traversable (for)
3334
import Data.Vector (Vector)
3435
import qualified Data.Vector as V
36+
import System.Exit (ExitCode (..), exitWith)
3537
import System.Process (readProcess)
3638

37-
type Function = Text
38-
type MergePolicy = Text
39-
type MergeSchedule = Text
40-
type WorstCaseDiskIOComplexity = Text
41-
type Condition = Text
42-
43-
data DiskIOComplexity = DiskIOComplexity
44-
{ function :: Function
45-
, mergePolicy :: Maybe MergePolicy
46-
, mergeSchedule :: Maybe MergeSchedule
47-
, worstCaseDiskIOComplexity :: WorstCaseDiskIOComplexity
48-
, condition :: Maybe Condition
49-
}
50-
deriving (Eq, Show)
51-
52-
looseEq :: DiskIOComplexity -> DiskIOComplexity -> Bool
53-
dioc1 `looseEq` dioc2 =
54-
and
55-
[ dioc1.function == dioc2.function
56-
, dioc1.mergePolicy == dioc2.mergePolicy
57-
, dioc1.mergeSchedule == dioc2.mergeSchedule
58-
, dioc1.worstCaseDiskIOComplexity == dioc2.worstCaseDiskIOComplexity
59-
, isNothing dioc1.condition || dioc1.condition == dioc2.condition
60-
]
61-
6239
main :: IO ()
6340
main = do
6441
-- Get the disk I/O complexities from the package description
@@ -78,91 +55,109 @@ main = do
7855

7956
-- Comparing Database.LSMTree.Simple to Database.LSMTree
8057
putStrLn "Comparing Database.LSMTree.Simple to Database.LSMTree:"
81-
diskIOComplexityComparisonSimpleToFull <-
82-
for (concat . M.elems $ mapForSimpleApi) $ \diskIOComplexity@DiskIOComplexity{..} -> do
58+
comparisonSimpleToFull <-
59+
fmap concat . for (concat . M.elems $ mapForSimpleApi) $ \simpleEntry@DiskIOComplexity{..} -> do
8360
case M.lookup function mapForFullApi of
8461
Nothing ->
85-
pure [("Database.LSMTree.Simple", diskIOComplexity)]
86-
Just fullDiskIOComplexities
87-
| diskIOComplexity `elem` fullDiskIOComplexities -> pure []
88-
| otherwise -> pure (("Database.LSMTree.Simple", diskIOComplexity) : (("Database.LSMTree",) <$> fullDiskIOComplexities))
89-
TIO.putStrLn . prettyDiskIOComplexityTable . concat $ diskIOComplexityComparisonSimpleToFull
62+
pure [("Database.LSMTree.Simple", simpleEntry)]
63+
Just fullEntries
64+
| simpleEntry `elem` fullEntries -> pure []
65+
| otherwise -> pure (("Database.LSMTree.Simple", simpleEntry) : (("Database.LSMTree",) <$> fullEntries))
66+
TIO.putStrLn (prettyDiskIOComplexityTable comparisonSimpleToFull)
9067

9168
-- Comparing lsm-tree.cabal to Database.LSMTree
9269
putStrLn "Comparing lsm-tree.cabal to Database.LSMTree:"
93-
diskIOComplexityComparisonPackageDescriptionToFull <-
94-
for (concat . M.elems $ mapForPackageDescription) $ \diskIOComplexity@DiskIOComplexity{..} -> do
70+
comparisonPackageDescriptionToFull <-
71+
fmap concat . for (concat . M.elems $ mapForPackageDescription) $ \simpleEntry@DiskIOComplexity{..} -> do
9572
case M.lookup function mapForFullApi of
9673
Nothing ->
97-
pure [("lsm-tree.cabal", diskIOComplexity)]
98-
Just fullDiskIOComplexities
99-
| any (looseEq diskIOComplexity) fullDiskIOComplexities -> pure []
100-
| otherwise -> pure (("lsm-tree.cabal", diskIOComplexity) : (("Database.LSMTree",) <$> fullDiskIOComplexities))
101-
TIO.putStrLn . prettyDiskIOComplexityTable . concat $ diskIOComplexityComparisonPackageDescriptionToFull
74+
pure [("lsm-tree.cabal", simpleEntry)]
75+
Just fullEntries
76+
| any (looseEq simpleEntry) fullEntries -> pure []
77+
| otherwise -> pure (("lsm-tree.cabal", simpleEntry) : (("Database.LSMTree",) <$> fullEntries))
78+
TIO.putStrLn (prettyDiskIOComplexityTable comparisonPackageDescriptionToFull)
79+
80+
-- Set the exit code based on whether any differences were found
81+
unless (null comparisonSimpleToFull && null comparisonPackageDescriptionToFull) $
82+
exitWith (ExitFailure 1)
10283

10384
--------------------------------------------------------------------------------
10485
-- Helper functions
10586
--------------------------------------------------------------------------------
10687

88+
type Function = Text
89+
type MergePolicy = Text
90+
type MergeSchedule = Text
91+
type WorstCaseDiskIOComplexity = Text
92+
type Condition = Text
93+
94+
data DiskIOComplexity = DiskIOComplexity
95+
{ function :: Function
96+
, mergePolicy :: Maybe MergePolicy
97+
, mergeSchedule :: Maybe MergeSchedule
98+
, worstCaseDiskIOComplexity :: WorstCaseDiskIOComplexity
99+
, condition :: Maybe Condition
100+
}
101+
deriving (Eq, Show)
102+
103+
-- | Loose equality which is used when comparing the disk I/O complexities
104+
-- listed in the package description to those in the modules. Those in the
105+
-- package description do not list complex side conditions, such as all
106+
-- tables having been closed beforehand, or all tables having the same merge
107+
-- policy. Therefore, this equality disregards mismatches when the first
108+
-- entry does not list a condition.
109+
looseEq :: DiskIOComplexity -> DiskIOComplexity -> Bool
110+
entry1 `looseEq` entry2 =
111+
and
112+
[ entry1.function == entry2.function
113+
, entry1.mergePolicy == entry2.mergePolicy
114+
, entry1.mergeSchedule == entry2.mergeSchedule
115+
, entry1.worstCaseDiskIOComplexity == entry2.worstCaseDiskIOComplexity
116+
, isNothing entry1.condition || entry1.condition == entry2.condition
117+
]
118+
107119
-- | Typeset a tagged list of 'DiskIOComplexity' records as an aligned table.
108120
prettyDiskIOComplexityTable :: [(Text, DiskIOComplexity)] -> Text
109-
prettyDiskIOComplexityTable diskIOComplexities =
121+
prettyDiskIOComplexityTable [] = "No differences found.\n"
122+
prettyDiskIOComplexityTable entries =
110123
T.unlines
111124
[ T.unwords
112-
[ tag `padUpTo` maxTagLen
113-
, function `padUpTo` maxFunctionLen
114-
, condition `padUpTo` maxConditionLen
115-
, worstCaseDiskIOComplexity `padUpTo` maxWorstCaseDiskIOComplexityLen
125+
[ prettyCellForColumn tag tags
126+
, prettyCellForColumn function functions
127+
, prettyCellForColumn fullCondition fullConditions
128+
, prettyCellForColumn worstCaseDiskIOComplexity worstCaseDiskIOComplexities
116129
]
117-
| (tag, function, condition, worstCaseDiskIOComplexity) <-
118-
zip4 tags functions conditions worstCaseDiskIOComplexities
130+
| (tag, function, fullCondition, worstCaseDiskIOComplexity) <-
131+
zip4 tags functions fullConditions worstCaseDiskIOComplexities
119132
]
120133
where
121-
tags = fst <$> diskIOComplexities
122-
maxTagLen = maximum (T.length <$> tags)
134+
tags = fst <$> entries
135+
functions = ((.function) . snd) <$> entries
136+
fullConditions = (prettyFullCondition . snd) <$> entries
137+
worstCaseDiskIOComplexities = ((.worstCaseDiskIOComplexity) . snd) <$> entries
123138

124-
functions = ((.function) . snd) <$> diskIOComplexities
125-
maxFunctionLen = maximum (T.length <$> functions)
139+
prettyCellForColumn :: Text -> [Text] -> Text
140+
prettyCellForColumn cell column = cell <> T.replicate (maximum (T.length <$> column) - T.length cell) " "
126141

127-
conditions = (prettyCondition . snd) <$> diskIOComplexities
128-
maxConditionLen = maximum (T.length <$> conditions)
129-
130-
worstCaseDiskIOComplexities = ((.worstCaseDiskIOComplexity) . snd) <$> diskIOComplexities
131-
maxWorstCaseDiskIOComplexityLen = maximum (T.length <$> worstCaseDiskIOComplexities)
132-
133-
padUpTo :: Text -> Int -> Text
134-
padUpTo txt len = txt <> T.replicate (len - T.length txt) " "
135-
136-
prettyCondition :: DiskIOComplexity -> Text
137-
prettyCondition DiskIOComplexity{..} =
138-
fromMaybe "*" (unionMaybeWith slash mergePolicy (unionMaybeWith slash mergeSchedule condition))
142+
prettyFullCondition :: DiskIOComplexity -> Text
143+
prettyFullCondition DiskIOComplexity{..} =
144+
fromMaybe "*" mergePolicy `slashWith` mergeSchedule `slashWith` condition
139145
where
140-
slash :: Text -> Text -> Text
141-
x `slash` y = x <> "/" <> y
142-
143-
unionMaybeWith :: (a -> a -> a) -> Maybe a -> Maybe a -> Maybe a
144-
unionMaybeWith op (Just x) (Just y) = Just (x `op` y)
145-
unionMaybeWith _op (Just x) Nothing = Just x
146-
unionMaybeWith _op Nothing (Just y) = Just y
147-
unionMaybeWith _op Nothing Nothing = Nothing
146+
slashWith :: Text -> Maybe Text -> Text
147+
slashWith x my = maybe x (\y -> x <> "/" <> y) my
148148

149149
-- | Structure vector of 'DiskIOComplexity' records into lookup table by function name.
150150
buildDiskIOComplexityMap :: Vector DiskIOComplexity -> Map Function [DiskIOComplexity]
151151
buildDiskIOComplexityMap = M.unionsWith (<>) . fmap toSingletonMap . V.toList
152152
where
153153
toSingletonMap :: DiskIOComplexity -> Map Function [DiskIOComplexity]
154-
toSingletonMap diskIOComplexity = M.singleton diskIOComplexity.function [diskIOComplexity]
154+
toSingletonMap simpleEntry = M.singleton simpleEntry.function [simpleEntry]
155155

156156
-- | Parse CSV file into vector of 'DiskIOComplexity' records.
157157
decodeDiskIOComplexities :: String -> Vector DiskIOComplexity
158158
decodeDiskIOComplexities =
159159
either error snd . decodeByName . BSL.fromStrict . TE.encodeUtf8 . T.pack
160160

161-
-- | CSV file header for 'DiskIOComplexity' records.
162-
diskIOComplexityHeader :: Header
163-
diskIOComplexityHeader =
164-
header ["Function", "Merge policy", "Merge schedule", "Worst-case disk I/O complexity", "Condition"]
165-
166161
normaliseWorstCaseDiskIOComplexity :: WorstCaseDiskIOComplexity -> WorstCaseDiskIOComplexity
167162
normaliseWorstCaseDiskIOComplexity =
168163
T.replace "+ " "+" . T.replace " +" "+" . T.replace " \\" "\\" . T.replace " " " " . T.replace "\\:" ""

0 commit comments

Comments
 (0)