{-# LANGUAGE MonadComprehensions #-}
{-# LANGUAGE OverloadedLists #-}
module Shrun.Configuration.Legend
(
linesToMap,
LegendMap,
DuplicateKeyError (..),
translateCommands,
CyclicKeyError (..),
)
where
import Data.HashMap.Strict qualified as Map
import Data.HashSet qualified as Set
import Data.Sequence.NonEmpty qualified as NESeq
import Data.Text.Lazy qualified as LazyT
import Data.Text.Lazy.Builder (Builder)
import Data.Text.Lazy.Builder qualified as LTBuilder
import Shrun.Command.Types
( CommandIndex,
CommandP (MkCommandP),
CommandP1,
)
import Shrun.Command.Types qualified as CT
import Shrun.Configuration.Data.Graph
( Edge,
EdgeArgs (EdgeArgsList, EdgeArgsSequential),
EdgeLabel (EdgeAnd, EdgeAny, EdgeOr),
EdgeSequential (EdgeSequentialAnd, EdgeSequentialAny, EdgeSequentialOr),
Edges (MkEdges),
)
import Shrun.Configuration.Data.Graph qualified as Graph
import Shrun.Configuration.Toml.Legend (KeyVal (MkKeyVal), LegendMap)
import Shrun.Prelude
newtype DuplicateKeyError = MkDuplicateKeyError Text
deriving stock (DuplicateKeyError -> DuplicateKeyError -> Bool
(DuplicateKeyError -> DuplicateKeyError -> Bool)
-> (DuplicateKeyError -> DuplicateKeyError -> Bool)
-> Eq DuplicateKeyError
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: DuplicateKeyError -> DuplicateKeyError -> Bool
== :: DuplicateKeyError -> DuplicateKeyError -> Bool
$c/= :: DuplicateKeyError -> DuplicateKeyError -> Bool
/= :: DuplicateKeyError -> DuplicateKeyError -> Bool
Eq, Int -> DuplicateKeyError -> ShowS
[DuplicateKeyError] -> ShowS
DuplicateKeyError -> String
(Int -> DuplicateKeyError -> ShowS)
-> (DuplicateKeyError -> String)
-> ([DuplicateKeyError] -> ShowS)
-> Show DuplicateKeyError
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> DuplicateKeyError -> ShowS
showsPrec :: Int -> DuplicateKeyError -> ShowS
$cshow :: DuplicateKeyError -> String
show :: DuplicateKeyError -> String
$cshowList :: [DuplicateKeyError] -> ShowS
showList :: [DuplicateKeyError] -> ShowS
Show)
instance Exception DuplicateKeyError where
displayException :: DuplicateKeyError -> String
displayException (MkDuplicateKeyError Text
k) = String
"Legend error: found duplicate key: " String -> ShowS
forall a. Semigroup a => a -> a -> a
<> Text -> String
unpack Text
k
linesToMap :: (HasCallStack, MonadThrow m) => Seq KeyVal -> m LegendMap
linesToMap :: forall (m :: Type -> Type).
(HasCallStack, MonadThrow m) =>
Seq KeyVal -> m LegendMap
linesToMap = (KeyVal -> m LegendMap -> m LegendMap)
-> m LegendMap -> Seq KeyVal -> m LegendMap
forall a b. (a -> b -> b) -> b -> Seq a -> b
forall (t :: Type -> Type) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr KeyVal -> m LegendMap -> m LegendMap
forall {m :: Type -> Type}.
MonadThrow m =>
KeyVal -> m LegendMap -> m LegendMap
f (LegendMap -> m LegendMap
forall a. a -> m a
forall (f :: Type -> Type) a. Applicative f => a -> f a
pure LegendMap
forall k v. HashMap k v
Map.empty)
where
f :: KeyVal -> m LegendMap -> m LegendMap
f (MkKeyVal Maybe EdgeArgs
es Text
k NESeq Text
v) = (Text, (NESeq Text, Maybe EdgeArgs)) -> m LegendMap -> m LegendMap
forall {m :: Type -> Type} {v}.
MonadThrow m =>
(Text, v) -> m (HashMap Text v) -> m (HashMap Text v)
insertPair (Text
k, (NESeq Text
v, Maybe EdgeArgs
es))
insertPair :: (Text, v) -> m (HashMap Text v) -> m (HashMap Text v)
insertPair (Text
key, v
cmd) m (HashMap Text v)
mMap = do
HashMap Text v
mp <- m (HashMap Text v)
mMap
case Text -> HashMap Text v -> Maybe v
forall k v. Hashable k => k -> HashMap k v -> Maybe v
Map.lookup Text
key HashMap Text v
mp of
Just v
_ -> DuplicateKeyError -> m (HashMap Text v)
forall e a. (HasCallStack, Exception e) => e -> m a
forall (m :: Type -> Type) e a.
(MonadThrow m, HasCallStack, Exception e) =>
e -> m a
throwM (DuplicateKeyError -> m (HashMap Text v))
-> DuplicateKeyError -> m (HashMap Text v)
forall a b. (a -> b) -> a -> b
$ Text -> DuplicateKeyError
MkDuplicateKeyError Text
key
Maybe v
Nothing -> HashMap Text v -> m (HashMap Text v)
forall a. a -> m a
forall (f :: Type -> Type) a. Applicative f => a -> f a
pure (HashMap Text v -> m (HashMap Text v))
-> HashMap Text v -> m (HashMap Text v)
forall a b. (a -> b) -> a -> b
$ Text -> v -> HashMap Text v -> HashMap Text v
forall k v. Hashable k => k -> v -> HashMap k v -> HashMap k v
Map.insert Text
key v
cmd HashMap Text v
mp
newtype CyclicKeyError = MkCyclicKeyError Text
deriving stock (CyclicKeyError -> CyclicKeyError -> Bool
(CyclicKeyError -> CyclicKeyError -> Bool)
-> (CyclicKeyError -> CyclicKeyError -> Bool) -> Eq CyclicKeyError
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: CyclicKeyError -> CyclicKeyError -> Bool
== :: CyclicKeyError -> CyclicKeyError -> Bool
$c/= :: CyclicKeyError -> CyclicKeyError -> Bool
/= :: CyclicKeyError -> CyclicKeyError -> Bool
Eq, Int -> CyclicKeyError -> ShowS
[CyclicKeyError] -> ShowS
CyclicKeyError -> String
(Int -> CyclicKeyError -> ShowS)
-> (CyclicKeyError -> String)
-> ([CyclicKeyError] -> ShowS)
-> Show CyclicKeyError
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> CyclicKeyError -> ShowS
showsPrec :: Int -> CyclicKeyError -> ShowS
$cshow :: CyclicKeyError -> String
show :: CyclicKeyError -> String
$cshowList :: [CyclicKeyError] -> ShowS
showList :: [CyclicKeyError] -> ShowS
Show)
instance Exception CyclicKeyError where
displayException :: CyclicKeyError -> String
displayException (MkCyclicKeyError Text
path) =
String
"Encountered cyclic definitions when translating commands: " String -> ShowS
forall a. Semigroup a => a -> a -> a
<> Text -> String
unpack Text
path
translateCommands ::
forall m.
( HasCallStack,
MonadThrow m
) =>
LegendMap ->
NESeq Text ->
Maybe EdgeArgs ->
m (Tuple2 (NESeq CommandP1) Edges)
translateCommands :: forall (m :: Type -> Type).
(HasCallStack, MonadThrow m) =>
LegendMap
-> NESeq Text -> Maybe EdgeArgs -> m (NESeq CommandP1, Edges)
translateCommands LegendMap
legendMap NESeq Text
commands =
LegendMap -> NESeq Text -> Maybe EdgeArgs -> m (LegendMap, Text)
forall (m :: Type -> Type).
(HasCallStack, MonadThrow m) =>
LegendMap -> NESeq Text -> Maybe EdgeArgs -> m (LegendMap, Text)
addCliLegend LegendMap
legendMap NESeq Text
commands (Maybe EdgeArgs -> m (LegendMap, Text))
-> ((LegendMap, Text) -> m (NESeq CommandP1, Edges))
-> Maybe EdgeArgs
-> m (NESeq CommandP1, Edges)
forall (m :: Type -> Type) a b c.
Monad m =>
(a -> m b) -> (b -> m c) -> a -> m c
>=> (LegendMap -> Text -> m (NESeq CommandP1, Edges))
-> (LegendMap, Text) -> m (NESeq CommandP1, Edges)
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry LegendMap -> Text -> m (NESeq CommandP1, Edges)
forall (m :: Type -> Type).
(HasCallStack, MonadThrow m) =>
LegendMap -> Text -> m (NESeq CommandP1, Edges)
translateMap
{-# INLINEABLE translateCommands #-}
translateMap ::
forall m.
( HasCallStack,
MonadThrow m
) =>
LegendMap ->
Text ->
m (Tuple2 (NESeq CommandP1) Edges)
translateMap :: forall (m :: Type -> Type).
(HasCallStack, MonadThrow m) =>
LegendMap -> Text -> m (NESeq CommandP1, Edges)
translateMap LegendMap
mp Text
initKey = do
let commands :: NESeq (CommandIndex, Text)
commands = NESeq Text -> NESeq (CommandIndex, Text)
forall a. NESeq a -> NESeq (CommandIndex, a)
indexSeq (NESeq Text -> NESeq (CommandIndex, Text))
-> NESeq Text -> NESeq (CommandIndex, Text)
forall a b. (a -> b) -> a -> b
$ Text -> NESeq Text
forall a. a -> NESeq a
NESeq.singleton Text
initKey
(NESeq CommandP1
cmds, Edges
edges, HashMap CommandIndex (CommandIndex, CommandIndex)
_) <- Maybe Text
-> HashSet Text
-> Builder
-> CommandIndex
-> NESeq (CommandIndex, Text)
-> m Acc
go Maybe Text
forall a. Maybe a
Nothing HashSet Text
forall a. HashSet a
Set.empty (Text -> Builder
LTBuilder.fromText Text
"") CommandIndex
forall m. MMonoid m => m
one NESeq (CommandIndex, Text)
commands
(NESeq CommandP1, Edges) -> m (NESeq CommandP1, Edges)
forall a. a -> m a
forall (f :: Type -> Type) a. Applicative f => a -> f a
pure (NESeq CommandP1
cmds, Edges -> Edges
Graph.sortEdges Edges
edges)
where
go ::
Maybe Text ->
HashSet Text ->
Builder ->
CommandIndex ->
NESeq (Tuple2 CommandIndex Text) ->
m Acc
go :: Maybe Text
-> HashSet Text
-> Builder
-> CommandIndex
-> NESeq (CommandIndex, Text)
-> m Acc
go Maybe Text
prevKey HashSet Text
foundKeys Builder
path CommandIndex
startIdx ((CommandIndex
origIdx, Text
line) :<|| Seq (CommandIndex, Text)
lines) = do
case Text -> LegendMap -> Maybe (NESeq Text, Maybe EdgeArgs)
forall k v. Hashable k => k -> HashMap k v -> Maybe v
Map.lookup Text
line LegendMap
mp of
Maybe (NESeq Text, Maybe EdgeArgs)
Nothing -> do
let cmds :: NESeq CommandP1
cmds = CommandP1 -> NESeq CommandP1
forall a. a -> NESeq a
NESeq.singleton (CommandIndex -> Maybe Text -> Text -> CommandP1
forall (p :: CommandPhase).
CommandIndex -> Maybe Text -> Text -> CommandP p
MkCommandP CommandIndex
startIdx Maybe Text
prevKey Text
line)
allData :: Acc
allData = (NESeq CommandP1
cmds, Edges
forall a. Monoid a => a
mempty, CommandIndex
-> (CommandIndex, CommandIndex)
-> HashMap CommandIndex (CommandIndex, CommandIndex)
forall k v. Hashable k => k -> v -> HashMap k v
Map.singleton CommandIndex
origIdx (CommandIndex
startIdx, CommandIndex
startIdx))
case Seq (CommandIndex, Text)
lines of
Seq (CommandIndex, Text)
Empty -> Acc -> m Acc
forall a. a -> m a
forall (f :: Type -> Type) a. Applicative f => a -> f a
pure Acc
allData
(CommandIndex, Text)
l :<| Seq (CommandIndex, Text)
ls -> (Acc
allData Acc -> Acc -> Acc
forall a. Semigroup a => a -> a -> a
<>) (Acc -> Acc) -> m Acc -> m Acc
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe Text
-> HashSet Text
-> Builder
-> CommandIndex
-> NESeq (CommandIndex, Text)
-> m Acc
go Maybe Text
prevKey HashSet Text
foundKeys Builder
path (CommandIndex -> CommandIndex
CT.succ CommandIndex
startIdx) ((CommandIndex, Text)
l (CommandIndex, Text)
-> Seq (CommandIndex, Text) -> NESeq (CommandIndex, Text)
forall a. a -> Seq a -> NESeq a
:<|| Seq (CommandIndex, Text)
ls)
Just (NESeq Text
vals, Maybe EdgeArgs
mEdges) -> case Maybe Text
maybeCyclicVal of
Just Text
cyclicVal -> do
let pathTxt :: Text
pathTxt = Builder -> Text -> Text -> Text
builderToPath Builder
path Text
line Text
cyclicVal
CyclicKeyError -> m Acc
forall e a. (HasCallStack, Exception e) => e -> m a
forall (m :: Type -> Type) e a.
(MonadThrow m, HasCallStack, Exception e) =>
e -> m a
throwM (CyclicKeyError -> m Acc) -> CyclicKeyError -> m Acc
forall a b. (a -> b) -> a -> b
$ Text -> CyclicKeyError
MkCyclicKeyError Text
pathTxt
Maybe Text
Nothing -> do
let mPrevKey :: Maybe Text
mPrevKey =
if NESeq Text -> Int
forall a. NESeq a -> Int
forall (t :: Type -> Type) a. Foldable t => t a -> Int
length NESeq Text
vals Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
1 Bool -> Bool -> Bool
|| Text
line Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
== Text
initKey
then Maybe Text
forall a. Maybe a
Nothing
else Text -> Maybe Text
forall a. a -> Maybe a
Just Text
line
valsIx :: NESeq (CommandIndex, Text)
valsIx = NESeq Text -> NESeq (CommandIndex, Text)
forall a. NESeq a -> NESeq (CommandIndex, a)
indexSeq NESeq Text
vals
(NESeq CommandP1
subCmds, Edges
subEdges, HashMap CommandIndex (CommandIndex, CommandIndex)
subCmdIdxMap) <- Maybe Text
-> HashSet Text
-> Builder
-> CommandIndex
-> NESeq (CommandIndex, Text)
-> m Acc
go Maybe Text
mPrevKey HashSet Text
foundKeys' Builder
path' CommandIndex
startIdx NESeq (CommandIndex, Text)
valsIx
let
numCmdsIdx :: NonNegative Int
numCmdsIdx = Int -> NonNegative Int
forall a.
(AMonoid a, HasCallStack, Ord a, Show a) =>
a -> NonNegative a
unsafeNonNegative (Int -> NonNegative Int) -> Int -> NonNegative Int
forall a b. (a -> b) -> a -> b
$ NESeq CommandP1 -> Int
forall a. NESeq a -> Int
forall (t :: Type -> Type) a. Foldable t => t a -> Int
length NESeq CommandP1
subCmds Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1
endIdx :: CommandIndex
endIdx = CommandIndex -> NonNegative Int -> CommandIndex
CT.addNN CommandIndex
startIdx NonNegative Int
numCmdsIdx
idxMap :: HashMap CommandIndex (CommandIndex, CommandIndex)
idxMap = CommandIndex
-> (CommandIndex, CommandIndex)
-> HashMap CommandIndex (CommandIndex, CommandIndex)
forall k v. Hashable k => k -> v -> HashMap k v
Map.singleton CommandIndex
origIdx (CommandIndex
startIdx, CommandIndex
endIdx)
errKeyName :: Text
errKeyName =
if Text
line Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
== Text
initKey
then Text
"command_line"
else Text
line
Edges
repairedEdges <- case Maybe EdgeArgs
mEdges of
Maybe EdgeArgs
Nothing -> Edges -> m Edges
forall a. a -> m a
forall (f :: Type -> Type) a. Applicative f => a -> f a
pure Edges
forall a. Monoid a => a
mempty
Just (EdgeArgsSequential EdgeSequential
s) ->
Text
-> Edges
-> HashMap CommandIndex (CommandIndex, CommandIndex)
-> m Edges
forall (m :: Type -> Type).
(HasCallStack, MonadThrow m) =>
Text
-> Edges
-> HashMap CommandIndex (CommandIndex, CommandIndex)
-> m Edges
repairEdges Text
errKeyName (EdgeSequential -> NESeq Text -> Edges
mkSequentialEdges EdgeSequential
s NESeq Text
vals) HashMap CommandIndex (CommandIndex, CommandIndex)
subCmdIdxMap
Just (EdgeArgsList Edges
es) -> Text
-> Edges
-> HashMap CommandIndex (CommandIndex, CommandIndex)
-> m Edges
forall (m :: Type -> Type).
(HasCallStack, MonadThrow m) =>
Text
-> Edges
-> HashMap CommandIndex (CommandIndex, CommandIndex)
-> m Edges
repairEdges Text
errKeyName Edges
es HashMap CommandIndex (CommandIndex, CommandIndex)
subCmdIdxMap
let newEdges :: Edges
newEdges = Edges
repairedEdges Edges -> Edges -> Edges
forall a. Semigroup a => a -> a -> a
<> Edges
subEdges
allData :: Acc
allData = (NESeq CommandP1
subCmds, Edges
newEdges, HashMap CommandIndex (CommandIndex, CommandIndex)
idxMap)
case Seq (CommandIndex, Text)
lines of
Seq (CommandIndex, Text)
Empty -> Acc -> m Acc
forall a. a -> m a
forall (f :: Type -> Type) a. Applicative f => a -> f a
pure Acc
allData
(CommandIndex, Text)
l :<| Seq (CommandIndex, Text)
ls -> do
let newIdx :: CommandIndex
newIdx = CommandIndex
startIdx CommandIndex -> CommandIndex -> CommandIndex
forall s. ASemigroup s => s -> s -> s
.+. HasCallStack => Int -> CommandIndex
Int -> CommandIndex
CT.unsafeFromInt (NESeq CommandP1 -> Int
forall a. NESeq a -> Int
forall (t :: Type -> Type) a. Foldable t => t a -> Int
length NESeq CommandP1
subCmds)
(Acc
allData Acc -> Acc -> Acc
forall a. Semigroup a => a -> a -> a
<>) (Acc -> Acc) -> m Acc -> m Acc
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe Text
-> HashSet Text
-> Builder
-> CommandIndex
-> NESeq (CommandIndex, Text)
-> m Acc
go Maybe Text
prevKey HashSet Text
foundKeys Builder
path CommandIndex
newIdx ((CommandIndex, Text)
l (CommandIndex, Text)
-> Seq (CommandIndex, Text) -> NESeq (CommandIndex, Text)
forall a. a -> Seq a -> NESeq a
:<|| Seq (CommandIndex, Text)
ls)
where
foundKeys' :: HashSet Text
foundKeys' = Text -> HashSet Text -> HashSet Text
forall a. Hashable a => a -> HashSet a -> HashSet a
Set.insert Text
line HashSet Text
foundKeys
intersect :: HashSet Text
intersect = HashSet Text -> HashSet Text -> HashSet Text
forall a. Eq a => HashSet a -> HashSet a -> HashSet a
Set.intersection HashSet Text
foundKeys (NESeq Text -> HashSet Text
neToSet NESeq Text
vals)
maybeCyclicVal :: Maybe Text
maybeCyclicVal = [Text] -> Maybe Text
forall (f :: Type -> Type) a. Foldable f => f a -> Maybe a
headMaybe ([Text] -> Maybe Text) -> [Text] -> Maybe Text
forall a b. (a -> b) -> a -> b
$ HashSet Text -> [Text]
forall a. HashSet a -> [a]
Set.toList HashSet Text
intersect
path' :: Builder
path' =
if Text
line Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
== Text
initKey
then Builder
""
else Builder
path Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Text -> Builder
LTBuilder.fromText Text
line Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Builder
" -> "
neToSet :: NESeq Text -> HashSet Text
neToSet = [Text] -> HashSet Text
forall a. Hashable a => [a] -> HashSet a
Set.fromList ([Text] -> HashSet Text)
-> (NESeq Text -> [Text]) -> NESeq Text -> HashSet Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> Type) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. NESeq Text -> [Text]
forall a. NESeq a -> [a]
forall (t :: Type -> Type) a. Foldable t => t a -> [a]
toList
{-# INLINEABLE translateMap #-}
indexSeq :: NESeq a -> NESeq (Tuple2 CommandIndex a)
indexSeq :: forall a. NESeq a -> NESeq (CommandIndex, a)
indexSeq NESeq a
xs = NESeq CommandIndex -> NESeq a -> NESeq (CommandIndex, a)
forall a b. NESeq a -> NESeq b -> NESeq (a, b)
NESeq.zip (HasCallStack => Int -> CommandIndex
Int -> CommandIndex
CT.unsafeFromInt (Int -> CommandIndex) -> NESeq Int -> NESeq CommandIndex
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
<$> [Int] -> NESeq Int
forall a. HasCallStack => [a] -> NESeq a
unsafeListToNESeq [Int
Item [Int]
1 .. NESeq a -> Int
forall a. NESeq a -> Int
forall (t :: Type -> Type) a. Foldable t => t a -> Int
length NESeq a
xs]) NESeq a
xs
repairEdges ::
( HasCallStack,
MonadThrow m
) =>
Text ->
Edges ->
HashMap CommandIndex (Tuple2 CommandIndex CommandIndex) ->
m Edges
repairEdges :: forall (m :: Type -> Type).
(HasCallStack, MonadThrow m) =>
Text
-> Edges
-> HashMap CommandIndex (CommandIndex, CommandIndex)
-> m Edges
repairEdges Text
key (MkEdges Seq Edge
es) HashMap CommandIndex (CommandIndex, CommandIndex)
idxMap = Seq Edge -> Edges
MkEdges (Seq Edge -> Edges) -> m (Seq Edge) -> m Edges
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
<$> (Edge -> m (Seq Edge) -> m (Seq Edge))
-> m (Seq Edge) -> Seq Edge -> m (Seq Edge)
forall a b. (a -> b -> b) -> b -> Seq a -> b
forall (t :: Type -> Type) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr Edge -> m (Seq Edge) -> m (Seq Edge)
mapEdge (Seq Edge -> m (Seq Edge)
forall a. a -> m a
forall (f :: Type -> Type) a. Applicative f => a -> f a
pure Seq Edge
forall a. Seq a
Empty) Seq Edge
es
where
mapEdge :: Edge -> m (Seq Edge) -> m (Seq Edge)
mapEdge (CommandIndex
src, CommandIndex
dest, EdgeLabel
lbl) m (Seq Edge)
mAcc = do
(CommandIndex
srcStart, CommandIndex
srcEnd) <- CommandIndex -> m (CommandIndex, CommandIndex)
lookupEdge CommandIndex
src
(CommandIndex
destStart, CommandIndex
destEnd) <- CommandIndex -> m (CommandIndex, CommandIndex)
lookupEdge CommandIndex
dest
let newEdges :: Seq Edge
newEdges :: Seq Edge
newEdges =
[ (CommandIndex
s, CommandIndex
d, EdgeLabel
lbl)
| CommandIndex
s <- [Item (Seq CommandIndex)
CommandIndex
srcStart .. Item (Seq CommandIndex)
CommandIndex
srcEnd],
CommandIndex
d <- [Item (Seq CommandIndex)
CommandIndex
destStart .. Item (Seq CommandIndex)
CommandIndex
destEnd]
]
(Seq Edge
newEdges Seq Edge -> Seq Edge -> Seq Edge
forall a. Semigroup a => a -> a -> a
<>) (Seq Edge -> Seq Edge) -> m (Seq Edge) -> m (Seq Edge)
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
<$> m (Seq Edge)
mAcc
where
lookupEdge :: CommandIndex -> m (CommandIndex, CommandIndex)
lookupEdge CommandIndex
i = case CommandIndex
-> HashMap CommandIndex (CommandIndex, CommandIndex)
-> Maybe (CommandIndex, CommandIndex)
forall k v. Hashable k => k -> HashMap k v -> Maybe v
Map.lookup CommandIndex
i HashMap CommandIndex (CommandIndex, CommandIndex)
idxMap of
Maybe (CommandIndex, CommandIndex)
Nothing ->
Text -> m (CommandIndex, CommandIndex)
forall (m :: Type -> Type) a.
(HasCallStack, MonadThrow m) =>
Text -> m a
throwText
(Text -> m (CommandIndex, CommandIndex))
-> Text -> m (CommandIndex, CommandIndex)
forall a b. (a -> b) -> a -> b
$ [Text] -> Text
forall a. Monoid a => [a] -> a
mconcat
[ Text
Item [Text]
"Key ",
Text
Item [Text]
key,
Text
Item [Text]
": Index '",
CommandIndex -> Text
forall a. Pretty a => a -> Text
prettyToText CommandIndex
i,
Text
Item [Text]
"' in edge '",
CommandIndex -> Text
forall a. Pretty a => a -> Text
prettyToText CommandIndex
src,
Text
Item [Text]
" ",
EdgeLabel -> Text
forall s. IsString s => EdgeLabel -> s
Graph.displayEdgeLabel EdgeLabel
lbl,
Text
Item [Text]
" ",
CommandIndex -> Text
forall a. Pretty a => a -> Text
prettyToText CommandIndex
dest,
Text
Item [Text]
"' is out-of-bounds."
]
Just (CommandIndex
s, CommandIndex
e) -> (CommandIndex, CommandIndex) -> m (CommandIndex, CommandIndex)
forall a. a -> m a
forall (f :: Type -> Type) a. Applicative f => a -> f a
pure (CommandIndex
s, CommandIndex
e)
{-# INLINEABLE repairEdges #-}
mkSequentialEdges :: EdgeSequential -> NESeq Text -> Edges
mkSequentialEdges :: EdgeSequential -> NESeq Text -> Edges
mkSequentialEdges EdgeSequential
eseq =
Seq Edge -> Edges
MkEdges
(Seq Edge -> Edges)
-> (NESeq Text -> Seq Edge) -> NESeq Text -> Edges
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> Type) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Seq Edge -> Seq Edge
forall {a}. Seq a -> Seq a
dropLast
(Seq Edge -> Seq Edge)
-> (NESeq Text -> Seq Edge) -> NESeq Text -> Seq Edge
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> Type) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. ((CommandIndex, Text) -> Edge)
-> Seq (CommandIndex, Text) -> Seq Edge
forall a b. (a -> b) -> Seq a -> Seq b
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
fmap (CommandIndex, Text) -> Edge
toEdge
(Seq (CommandIndex, Text) -> Seq Edge)
-> (NESeq Text -> Seq (CommandIndex, Text))
-> NESeq Text
-> Seq Edge
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> Type) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. NESeq (CommandIndex, Text) -> Seq (CommandIndex, Text)
forall a. NESeq a -> Seq a
NESeq.toSeq
(NESeq (CommandIndex, Text) -> Seq (CommandIndex, Text))
-> (NESeq Text -> NESeq (CommandIndex, Text))
-> NESeq Text
-> Seq (CommandIndex, Text)
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> Type) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. NESeq Text -> NESeq (CommandIndex, Text)
forall a. NESeq a -> NESeq (CommandIndex, a)
indexSeq
where
toEdge :: (CommandIndex, Text) -> Edge
toEdge (CommandIndex
idx, Text
_) = (CommandIndex
idx, CommandIndex -> CommandIndex
CT.succ CommandIndex
idx, EdgeLabel
lbl)
lbl :: EdgeLabel
lbl = case EdgeSequential
eseq of
EdgeSequential
EdgeSequentialAnd -> EdgeLabel
EdgeAnd
EdgeSequential
EdgeSequentialOr -> EdgeLabel
EdgeOr
EdgeSequential
EdgeSequentialAny -> EdgeLabel
EdgeAny
dropLast :: Seq a -> Seq a
dropLast Seq a
Empty = Seq a
forall a. Seq a
Empty
dropLast (a
_ :<| Seq a
Empty) = Seq a
forall a. Seq a
Empty
dropLast (a
x :<| Seq a
ys) = a
x a -> Seq a -> Seq a
forall a. a -> Seq a -> Seq a
:<| Seq a -> Seq a
dropLast Seq a
ys
type Acc =
Tuple3
(NESeq CommandP1)
Edges
(HashMap CommandIndex (CommandIndex, CommandIndex))
builderToPath :: Builder -> Text -> Text -> Text
builderToPath :: Builder -> Text -> Text -> Text
builderToPath Builder
path Text
l Text
v =
LazyText -> Text
LazyT.toStrict
(LazyText -> Text) -> LazyText -> Text
forall a b. (a -> b) -> a -> b
$ Builder -> LazyText
LTBuilder.toLazyText
(Builder -> LazyText) -> Builder -> LazyText
forall a b. (a -> b) -> a -> b
$ Builder
path
Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Text -> Builder
LTBuilder.fromText Text
l
Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Builder
" -> "
Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Text -> Builder
LTBuilder.fromText Text
v
addCliLegend ::
(HasCallStack, MonadThrow m) =>
LegendMap ->
NESeq Text ->
Maybe EdgeArgs ->
m (Tuple2 LegendMap Text)
addCliLegend :: forall (m :: Type -> Type).
(HasCallStack, MonadThrow m) =>
LegendMap -> NESeq Text -> Maybe EdgeArgs -> m (LegendMap, Text)
addCliLegend LegendMap
legendMap NESeq Text
commands Maybe EdgeArgs
mCliEdgeArgs = do
Text
unmappedKey <- LegendMap -> NESeq Text -> m Text
forall (m :: Type -> Type).
(HasCallStack, MonadThrow m) =>
LegendMap -> NESeq Text -> m Text
findUnmappedKey LegendMap
legendMap NESeq Text
commands
pure (Text -> (NESeq Text, Maybe EdgeArgs) -> LegendMap -> LegendMap
forall k v. Hashable k => k -> v -> HashMap k v -> HashMap k v
Map.insert Text
unmappedKey (NESeq Text
commands, Maybe EdgeArgs
mCliEdgeArgs) LegendMap
legendMap, Text
unmappedKey)
{-# INLINEABLE addCliLegend #-}
findUnmappedKey ::
forall m.
(HasCallStack, MonadThrow m) =>
LegendMap ->
NESeq Text ->
m Text
findUnmappedKey :: forall (m :: Type -> Type).
(HasCallStack, MonadThrow m) =>
LegendMap -> NESeq Text -> m Text
findUnmappedKey LegendMap
legendMap NESeq Text
commands = Word16 -> m Text
go Word16
0
where
commandSet :: HashSet Text
commandSet = [Text] -> HashSet Text
forall a. Hashable a => [a] -> HashSet a
Set.fromList (NESeq Text -> [Text]
forall a. NESeq a -> [a]
forall (t :: Type -> Type) a. Foldable t => t a -> [a]
toList NESeq Text
commands)
mx :: Word16
mx = Word16
forall a. Bounded a => a
maxBound
pfx :: Text
pfx = Text
"shrun_init_key_"
unmapped :: Text -> Bool
unmapped Text
t =
Bool -> Bool
not (Text -> LegendMap -> Bool
forall k a. Hashable k => k -> HashMap k a -> Bool
Map.member Text
t LegendMap
legendMap Bool -> Bool -> Bool
|| Text -> HashSet Text -> Bool
forall a. Hashable a => a -> HashSet a -> Bool
Set.member Text
t HashSet Text
commandSet)
go :: Word16 -> m Text
go :: Word16 -> m Text
go Word16
i
| Word16
i Word16 -> Word16 -> Bool
forall a. Eq a => a -> a -> Bool
== Word16
mx =
Text -> m Text
forall (m :: Type -> Type) a.
(HasCallStack, MonadThrow m) =>
Text -> m a
throwText
(Text -> m Text) -> Text -> m Text
forall a b. (a -> b) -> a -> b
$ [Text] -> Text
forall a. Monoid a => [a] -> a
mconcat
[ Text
Item [Text]
"Found too many ",
Text
Item [Text]
pfx,
Text
Item [Text]
"<i> keys in legend. Expected at least one free in range (0, ",
Word16 -> Text
forall a. Show a => a -> Text
showt Word16
mx,
Text
Item [Text]
")."
]
| Text -> Bool
unmapped Text
key = Text -> m Text
forall a. a -> m a
forall (f :: Type -> Type) a. Applicative f => a -> f a
pure Text
key
| Bool
otherwise = Word16 -> m Text
go (Word16
i Word16 -> Word16 -> Word16
forall a. Num a => a -> a -> a
+ Word16
1)
where
key :: Text
key = Text
pfx Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Word16 -> Text
forall a. Show a => a -> Text
showt Word16
i
{-# INLINEABLE findUnmappedKey #-}