#lang scheme
(define-struct queue (value left right) #:mutable)
(define head (gensym 'queue-head))
(define (empty-queue)
(let* ([q (make-queue head #f #f)])
(set-queue-left! q q)
(set-queue-right! q q)
q))
(define (queue-head? q)
(eq? (queue-value q) head))
(define (head-queue? v)
(and (queue? v) (queue-head? v)))
(define (queue-empty? q)
(and (queue-head? q) (queue-head? (queue-right q))))
(define (nonempty-queue? v)
(and (queue? v)
(queue-head? v)
(queue? (queue-right v))
(not (queue-head? (queue-right v)))))
(define (enqueue! q v)
(let* ([bot (queue-left q)]
[new (make-queue v bot q)])
(set-queue-left! q new)
(set-queue-right! bot new)))
(define (dequeue! q)
(let* ([old (queue-right q)]
[top (queue-right old)])
(set-queue-right! q top)
(set-queue-left! top q)
(queue-value old)))
(define queue/c
(flat-named-contract "queue" head-queue?))
(define nonempty-queue/c
(flat-named-contract "nonempty-queue" nonempty-queue?))
(provide/contract
[queue/c flat-contract?]
[nonempty-queue/c flat-contract?]
[rename head-queue? queue? (-> any/c boolean?)]
[rename empty-queue make-queue (-> queue/c)]
[queue-empty? (-> queue/c boolean?)]
[enqueue! (-> queue/c any/c void?)]
[dequeue! (-> nonempty-queue/c any/c)])