/* This file is part of the db4o object database http://www.db4o.com
Copyright (C) 2004 - 2011 Versant Corporation http://www.versant.com
db4o is free software; you can redistribute it and/or modify it under
the terms of version 3 of the GNU General Public License as published
by the Free Software Foundation.
db4o is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License along
with this program. If not, see http://www.gnu.org/licenses/. */
package EDU.purdue.cs.bloat.tree;
import java.util.*;
import EDU.purdue.cs.bloat.editor.*;
/**
* <tt>OperandStack</tt> is used to simulate the JVM stack. A stack of
* expressions is maintained. <tt>OperandStack</tt> has methods to push and
* pop (both wide and non-wide) expressions, replace an expression at a given
* depth in the stack, peek into the stack, etc.
*
* @see Expr
* @see Tree
*/
public class OperandStack {
ArrayList stack; // The contents of the stack
int height; // The height of the stack (i.e. the number
// of elements in the stack)
/**
* Constructor.
*/
public OperandStack() {
stack = new ArrayList();
height = 0;
}
/**
* @return True, if the stack is empty.
*/
public boolean isEmpty() {
return stack.isEmpty();
}
/**
* Pops an operand off the stack. Checks to make sure the top of the stack
* is of the expected Type.
*
* @param type
* The expected Type of the top of the stack
* @return Expression on the top of the stack
*/
public Expr pop(final Type type) {
final Expr top = (Expr) stack.remove(stack.size() - 1);
final Type topType = top.type();
height -= topType.stackHeight();
if (type.isAddress()) {
if (!topType.isAddress()) {
throw new IllegalArgumentException("Expected " + type
+ ", stack = " + toString());
}
} else if (type.isReference()) {
if (!topType.isReference()) {
throw new IllegalArgumentException("Expected " + type
+ ", stack = " + toString());
}
} else if (type.isIntegral()) {
if (!topType.isIntegral()) {
throw new IllegalArgumentException("Expected " + type
+ ", stack = " + toString());
}
} else if (!type.equals(topType)) {
throw new IllegalArgumentException("Expected " + type
+ ", stack = " + toString());
}
return top;
}
/**
* Returns the expression at the top of the stack, but does not modify the
* stack.
*/
public Expr peek() {
return (Expr) stack.get(stack.size() - 1);
}
/**
* Sets the entry at a specified index from the bottom of the stack
*
* @param index
* The position in the stack.
* @param expr
* The new value of the expression.
*/
public void set(final int index, final Expr expr) {
stack.set(index, expr);
}
/**
* @return The number of elements in the stack.
*/
public int height() {
return height;
}
/**
* Replaces the expression that is depth expressions from the top of the
* stack.
*
* @param depth
* The number of expressions from the top of the stack.
*
* @param expr
* The new expression
*/
public void replace(int depth, final Expr expr) {
for (int i = stack.size() - 1; i >= 0; i--) {
final Expr top = (Expr) stack.get(i);
if (depth == 0) {
stack.set(i, expr);
return;
}
depth -= top.type().stackHeight();
}
throw new IllegalArgumentException("Can't replace below stack bottom.");
}
/**
* Get the expression that is depth expressions from the top of the stack,
* but do not modify the stack.
*
* @param depth
* Number of expressions deep to get.
*
* @return The expression that is depth expression from the top of the
* stack.
*/
public Expr peek(int depth) {
for (int i = stack.size() - 1; i >= 0; i--) {
final Expr top = (Expr) stack.get(i);
if (depth == 0) {
return top;
}
depth -= top.type().stackHeight();
}
throw new IllegalArgumentException("Can't peek below stack bottom.");
}
/**
* Pops a non-wide expression off the stack.
*/
public Expr pop1() {
final Expr top = (Expr) stack.remove(stack.size() - 1);
final Type type = top.type();
if (type.isWide()) {
throw new IllegalArgumentException("Expected a word "
+ ", got a long");
}
height--;
return top;
}
/**
* Pops a (possibly) wide expression off of the stack and returns the result
* as an array of <tt>Expr</tt>. If the expression at the top of the
* stack is indeed wide, it is returned in element [0] of the array. If the
* expression at the top of the stack is <b>not</b> wide, the top two
* expressions are returned in the array as elements 0 and 1.
*/
public Expr[] pop2() {
final Expr top = (Expr) stack.remove(stack.size() - 1);
Expr[] a;
final Type type = top.type();
if (type.isWide()) {
a = new Expr[1];
a[0] = top;
} else {
a = new Expr[2];
a[0] = (Expr) stack.remove(stack.size() - 1);
a[1] = top;
}
height -= 2;
return a;
}
/**
* Push an expression onto the stack.
*
* @see EDU.purdue.cs.bloat.editor.Type#stackHeight
*/
public void push(final Expr expr) {
height += expr.type().stackHeight();
stack.add(expr);
}
/**
* Returns the number of expressions on the stack.
*/
public int size() {
return stack.size();
}
/**
* Returns the expression at index from the bottom of the stack.
*/
public Expr get(final int index) {
final Expr expr = (Expr) stack.get(index);
return expr;
}
/**
* Returns a String represntation of this stack.
*/
public String toString() {
return stack.toString();
}
}