open Okasaki
open QueueSig
module HoodMelvilleQueue : Queue = struct
type 'a status =
| Idle
| Reversing of int * 'a list * 'a list * 'a list * 'a list
| Appending of int * 'a list * 'a list
| Finished of 'a list
type 'a queue = int * 'a list * 'a status * int * 'a list
let exec = function
| Reversing (ok, x::f, f', y::r, r') -> Reversing (ok+1, f, x::f', r, y::r')
| Reversing (ok, [], f', [y], r') -> Appending (ok, f', y::r')
| Appending (0, f', r') -> Finished r'
| Appending (ok, x::f', r') -> Appending (ok-1, f', x::r')
| s -> s
let invalidate = function
| Reversing (ok, f, f', r, r') -> Reversing (ok-1, f, f', r, r')
| Appending (0, f', x::r') -> Finished r'
| Appending (ok, f', r') -> Appending (ok-1, f', r')
| s -> s
let exec2 (lenf, f, state, lenr, r) =
match exec (exec state) with
| Finished newf -> (lenf, newf, Idle, lenr, r)
| newstate -> (lenf, f, newstate, lenr, r)
let check ((lenf, f, state, lenr, r) as q) =
if lenr <= lenf
then exec2 q
else let newstate = Reversing (0, f, [], r, []) in
exec2 (lenf+lenr, f, newstate, 0, [])
let empty : 'a queue = (0, [], Idle, 0, [])
let is_empty (lenf, _, _, _, _) = (lenf = 0)
let snoc (lenf, f, state, lenr, r) x =
check (lenf, f, state, lenr+1, x::r)
let head = function
| (_,[],_,_,_) -> raise EmptyStructure
| (_,x::_,_,_,_) -> x
let tail = function
| (_,[],_,_,_) -> raise EmptyStructure
| (lenf, x::f', state, lenr, r) ->
check (lenf-1, f', invalidate state, lenr, r)
end
|