{-# LANGUAGE BinaryLiterals             #-}
{-# LANGUAGE DeriveGeneric              #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE OverloadedStrings          #-}

module HaskellWorks.Data.Json.Standard.Cursor.Internal.StateMachine
  ( lookupPhiTable
  , lookupTransitionTable
  , phiTable
  , phiTableSimd
  , transitionTable
  , transitionTableSimd
  , IntState(..)
  , State(..)
  ) where

import Data.Word
import GHC.Generics
import HaskellWorks.Data.Bits.BitWise

import qualified Data.Vector                                           as DV
import qualified Data.Vector.Storable                                  as DVS
import qualified HaskellWorks.Data.Json.Standard.Cursor.Internal.Word8 as W8

{- HLINT ignore "Reduce guard"        -}

newtype IntState = IntState Int deriving (IntState -> IntState -> Bool
(IntState -> IntState -> Bool)
-> (IntState -> IntState -> Bool) -> Eq IntState
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: IntState -> IntState -> Bool
$c/= :: IntState -> IntState -> Bool
== :: IntState -> IntState -> Bool
$c== :: IntState -> IntState -> Bool
Eq, Eq IntState
Eq IntState
-> (IntState -> IntState -> Ordering)
-> (IntState -> IntState -> Bool)
-> (IntState -> IntState -> Bool)
-> (IntState -> IntState -> Bool)
-> (IntState -> IntState -> Bool)
-> (IntState -> IntState -> IntState)
-> (IntState -> IntState -> IntState)
-> Ord IntState
IntState -> IntState -> Bool
IntState -> IntState -> Ordering
IntState -> IntState -> IntState
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: IntState -> IntState -> IntState
$cmin :: IntState -> IntState -> IntState
max :: IntState -> IntState -> IntState
$cmax :: IntState -> IntState -> IntState
>= :: IntState -> IntState -> Bool
$c>= :: IntState -> IntState -> Bool
> :: IntState -> IntState -> Bool
$c> :: IntState -> IntState -> Bool
<= :: IntState -> IntState -> Bool
$c<= :: IntState -> IntState -> Bool
< :: IntState -> IntState -> Bool
$c< :: IntState -> IntState -> Bool
compare :: IntState -> IntState -> Ordering
$ccompare :: IntState -> IntState -> Ordering
$cp1Ord :: Eq IntState
Ord, Int -> IntState -> ShowS
[IntState] -> ShowS
IntState -> String
(Int -> IntState -> ShowS)
-> (IntState -> String) -> ([IntState] -> ShowS) -> Show IntState
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [IntState] -> ShowS
$cshowList :: [IntState] -> ShowS
show :: IntState -> String
$cshow :: IntState -> String
showsPrec :: Int -> IntState -> ShowS
$cshowsPrec :: Int -> IntState -> ShowS
Show, Integer -> IntState
IntState -> IntState
IntState -> IntState -> IntState
(IntState -> IntState -> IntState)
-> (IntState -> IntState -> IntState)
-> (IntState -> IntState -> IntState)
-> (IntState -> IntState)
-> (IntState -> IntState)
-> (IntState -> IntState)
-> (Integer -> IntState)
-> Num IntState
forall a.
(a -> a -> a)
-> (a -> a -> a)
-> (a -> a -> a)
-> (a -> a)
-> (a -> a)
-> (a -> a)
-> (Integer -> a)
-> Num a
fromInteger :: Integer -> IntState
$cfromInteger :: Integer -> IntState
signum :: IntState -> IntState
$csignum :: IntState -> IntState
abs :: IntState -> IntState
$cabs :: IntState -> IntState
negate :: IntState -> IntState
$cnegate :: IntState -> IntState
* :: IntState -> IntState -> IntState
$c* :: IntState -> IntState -> IntState
- :: IntState -> IntState -> IntState
$c- :: IntState -> IntState -> IntState
+ :: IntState -> IntState -> IntState
$c+ :: IntState -> IntState -> IntState
Num, (forall x. IntState -> Rep IntState x)
-> (forall x. Rep IntState x -> IntState) -> Generic IntState
forall x. Rep IntState x -> IntState
forall x. IntState -> Rep IntState x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep IntState x -> IntState
$cfrom :: forall x. IntState -> Rep IntState x
Generic)

data State = InJson | InString | InEscape | InValue deriving (State -> State -> Bool
(State -> State -> Bool) -> (State -> State -> Bool) -> Eq State
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: State -> State -> Bool
$c/= :: State -> State -> Bool
== :: State -> State -> Bool
$c== :: State -> State -> Bool
Eq, Int -> State
State -> Int
State -> [State]
State -> State
State -> State -> [State]
State -> State -> State -> [State]
(State -> State)
-> (State -> State)
-> (Int -> State)
-> (State -> Int)
-> (State -> [State])
-> (State -> State -> [State])
-> (State -> State -> [State])
-> (State -> State -> State -> [State])
-> Enum State
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
enumFromThenTo :: State -> State -> State -> [State]
$cenumFromThenTo :: State -> State -> State -> [State]
enumFromTo :: State -> State -> [State]
$cenumFromTo :: State -> State -> [State]
enumFromThen :: State -> State -> [State]
$cenumFromThen :: State -> State -> [State]
enumFrom :: State -> [State]
$cenumFrom :: State -> [State]
fromEnum :: State -> Int
$cfromEnum :: State -> Int
toEnum :: Int -> State
$ctoEnum :: Int -> State
pred :: State -> State
$cpred :: State -> State
succ :: State -> State
$csucc :: State -> State
Enum, State
State -> State -> Bounded State
forall a. a -> a -> Bounded a
maxBound :: State
$cmaxBound :: State
minBound :: State
$cminBound :: State
Bounded, Int -> State -> ShowS
[State] -> ShowS
State -> String
(Int -> State -> ShowS)
-> (State -> String) -> ([State] -> ShowS) -> Show State
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [State] -> ShowS
$cshowList :: [State] -> ShowS
show :: State -> String
$cshow :: State -> String
showsPrec :: Int -> State -> ShowS
$cshowsPrec :: Int -> State -> ShowS
Show, (forall x. State -> Rep State x)
-> (forall x. Rep State x -> State) -> Generic State
forall x. Rep State x -> State
forall x. State -> Rep State x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep State x -> State
$cfrom :: forall x. State -> Rep State x
Generic)

phiTable :: DV.Vector (DVS.Vector Word8)
phiTable :: Vector (Vector Word8)
phiTable = Int -> (Int -> Vector Word8) -> Vector (Vector Word8)
forall a. Int -> (Int -> a) -> Vector a
DV.generate Int
5 Int -> Vector Word8
gos
  where gos :: Int -> DVS.Vector Word8
        gos :: Int -> Vector Word8
gos Int
vj = Int -> (Int -> Word8) -> Vector Word8
forall a. Storable a => Int -> (Int -> a) -> Vector a
DVS.generate Int
256 Int -> Word8
go
          where vi :: Int
vi = Int -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
vj
                go :: Int -> Word8
                go :: Int -> Word8
go Int
uj = Word32 -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral ((State, Word32) -> Word32
forall a b. (a, b) -> b
snd (Word8 -> State -> (State, Word32)
stateMachine (Int -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
uj) (Int -> State
forall a. Enum a => Int -> a
toEnum Int
vi)))
{-# NOINLINE phiTable #-}

phiTable2 :: DVS.Vector Word8
phiTable2 :: Vector Word8
phiTable2 = Int -> (Int -> Word8) -> Vector Word8
forall a. Storable a => Int -> (Int -> a) -> Vector a
DVS.generate (Int
4 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
iLen) Int -> Word8
go
  where iLen :: Int
iLen = Int
256 :: Int
        go :: Int -> Word8
        go :: Int -> Word8
go Int
uj = Word32 -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral ((State, Word32) -> Word32
forall a b. (a, b) -> b
snd (Word8 -> State -> (State, Word32)
stateMachine (Int -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
ui) (Int -> State
forall a. Enum a => Int -> a
toEnum (Int -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
uk))))
          where (Int
uk, Int
ui) = Int -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
uj Int -> Int -> (Int, Int)
forall a. Integral a => a -> a -> (a, a)
`divMod` Int
iLen
{-# NOINLINE phiTable2 #-}

lookupPhiTable :: IntState -> Word8 -> Word8
lookupPhiTable :: IntState -> Word8 -> Word8
lookupPhiTable (IntState Int
s) Word8
w = Vector Word8 -> Int -> Word8
forall a. Storable a => Vector a -> Int -> a
DVS.unsafeIndex Vector Word8
phiTable2 (Int
s Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
256 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Word8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
w)
{-# INLINE lookupPhiTable #-}

phiTableSimd :: DVS.Vector Word32
phiTableSimd :: Vector Word32
phiTableSimd = Int -> (Int -> Word32) -> Vector Word32
forall a. Storable a => Int -> (Int -> a) -> Vector a
DVS.generate Int
256 Int -> Word32
go
  where go :: Int -> Word32
        go :: Int -> Word32
go Int
vj = ((State, Word32) -> Word32
forall a b. (a, b) -> b
snd (Word8 -> State -> (State, Word32)
stateMachine Word8
vi State
InJson  ) Word32 -> Count -> Word32
forall a. Shift a => a -> Count -> a
.<.  Count
0) Word32 -> Word32 -> Word32
forall a. BitWise a => a -> a -> a
.|.
                ((State, Word32) -> Word32
forall a b. (a, b) -> b
snd (Word8 -> State -> (State, Word32)
stateMachine Word8
vi State
InString) Word32 -> Count -> Word32
forall a. Shift a => a -> Count -> a
.<.  Count
8) Word32 -> Word32 -> Word32
forall a. BitWise a => a -> a -> a
.|.
                ((State, Word32) -> Word32
forall a b. (a, b) -> b
snd (Word8 -> State -> (State, Word32)
stateMachine Word8
vi State
InEscape) Word32 -> Count -> Word32
forall a. Shift a => a -> Count -> a
.<. Count
16) Word32 -> Word32 -> Word32
forall a. BitWise a => a -> a -> a
.|.
                ((State, Word32) -> Word32
forall a b. (a, b) -> b
snd (Word8 -> State -> (State, Word32)
stateMachine Word8
vi State
InValue ) Word32 -> Count -> Word32
forall a. Shift a => a -> Count -> a
.<. Count
24)
          where vi :: Word8
vi = Int -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
vj
{-# NOINLINE phiTableSimd #-}

transitionTable :: DV.Vector (DVS.Vector Word8)
transitionTable :: Vector (Vector Word8)
transitionTable = Int -> (Int -> Vector Word8) -> Vector (Vector Word8)
forall a. Int -> (Int -> a) -> Vector a
DV.generate Int
5 Int -> Vector Word8
gos
  where gos :: Int -> DVS.Vector Word8
        gos :: Int -> Vector Word8
gos Int
vj = Int -> (Int -> Word8) -> Vector Word8
forall a. Storable a => Int -> (Int -> a) -> Vector a
DVS.generate Int
256 Int -> Word8
go
          where vi :: Int
vi = Int -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
vj
                go :: Int -> Word8
                go :: Int -> Word8
go Int
uj = Int -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral (State -> Int
forall a. Enum a => a -> Int
fromEnum ((State, Word32) -> State
forall a b. (a, b) -> a
fst (Word8 -> State -> (State, Word32)
stateMachine Word8
ui (Int -> State
forall a. Enum a => Int -> a
toEnum Int
vi))))
                  where ui :: Word8
ui = Int -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
uj
{-# NOINLINE transitionTable #-}

transitionTable2 :: DVS.Vector Word8
transitionTable2 :: Vector Word8
transitionTable2 = Int -> (Int -> Word8) -> Vector Word8
forall a. Storable a => Int -> (Int -> a) -> Vector a
DVS.generate (Int
4 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
iLen) Int -> Word8
go
  where iLen :: Int
iLen = Int
256 :: Int
        go :: Int -> Word8
        go :: Int -> Word8
go Int
uj = Int -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral (State -> Int
forall a. Enum a => a -> Int
fromEnum ((State, Word32) -> State
forall a b. (a, b) -> a
fst (Word8 -> State -> (State, Word32)
stateMachine (Int -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
ui) (Int -> State
forall a. Enum a => Int -> a
toEnum (Int -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
uk)))))
          where (Int
uk, Int
ui) = Int -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
uj Int -> Int -> (Int, Int)
forall a. Integral a => a -> a -> (a, a)
`divMod` Int
iLen
{-# NOINLINE transitionTable2 #-}

lookupTransitionTable :: IntState -> Word8 -> IntState
lookupTransitionTable :: IntState -> Word8 -> IntState
lookupTransitionTable (IntState Int
s) Word8
w = Word8 -> IntState
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Vector Word8 -> Int -> Word8
forall a. Storable a => Vector a -> Int -> a
DVS.unsafeIndex Vector Word8
transitionTable2 (Int
s Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
256 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Word8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
w))
{-# INLINE lookupTransitionTable #-}

transitionTableSimd :: DVS.Vector Word64
transitionTableSimd :: Vector Count
transitionTableSimd = Int -> (Int -> Count) -> Vector Count
forall a. Storable a => Int -> (Int -> a) -> Vector a
DVS.generate Int
256 Int -> Count
go
  where go :: Int -> Word64
        go :: Int -> Count
go Int
vj = Int -> Count
forall a b. (Integral a, Num b) => a -> b
fromIntegral (State -> Int
forall a. Enum a => a -> Int
fromEnum ((State, Word32) -> State
forall a b. (a, b) -> a
fst (Word8 -> State -> (State, Word32)
stateMachine Word8
vi State
InJson  ))) Count -> Count -> Count
forall a. BitWise a => a -> a -> a
.|.
                Int -> Count
forall a b. (Integral a, Num b) => a -> b
fromIntegral (State -> Int
forall a. Enum a => a -> Int
fromEnum ((State, Word32) -> State
forall a b. (a, b) -> a
fst (Word8 -> State -> (State, Word32)
stateMachine Word8
vi State
InString))) Count -> Count -> Count
forall a. BitWise a => a -> a -> a
.|.
                Int -> Count
forall a b. (Integral a, Num b) => a -> b
fromIntegral (State -> Int
forall a. Enum a => a -> Int
fromEnum ((State, Word32) -> State
forall a b. (a, b) -> a
fst (Word8 -> State -> (State, Word32)
stateMachine Word8
vi State
InEscape))) Count -> Count -> Count
forall a. BitWise a => a -> a -> a
.|.
                Int -> Count
forall a b. (Integral a, Num b) => a -> b
fromIntegral (State -> Int
forall a. Enum a => a -> Int
fromEnum ((State, Word32) -> State
forall a b. (a, b) -> a
fst (Word8 -> State -> (State, Word32)
stateMachine Word8
vi State
InValue )))
          where vi :: Word8
vi = Int -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
vj
{-# NOINLINE transitionTableSimd #-}

stateMachine :: Word8 -> State -> (State, Word32)
stateMachine :: Word8 -> State -> (State, Word32)
stateMachine Word8
c State
InJson   | Word8 -> Bool
W8.isOpen Word8
c         = (State
InJson  , Word32
0b110)
stateMachine Word8
c State
InJson   | Word8 -> Bool
W8.isClose Word8
c        = (State
InJson  , Word32
0b001)
stateMachine Word8
c State
InJson   | Word8 -> Bool
W8.isDelim Word8
c        = (State
InJson  , Word32
0b000)
stateMachine Word8
c State
InJson   | Word8 -> Bool
W8.isValueChar Word8
c    = (State
InValue , Word32
0b111)
stateMachine Word8
c State
InJson   | Word8 -> Bool
W8.isDoubleQuote Word8
c  = (State
InString, Word32
0b111)
stateMachine Word8
_ State
InJson   | Bool
otherwise           = (State
InJson  , Word32
0b000)
stateMachine Word8
c State
InString | Word8 -> Bool
W8.isDoubleQuote Word8
c  = (State
InJson  , Word32
0b000)
stateMachine Word8
c State
InString | Word8 -> Bool
W8.isBackSlash Word8
c    = (State
InEscape, Word32
0b000)
stateMachine Word8
_ State
InString | Bool
otherwise           = (State
InString, Word32
0b000)
stateMachine Word8
_ State
InEscape | Bool
otherwise           = (State
InString, Word32
0b000)
stateMachine Word8
c State
InValue  | Word8 -> Bool
W8.isOpen Word8
c         = (State
InJson  , Word32
0b110)
stateMachine Word8
c State
InValue  | Word8 -> Bool
W8.isClose Word8
c        = (State
InJson  , Word32
0b001)
stateMachine Word8
c State
InValue  | Word8 -> Bool
W8.isDelim Word8
c        = (State
InJson  , Word32
0b000)
stateMachine Word8
c State
InValue  | Word8 -> Bool
W8.isValueChar Word8
c    = (State
InValue , Word32
0b000)
stateMachine Word8
_ State
InValue  | Bool
otherwise           = (State
InJson  , Word32
0b000)
{-# INLINE stateMachine #-}