module Language.Lexer.Tlex.Pipeline.Nfa2Dfa (
    nfa2Dfa,
) where

import           Language.Lexer.Tlex.Prelude

import qualified Data.HashMap.Strict                 as HashMap
import qualified Data.IntMap.Strict                  as IntMap
import qualified Data.IntSet                         as IntSet
import qualified Language.Lexer.Tlex.Data.EnumMap    as EnumMap
import qualified Language.Lexer.Tlex.Machine.DFA     as DFA
import qualified Language.Lexer.Tlex.Machine.NFA     as NFA
import qualified Language.Lexer.Tlex.Machine.Pattern as Pattern
import qualified Language.Lexer.Tlex.Machine.State   as MState


nfa2Dfa :: NFA.NFA a -> DFA.DFA a
nfa2Dfa :: NFA a -> DFA a
nfa2Dfa NFA a
nfa = DFABuilder a () -> DFA a
forall m. DFABuilder m () -> DFA m
DFA.buildDFA
    do (DFABuilderContext a -> DFABuilderContext a) -> DFABuilder a ()
forall (m :: * -> *) s. Monad m => (s -> s) -> StateT s m ()
modify' \DFABuilderContext a
dfaBuilderCtx0 -> Nfa2DfaContext a -> DFABuilderContext a
forall m. Nfa2DfaContext m -> DFABuilderContext m
nfa2DfaCtxDFABuilderCtx
        do State (Nfa2DfaContext a) () -> Nfa2DfaContext a -> Nfa2DfaContext a
forall s a. State s a -> s -> s
execState
            do NFA a -> State (Nfa2DfaContext a) ()
forall m. NFA m -> Nfa2DfaM m ()
nfa2DfaM NFA a
nfa
            do Nfa2DfaContext :: forall m.
HashMap StateSet StateNum
-> DFABuilderContext m -> Nfa2DfaContext m
Nfa2DfaContext
                { $sel:nfa2DfaCtxStateMap:Nfa2DfaContext :: HashMap StateSet StateNum
nfa2DfaCtxStateMap = HashMap StateSet StateNum
forall k v. HashMap k v
HashMap.empty
                , $sel:nfa2DfaCtxDFABuilderCtx:Nfa2DfaContext :: DFABuilderContext a
nfa2DfaCtxDFABuilderCtx = DFABuilderContext a
dfaBuilderCtx0
                }


data Nfa2DfaContext m = Nfa2DfaContext
    { Nfa2DfaContext m -> HashMap StateSet StateNum
nfa2DfaCtxStateMap      :: HashMap.HashMap MState.StateSet MState.StateNum
    , Nfa2DfaContext m -> DFABuilderContext m
nfa2DfaCtxDFABuilderCtx :: DFA.DFABuilderContext m
    }

type Nfa2DfaM m = State (Nfa2DfaContext m)

liftBuilderOp :: DFA.DFABuilder m a -> Nfa2DfaM m a
liftBuilderOp :: DFABuilder m a -> Nfa2DfaM m a
liftBuilderOp DFABuilder m a
builder = do
    Nfa2DfaContext m
ctx0 <- StateT (Nfa2DfaContext m) Identity (Nfa2DfaContext m)
forall (m :: * -> *) s. Monad m => StateT s m s
get
    let (a
x, DFABuilderContext m
builderCtx1) = DFABuilder m a -> DFABuilderContext m -> (a, DFABuilderContext m)
forall s a. State s a -> s -> (a, s)
runState DFABuilder m a
builder do Nfa2DfaContext m -> DFABuilderContext m
forall m. Nfa2DfaContext m -> DFABuilderContext m
nfa2DfaCtxDFABuilderCtx Nfa2DfaContext m
ctx0
    Nfa2DfaContext m -> StateT (Nfa2DfaContext m) Identity ()
forall (m :: * -> *) s. Monad m => s -> StateT s m ()
put do Nfa2DfaContext m
ctx0
            { $sel:nfa2DfaCtxDFABuilderCtx:Nfa2DfaContext :: DFABuilderContext m
nfa2DfaCtxDFABuilderCtx = DFABuilderContext m
builderCtx1
            }
    a -> Nfa2DfaM m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure a
x

registerNewState :: MState.StateSet -> Nfa2DfaM m MState.StateNum
registerNewState :: StateSet -> Nfa2DfaM m StateNum
registerNewState StateSet
nfaSs = do
    StateNum
