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

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

type Stack = {
    push(_:T)->Void
    pop->T
    peek->T
    size->Number
    isEmpty->Boolean
    isFull->Boolean
    asString->String
    iterator->Iterator}

method withSize(capacity:Number)->Stack is public{StackArray.new(capacity)}

class StackArray.new(capacity:Number){

    // index to top element of stack
    var top:Number is readable := -1

    // Array of value references. Top is higher in array.
    var data is readable := PrimitiveArray.new(capacity)

    // @post removes all elements from stack
    method clear->Void is public{top := -1}

    // Add a value to top of stack
    // @post adds an element to stack
    // @param item the value to be added
    method push(item)->Void is public{
        if(!isFull) then{
            top := top + 1
            data[top] := item}
        else{print "Stack is full; can't push"}
    }

    // Remove value from top of stack
    // @pre stack is not empty
    // @post removes and returns top element
    // @return value removed
    method pop->Dynamic is public{
        if(!isEmpty) then {
            var result := data[top]
            data[top] := None
            top := top - 1
            result}
        else{
            print "Stack is empty"
            missing}
    }

    // Get reference to top value in stack
    // @pre stack not empty
    // @post @return top element
    method peek->Dynamic is public{
        if(!isEmpty) then {data[top]}
        else{
            print "Stack is empty"
            missing}
    }

    // @post @return number of elements in stack
    method size->Number is public{top + 1}

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

    // @post @return true iff stack is full
    method isFull->Boolean is public{top == (data.size - 1)}

    // @post @return string representation of stack
    method asString->String is public{
        var str:String := "= 0} do {
            str := str ++ " {data[i]}"
            i := i - 1}
        return str ++ ">"}

    // @post @return iterator to traverse stack
    method iterator->Iterator is public{StackIterator.new(data, top)}
}

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

    var data is readable := source

    var current:Number is readable := start

    var remaining:Number is readable := start + 1

    method reset->Void is public{
        current := start
        remaining := start + 1}

    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]}
}