{-# OPTIONS_GHC -Wno-incomplete-patterns #-}
{-# LANGUAGE ViewPatterns,
             DerivingStrategies #-}
module Parsley.Internal.Common.Queue (Queue, empty, enqueue, dequeue, null, size, foldr) where

import Prelude hiding (null, foldr)

import qualified Prelude (foldr)

data Queue a = Queue {
  Queue a -> Int
outsz :: Int,
  Queue a -> [a]
outs  :: [a],
  Queue a -> Int
insz  :: Int,
  Queue a -> [a]
ins   :: [a]
} deriving stock Queue a -> Queue a -> Bool
(Queue a -> Queue a -> Bool)
-> (Queue a -> Queue a -> Bool) -> Eq (Queue a)
forall a. Eq a => Queue a -> Queue a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Queue a -> Queue a -> Bool
$c/= :: forall a. Eq a => Queue a -> Queue a -> Bool
== :: Queue a -> Queue a -> Bool
$c== :: forall a. Eq a => Queue a -> Queue a -> Bool
Eq

empty :: Queue a
empty :: Queue a
empty = Int -> [a] -> Int -> [a] -> Queue a
forall a. Int -> [a] -> Int -> [a] -> Queue a
Queue Int
0 [] Int
0 []

enqueue :: a -> Queue a -> Queue a
enqueue :: a -> Queue a -> Queue a
enqueue a
x Queue a
q = Queue a
q {insz :: Int
insz = Queue a -> Int
forall a. Queue a -> Int
insz Queue a
q Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1, ins :: [a]
ins = a
x a -> [a] -> [a]
forall a. a -> [a] -> [a]
: Queue a -> [a]
forall a. Queue a -> [a]
ins Queue a
q}

dequeue :: Queue a -> (a, Queue a)
dequeue :: Queue a -> (a, Queue a)
dequeue q :: Queue a
q@(Queue a -> [a]
forall a. Queue a -> [a]
outs -> (a
x:[a]
outs')) = (a
x, Queue a
q {outsz :: Int
outsz = Queue a -> Int
forall a. Queue a -> Int
outsz Queue a
q Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1, outs :: [a]
outs = [a]
outs'})
dequeue q :: Queue a
q@(Queue a -> [a]
forall a. Queue a -> [a]
outs -> [])        = Queue a -> (a, Queue a)
forall a. Queue a -> (a, Queue a)
dequeue (Int -> [a] -> Int -> [a] -> Queue a
forall a. Int -> [a] -> Int -> [a] -> Queue a
Queue (Queue a -> Int
forall a. Queue a -> Int
insz Queue a
q) ([a] -> [a]
forall a. [a] -> [a]
reverse (Queue a -> [a]
forall a. Queue a -> [a]
ins Queue a
q)) Int
0 [])

null :: Queue a -> Bool
null :: Queue a -> Bool
null (Queue Int
0 [] Int
0 []) = Bool
True
null Queue a
_ = Bool
False

size :: Queue a -> Int
size :: Queue a -> Int
size Queue a
q = Queue a -> Int
forall a. Queue a -> Int
insz Queue a
q Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Queue a -> Int
forall a. Queue a -> Int
outsz Queue a
q

toList :: Queue a -> [a]
toList :: Queue a -> [a]
toList Queue a
q = Queue a -> [a]
forall a. Queue a -> [a]
outs Queue a
q [a] -> [a] -> [a]
forall a. [a] -> [a] -> [a]
++ [a] -> [a]
forall a. [a] -> [a]
reverse (Queue a -> [a]
forall a. Queue a -> [a]
ins Queue a
q)

foldr :: (a -> b -> b) -> b -> Queue a -> b
foldr :: (a -> b -> b) -> b -> Queue a -> b
foldr a -> b -> b
f b
k = (a -> b -> b) -> b -> [a] -> b
forall (t :: Type -> Type) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
Prelude.foldr a -> b -> b
f b
k ([a] -> b) -> (Queue a -> [a]) -> Queue a -> b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Queue a -> [a]
forall a. Queue a -> [a]
toList

instance Show a => Show (Queue a) where
  show :: Queue a -> String
show = [a] -> String
forall a. Show a => a -> String
show ([a] -> String) -> (Queue a -> [a]) -> Queue a -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Queue a -> [a]
forall a. Queue a -> [a]
toList