dfaSn <- DFABuilder m StateNum -> Nfa2DfaM m StateNum
forall m a. DFABuilder m a -> Nfa2DfaM m a
liftBuilderOp DFABuilder m StateNum
forall m. DFABuilder m StateNum
DFA.newStateNum
    (Nfa2DfaContext m -> Nfa2DfaContext m)
-> StateT (Nfa2DfaContext m) Identity ()
forall (m :: * -> *) s. Monad m => (s -> s) -> StateT s m ()
modify' \ctx0 :: Nfa2DfaContext m
ctx0@Nfa2DfaContext{ HashMap StateSet StateNum
nfa2DfaCtxStateMap :: HashMap StateSet StateNum
$sel:nfa2DfaCtxStateMap:Nfa2DfaContext :: forall m. Nfa2DfaContext m -> HashMap StateSet StateNum
nfa2DfaCtxStateMap } -> Nfa2DfaContext m
ctx0
        { $sel:nfa2DfaCtxStateMap:Nfa2DfaContext :: HashMap StateSet StateNum
nfa2DfaCtxStateMap = StateSet
-> StateNum
-> HashMap StateSet StateNum
-> HashMap StateSet StateNum
forall k v.
(Eq k, Hashable k) =>
k -> v -> HashMap k v -> HashMap k v
HashMap.insert StateSet
nfaSs StateNum
dfaSn HashMap StateSet StateNum
nfa2DfaCtxStateMap
        }
    StateNum -> Nfa2DfaM m StateNum
forall (f :: * -> *) a. Applicative f => a -> f a
pure StateNum
dfaSn

nfa2DfaM :: NFA.NFA m -> Nfa2DfaM m ()
nfa2DfaM :: NFA m -> Nfa2DfaM m ()
nfa2DfaM NFA.NFA{ [(StateNum, StartState)]
$sel:nfaInitials:NFA :: forall a. NFA a -> [(StateNum, StartState)]
nfaInitials :: [(StateNum, StartState)]
nfaInitials, StateArray (NFAState m)
$sel:nfaTrans:NFA :: forall a. NFA a -> StateArray (NFAState a)
nfaTrans :: StateArray (NFAState m)
nfaTrans } = do
    [(StateNum, StateSet)]
initials <- [(StateNum, StartState)]
-> ((StateNum, StartState)
    -> StateT (Nfa2DfaContext m) Identity (StateNum, StateSet))
-> StateT (Nfa2DfaContext m) Identity [(StateNum, StateSet)]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
t a -> (a -> m b) -> m (t b)
forM [(StateNum, StartState)]
nfaInitials \(StateNum
nfaSn, StartState
s) -> do
        let nfaSs :: StateSet
nfaSs = StateNum -> StateSet
buildNfaSs StateNum
nfaSn
        StateNum
dfaSn <- StateSet -> Nfa2DfaM m StateNum
forall m. StateSet -> Nfa2DfaM m StateNum
registerNewState StateSet
nfaSs
        DFABuilder m () -> Nfa2DfaM m ()
forall m a. DFABuilder m a -> Nfa2DfaM m a
liftBuilderOp do StateNum -> StartState -> DFABuilder m ()
forall m. StateNum -> StartState -> DFABuilder m ()
DFA.initial StateNum
dfaSn StartState
s
        (StateNum, StateSet)
-> StateT (Nfa2DfaContext m) Identity (StateNum, StateSet)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (StateNum
dfaSn, StateSet
nfaSs)

    [(StateNum, StateSet)] -> Nfa2DfaM m ()
buildStateMap [(StateNum, StateSet)]
initials
    where
        buildNfaSs :: StateNum -> StateSet
buildNfaSs StateNum
nfaSn =
            let nfaState :: NFAState m
nfaState = StateArray (NFAState m)
nfaTrans StateArray (NFAState m) -> StateNum -> NFAState m
forall a. StateArray a -> StateNum -> a
`MState.indexArray` StateNum
nfaSn
            in [StateNum] -> StateSet
MState.listToSet do NFAState m -> [StateNum]
forall a. NFAState a -> [StateNum]
NFA.nstEpsilonTrans NFAState m
nfaState

        insertNfaSn :: StateNum -> StateSet -> StateSet
insertNfaSn StateNum
nfaSn0 StateSet
nfaSs0 =
            let nfaState0 :: NFAState m
