def missing is public, readable = object{
    method asString->String{"-"}
}

type Iterator = {
    reset->Void
    hasNext->Boolean
    get->T
    next->T}

type Queue = {
    enqueue(_:T)->Void
    dequeue->T
    peek->T
    size->Number
    clear->Void
    isFull->Boolean
    isEmpty->Boolean
    asString->String
    iterator->Iterator}

method withSize(capacity:Number)->Queue is public{QueueArray.new(capacity)}

class QueueArray.new(capacity:Number){

    // references to values stored within queue
    var data is readable:= PrimitiveArray.new(capacity)
    
    // index of head in queue
    var head:Number is readable := 0

    // current size of queue
    var count:Number is readable := 0

    // Add a value to tail of queue
    // @pre queue is not full
    // @post value added to tail of queue
    // @param value the value added
    method enqueue(value)->Void is public{
        if(!isFull) then {
            var tail:Number := (head + count) % data.size
            data[tail] := value
            count := count + 1}
        else{print "Queue is full; can't enqueue value"}
    }

    // Remove value from head of queue
    // @pre queue not empty
    // @post head of queue removed and returned
    // @return value actually removed
    method dequeue->Dynamic is public{
        if(!isEmpty) then {
            var value := data[head]
            head := (head + 1) % data.size
            count := count - 1
            value}
        else{
            print "Queue is empty"
            missing}
    }

    // Fetch value at head of queue
    // @pre the queue is not empty
    // @post @return element at head of queue
    method peek->Dynamic is public{
        if(!isEmpty) then {data[head]}
        else{
            print "Queue is empty"
            missing}
    }

    // @post @return number of elements in queue
    method size->Number is public{count}

    // @post removes all elements from queue
    method clear->Void is public{
        count := 0
        head := 0}

    // @post @return true iff queue is at its capacity
    method isFull->Boolean is public{count == data.size}

    // @post @return true iff queue is empty
    method isEmpty->Boolean is public{count == 0}

    // @post @return string representation
    method asString->String is public{
        var str:String := "
            str := str ++ " {data[l]}"
            l := (l + 1) % data.size}
        return str ++ ">"}

    // @post @return iterator to traverse queue
    method iterator->Iterator is public{QueueIterator.new(data, head)}
}

class QueueIterator.new(source, start:Number){

    var data is readable := source

    var current:Number is readable := start

    var remaining:Number is readable:= data.size

    method reset->Void is public{
        current := start
        remaining := data.size}

    method hasNext->Boolean is public{remaining > 0}

    method next->Dynamic is public{
        var temp:Dynamic := data[current]
        current := (current + 1) % data.size
        remaining := remaining  - 1
        temp}

    method get->Dynamic is public{data[current]}
}