nfaState0 = StateArray (NFAState m)
nfaTrans StateArray (NFAState m) -> StateNum -> NFAState m
forall a. StateArray a -> StateNum -> a
`MState.indexArray` StateNum
nfaSn0
            in (StateSet -> StateNum -> StateSet)
-> StateSet -> [StateNum] -> StateSet
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl'
                do \StateSet
nfaSs StateNum
nfaSn -> StateNum -> StateSet -> StateSet
MState.insertSet StateNum
nfaSn StateSet
nfaSs
                do StateSet
nfaSs0
                do NFAState m -> [StateNum]
forall a. NFAState a -> [StateNum]
NFA.nstEpsilonTrans NFAState m
nfaState0

        buildStateMap :: [(StateNum, StateSet)] -> Nfa2DfaM m ()
buildStateMap = \case
            []                   -> () -> Nfa2DfaM m ()
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
            (StateNum
dfaSn, StateSet
nfaSs):[(StateNum, StateSet)]
rest0 -> do
                ([(StateNum, StateSet)]
rest1, DFAState m
dst) <- StateSet
-> [(StateNum, StateSet)]
-> StateT
     (Nfa2DfaContext m) Identity ([(StateNum, StateSet)], DFAState m)
buildDFAState StateSet
nfaSs [(StateNum, StateSet)]
rest0
                DFABuilder m () -> Nfa2DfaM m ()
forall m a. DFABuilder m a -> Nfa2DfaM m a
liftBuilderOp do StateNum -> DFAState m -> DFABuilder m ()
forall m. StateNum -> DFAState m -> DFABuilder m ()
DFA.insertTrans StateNum
dfaSn DFAState m
dst
                [(StateNum, StateSet)] -> Nfa2DfaM m ()
buildStateMap [(StateNum, StateSet)]
rest1

        buildDFAState :: StateSet
-> [(StateNum, StateSet)]
-> StateT
     (Nfa2DfaContext m) Identity ([(StateNum, StateSet)], DFAState m)
buildDFAState StateSet
nfaSs0 [(StateNum, StateSet)]
rest0 = do
            (EnumMap AcceptPriority (Accept m)
accs1, EnumMap Key StateSet
trans1, StateSet
otherTrans1) <- ((EnumMap AcceptPriority (Accept m), EnumMap Key StateSet,
  StateSet)
 -> StateNum
 -> StateT
      (Nfa2DfaContext m)
      Identity
      (EnumMap AcceptPriority (Accept m), EnumMap Key StateSet,
       StateSet))
-> (EnumMap AcceptPriority (Accept m), EnumMap Key StateSet,
    StateSet)
-> [StateNum]
-> StateT
     (Nfa2DfaContext m)
     Identity
     (EnumMap AcceptPriority (Accept m), EnumMap Key StateSet, StateSet)
forall (t :: * -> *) (m :: * -> *) b a.
(Foldable t, Monad m) =>
(b -> a -> m b) -> b -> t a -> m b
foldM
                do \(EnumMap AcceptPriority (Accept m)
accs, EnumMap Key StateSet
trans, StateSet
otherTrans) StateNum
nfaSn ->
                    let nfaState :: NFAState m
nfaState = StateArray (NFAState m)
nfaTrans StateArray (NFAState m) -> StateNum -> NFAState m
forall a. StateArray a -> StateNum -> a
`MState.indexArray` StateNum
nfaSn
                        accs' :: EnumMap AcceptPriority (Accept m)
accs' = (EnumMap AcceptPriority (Accept m)
 -> Accept m -> EnumMap AcceptPriority (Accept m))
-> EnumMap AcceptPriority (Accept m)
-> [Accept m]
-> EnumMap AcceptPriority (Accept m)
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl'
                                do \EnumMap AcceptPriority (Accept m)
m Accept m
acc -> AcceptPriority
-> Accept m
-> EnumMap AcceptPriority (Accept m)
-> EnumMap AcceptPriority (Accept m)
forall k a. Enum k => k -> a -> EnumMap k a -> EnumMap k a
EnumMap.insert
                                    do Accept m -> AcceptPriority
forall a. Accept a -> AcceptPriority
Pattern.accPriority Accept m
acc
                                    do Accept m
acc
                                    do EnumMap AcceptPriority (Accept m)
m
                                do EnumMap AcceptPriority (Accept m)
accs
                                do NFAState m -> [Accept m]
forall a. NFAState a -> [Accept a]
NFA.nstAccepts NFAState m
nfaState
                        (EnumMap Key StateSet
trans', StateSet
otherTrans') = ((EnumMap Key StateSet, StateSet)
 -> NFAStateTrans -> (EnumMap Key StateSet, StateSet))
-> (EnumMap Key StateSet, StateSet)
-> [NFAStateTrans]
-> (EnumMap Key StateSet, StateSet)
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' (EnumMap Key StateSet, StateSet)
-> NFAStateTrans -> (EnumMap Key StateSet, StateSet)
insertTrans (EnumMap Key StateSet
trans, StateSet
otherTrans)
                                                    do NFAState m -> [NFAStateTrans]
forall a. NFAState a -> [NFAStateTrans]
NFA.nstTrans NFAState m
nfaState
                    in (EnumMap AcceptPriority (Accept m), EnumMap Key StateSet, StateSet)
-> StateT
     (Nfa2DfaContext m)
     Identity
     (EnumMap AcceptPriority (Accept m), EnumMap Key StateSet, StateSet)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (EnumMap AcceptPriority (Accept m)
accs', EnumMap Key StateSet
trans', StateSet
otherTrans')
                do (EnumMap AcceptPriority (Accept m)
forall k a. Enum k => EnumMap k a
EnumMap.empty, EnumMap Key StateSet
forall k a. Enum k => EnumMap k a
EnumMap.empty, StateSet
MState.emptySet)
                do StateSet -> [StateNum]
MState.setToList StateSet
nfaSs0

            let getOrRegisterNfaSs :: StateSet
-> [(StateNum, StateSet)]
-> StateT
     (Nfa2DfaContext m) Identity ([(StateNum, StateSet)], StateNum)
getOrRegisterNfaSs StateSet
nfaSs [(StateNum, StateSet)]
rest = do
                    Nfa2DfaContext m
ctx0 <- StateT (Nfa2DfaContext m) Identity (Nfa2DfaContext m)
forall (m :: * -> *) s. Monad m => StateT s m s
get
                    let stateMap :: HashMap StateSet StateNum
stateMap = Nfa2DfaContext m -> HashMap StateSet StateNum
forall m. Nfa2DfaContext m -> HashMap StateSet StateNum
nfa2DfaCtxStateMap Nfa2DfaContext m
ctx0
                    case StateSet -> HashMap StateSet StateNum -> Maybe StateNum
forall k v. (Eq k, Hashable k) => k -> HashMap k v -> Maybe v
HashMap.lookup StateSet
nfaSs HashMap StateSet StateNum
stateMap of
                        Just StateNum
dfaSn -> ([(StateNum, StateSet)], StateNum)
-> StateT
     (Nfa2DfaContext m) Identity ([(StateNum, StateSet)], StateNum)
forall (f :: * -> *) a. Applicative f => a -> f a
pure ([(StateNum, StateSet)]
rest, StateNum
dfaSn)
                        Maybe StateNum
Nothing -> do
                            StateNum
dfaSn <- StateSet -> Nfa2DfaM m StateNum
forall m. StateSet -> Nfa2DfaM m StateNum
registerNewState StateSet
nfaSs
                            ([(StateNum, StateSet)], StateNum)
-> StateT
     (Nfa2DfaContext m) Identity ([(StateNum, StateSet)], StateNum)
forall (f :: * -> *) a. Applicative f => a -> f a
pure ((StateNum
dfaSn, StateSet
nfaSs)(StateNum, StateSet)
-> [(StateNum, StateSet)] -> [(StateNum, StateSet)]
forall a. a -> [a] -> [a]
:[(StateNum, StateSet)]
rest, StateNum
dfaSn)

            ([(StateNum, StateSet)]
rest1, IntMap StateNum
trans2) <- (([(StateNum, StateSet)], IntMap StateNum)
 -> (Key, StateSet)
 -> StateT
      (Nfa2DfaContext m)
      Identity
      ([(StateNum, StateSet)], IntMap StateNum))
-> ([(StateNum, StateSet)], IntMap StateNum)
-> [(Key, StateSet)]
-> StateT
     (Nfa2DfaContext m)
     Identity
     ([(StateNum, StateSet)], IntMap StateNum)
forall (t :: * -> *) (m :: * -> *) b a.
(Foldable t, Monad m) =>
(b -> a -> m b) -> b -> t a -> m b
foldM
                do \([(StateNum, StateSet)]
rest, IntMap StateNum
trans) (Key
c, StateSet
nfaSs) -> do
                    ([(StateNum, StateSet)]
rest', StateNum
dfaSn) <- StateSet
-> [(StateNum, StateSet)]
-> StateT
     (Nfa2DfaContext m) Identity ([(StateNum, StateSet)], StateNum)
forall m.
StateSet
-> [(StateNum, StateSet)]
-> StateT
     (Nfa2DfaContext m) Identity ([(StateNum, StateSet)], StateNum)
getOrRegisterNfaSs StateSet
nfaSs [(StateNum, StateSet)]
rest
                    ([(StateNum, StateSet)], IntMap StateNum)
-> StateT
     (Nfa2DfaContext m)
     Identity
     ([(StateNum, StateSet)], IntMap StateNum)
forall (f :: * -> *) a. Applicative f => a -> f a
pure ([(StateNum, StateSet)]
rest', Key -> StateNum -> IntMap StateNum -> IntMap StateNum
forall a. Key -> a -> IntMap a -> IntMap a
IntMap.insert (Key -> Key
forall a. Enum a => a -> Key
fromEnum Key
c) StateNum
dfaSn IntMap StateNum
trans)
                do ([(StateNum, StateSet)]
rest0, IntMap StateNum
forall a. IntMap a
IntMap.empty)
                do EnumMap Key StateSet -> [(Key, StateSet)]
forall k a. Enum k => EnumMap k a -> [(k, a)]
EnumMap.assocs EnumMap Key StateSet
trans1

            ([(StateNum, StateSet)]
rest2, Maybe StateNum
otherTrans2) <- case StateSet -> Bool
MState.nullSet StateSet
otherTrans1 of
                Bool
True  -> ([(StateNum, StateSet)], Maybe StateNum)
-> StateT
     (Nfa2DfaContext m)
     Identity
     ([(StateNum, StateSet)], Maybe StateNum)
forall (f :: * -> *) a. Applicative f => a -> f a
pure ([(StateNum, StateSet)]
rest1, Maybe StateNum
forall a. Maybe a
Nothing)
                Bool
False -> do
                    ([(StateNum, StateSet)]
rest, StateNum
dfaSn) <- StateSet
-> [(StateNum, StateSet)]
-> StateT
     (Nfa2DfaContext m) Identity ([(StateNum, StateSet)], StateNum)
forall m.
StateSet
-> [(StateNum, StateSet)]
-> StateT
     (Nfa2DfaContext m) Identity ([(StateNum, StateSet)], StateNum)
getOrRegisterNfaSs StateSet
otherTrans1 [(StateNum, StateSet)]
rest1
                    ([(StateNum, StateSet)], Maybe StateNum)
-> StateT
     (Nfa2DfaContext m)
     Identity
     ([(StateNum, StateSet)], Maybe StateNum)
forall (f :: * -> *) a. Applicative f => a -> f a
pure ([(StateNum, StateSet)]
rest, StateNum -> Maybe StateNum
forall a. a -> Maybe a
Just StateNum
dfaSn)

            ([(StateNum, StateSet)], DFAState m)
-> StateT
     (Nfa2DfaContext m) Identity ([(StateNum, StateSet)], DFAState m)
forall (f :: * -> *) a. Applicative f => a -> f a
pure
                ( [(StateNum, StateSet)]
rest2
                , DState :: forall a.
[Accept a] -> IntMap StateNum -> Maybe StateNum -> DFAState a
DFA.DState
                    { $sel:dstAccepts:DState :: [Accept m]
dstAccepts = [ Accept m
acc | (AcceptPriority
_, Accept m
acc) <- EnumMap AcceptPriority (Accept m) -> [(AcceptPriority, Accept m)]
forall k a. Enum k => EnumMap k a -> [(k, a)]
EnumMap.toDescList EnumMap AcceptPriority (Accept m)
accs1 ]
                    , $sel:dstTrans:DState :: IntMap StateNum
dstTrans = IntMap StateNum
trans2
                    , $sel:dstOtherTrans:DState :: Maybe StateNum
dstOtherTrans = Maybe StateNum
otherTrans2
                    }
                )

        insertTrans :: (EnumMap Key StateSet, StateSet)
-> NFAStateTrans -> (EnumMap Key StateSet, StateSet)
insertTrans (EnumMap Key StateSet
trans0, StateSet
otherTrans0) NFAStateTrans
st =
            let cs :: IntSet
cs = NFAStateTrans -> IntSet
NFA.nstTransRange NFAStateTrans
st
                nfaSn :: StateNum
nfaSn = NFAStateTrans -> StateNum
NFA.nstTransNextState NFAStateTrans
st
            in case NFAStateTrans -> Bool
NFA.nstTransIsStraight NFAStateTrans
st of
                Bool
True ->
                    let ~StateSet
newTrans = StateNum -> StateSet -> StateSet
insertNfaSn StateNum
nfaSn StateSet
otherTrans0
                        trans1 :: EnumMap Key StateSet
trans1 = (EnumMap Key StateSet -> Key -> EnumMap Key StateSet)
-> EnumMap Key StateSet -> IntSet -> EnumMap Key StateSet
forall a. (a -> Key -> a) -> a -> IntSet -> a
IntSet.foldl'
                            do \EnumMap Key StateSet
trans Key
c -> Key
-> StateSet
-> (StateSet -> StateSet)
-> EnumMap Key StateSet
-> EnumMap Key StateSet
forall k a.
Enum k =>
k -> a -> (a -> a) -> EnumMap k a -> EnumMap k a
EnumMap.insertOrUpdate Key
c
                                do StateSet
newTrans
                                do \StateSet
ss -> StateNum -> StateSet -> StateSet
insertNfaSn StateNum
nfaSn StateSet
ss
                                do EnumMap Key StateSet
trans
                            do EnumMap Key StateSet
trans0
                            do IntSet
cs
                    in (EnumMap Key StateSet
trans1, StateSet
otherTrans0)
                Bool
False ->
                    let (EnumMap Key StateSet
diffTrans1, EnumMap Key StateSet
trans1) = ((EnumMap Key StateSet, EnumMap Key StateSet)
 -> Key -> (EnumMap Key StateSet, EnumMap Key StateSet))
-> (EnumMap Key StateSet, EnumMap Key StateSet)
-> IntSet
-> (EnumMap Key StateSet, EnumMap Key StateSet)
forall a. (a -> Key -> a) -> a -> IntSet -> a
IntSet.foldl'
                                                do \(EnumMap Key StateSet
diffTrans, EnumMap Key StateSet
trans) Key
c ->
                                                    ( Key -> EnumMap Key StateSet -> EnumMap Key StateSet
forall k a. Enum k => k -> EnumMap k a -> EnumMap k a
EnumMap.delete Key
c EnumMap Key StateSet
diffTrans
                                                    , Key
-> StateSet
-> (StateSet -> StateSet)
-> EnumMap Key StateSet
-> EnumMap Key StateSet
forall k a.
Enum k =>
k -> a -> (a -> a) -> EnumMap k a -> EnumMap k a
EnumMap.insertOrUpdate Key
c
                                                        StateSet
MState.emptySet
                                                        StateSet -> StateSet
forall a. a -> a
id
                                                        EnumMap Key StateSet
trans
                                                    )
                                                do (EnumMap Key StateSet
trans0, EnumMap Key StateSet
trans0)
                                                do IntSet
cs
                        trans2 :: EnumMap Key StateSet
trans2 = (EnumMap Key StateSet -> Key -> StateSet -> EnumMap Key StateSet)
-> EnumMap Key StateSet
-> EnumMap Key StateSet
-> EnumMap Key StateSet
forall k b a. Enum k => (b -> k -> a -> b) -> b -> EnumMap k a -> b
EnumMap.foldlWithKey'
                                    do \EnumMap Key StateSet
trans Key
c StateSet
ss -> Key -> StateSet -> EnumMap Key StateSet -> EnumMap Key StateSet
forall k a. Enum k => k -> a -> EnumMap k a -> EnumMap k a
EnumMap.insert Key
c
                                        do StateNum -> StateSet -> StateSet
insertNfaSn StateNum
nfaSn StateSet
ss
                                        do EnumMap Key StateSet
trans
                                    do EnumMap Key StateSet
trans1
                                    do EnumMap Key StateSet
diffTrans1
                    in (EnumMap Key StateSet
trans2, StateNum -> StateSet -> StateSet
insertNfaSn StateNum
nfaSn StateSet
otherTrans0)