001: /* Copyright (C) 2004 - 2007 db4objects Inc. http://www.db4o.com
002:
003: This file is part of the db4o open source object database.
004:
005: db4o is free software; you can redistribute it and/or modify it under
006: the terms of version 2 of the GNU General Public License as published
007: by the Free Software Foundation and as clarified by db4objects' GPL
008: interpretation policy, available at
009: http://www.db4o.com/about/company/legalpolicies/gplinterpretation/
010: Alternatively you can write to db4objects, Inc., 1900 S Norfolk Street,
011: Suite 350, San Mateo, CA 94403, USA.
012:
013: db4o is distributed in the hope that it will be useful, but WITHOUT ANY
014: WARRANTY; without even the implied warranty of MERCHANTABILITY or
015: FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
016: for more details.
017:
018: You should have received a copy of the GNU General Public License along
019: with this program; if not, write to the Free Software Foundation, Inc.,
020: 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
021: package EDU.purdue.cs.bloat.tree;
022:
023: import java.util.*;
024:
025: import EDU.purdue.cs.bloat.editor.*;
026:
027: /**
028: * <tt>OperandStack</tt> is used to simulate the JVM stack. A stack of
029: * expressions is maintained. <tt>OperandStack</tt> has methods to push and
030: * pop (both wide and non-wide) expressions, replace an expression at a given
031: * depth in the stack, peek into the stack, etc.
032: *
033: * @see Expr
034: * @see Tree
035: */
036: public class OperandStack {
037: ArrayList stack; // The contents of the stack
038:
039: int height; // The height of the stack (i.e. the number
040:
041: // of elements in the stack)
042:
043: /**
044: * Constructor.
045: */
046: public OperandStack() {
047: stack = new ArrayList();
048: height = 0;
049: }
050:
051: /**
052: * @return True, if the stack is empty.
053: */
054: public boolean isEmpty() {
055: return stack.isEmpty();
056: }
057:
058: /**
059: * Pops an operand off the stack. Checks to make sure the top of the stack
060: * is of the expected Type.
061: *
062: * @param type
063: * The expected Type of the top of the stack
064: * @return Expression on the top of the stack
065: */
066: public Expr pop(final Type type) {
067: final Expr top = (Expr) stack.remove(stack.size() - 1);
068:
069: final Type topType = top.type();
070:
071: height -= topType.stackHeight();
072:
073: if (type.isAddress()) {
074: if (!topType.isAddress()) {
075: throw new IllegalArgumentException("Expected " + type
076: + ", stack = " + toString());
077: }
078: } else if (type.isReference()) {
079: if (!topType.isReference()) {
080: throw new IllegalArgumentException("Expected " + type
081: + ", stack = " + toString());
082: }
083: } else if (type.isIntegral()) {
084: if (!topType.isIntegral()) {
085: throw new IllegalArgumentException("Expected " + type
086: + ", stack = " + toString());
087: }
088: } else if (!type.equals(topType)) {
089: throw new IllegalArgumentException("Expected " + type
090: + ", stack = " + toString());
091: }
092:
093: return top;
094: }
095:
096: /**
097: * Returns the expression at the top of the stack, but does not modify the
098: * stack.
099: */
100: public Expr peek() {
101: return (Expr) stack.get(stack.size() - 1);
102: }
103:
104: /**
105: * Sets the entry at a specified index from the bottom of the stack
106: *
107: * @param index
108: * The position in the stack.
109: * @param expr
110: * The new value of the expression.
111: */
112: public void set(final int index, final Expr expr) {
113: stack.set(index, expr);
114: }
115:
116: /**
117: * @return The number of elements in the stack.
118: */
119: public int height() {
120: return height;
121: }
122:
123: /**
124: * Replaces the expression that is depth expressions from the top of the
125: * stack.
126: *
127: * @param depth
128: * The number of expressions from the top of the stack.
129: *
130: * @param expr
131: * The new expression
132: */
133: public void replace(int depth, final Expr expr) {
134: for (int i = stack.size() - 1; i >= 0; i--) {
135: final Expr top = (Expr) stack.get(i);
136:
137: if (depth == 0) {
138: stack.set(i, expr);
139: return;
140: }
141:
142: depth -= top.type().stackHeight();
143: }
144:
145: throw new IllegalArgumentException(
146: "Can't replace below stack bottom.");
147: }
148:
149: /**
150: * Get the expression that is depth expressions from the top of the stack,
151: * but do not modify the stack.
152: *
153: * @param depth
154: * Number of expressions deep to get.
155: *
156: * @return The expression that is depth expression from the top of the
157: * stack.
158: */
159: public Expr peek(int depth) {
160: for (int i = stack.size() - 1; i >= 0; i--) {
161: final Expr top = (Expr) stack.get(i);
162: if (depth == 0) {
163: return top;
164: }
165:
166: depth -= top.type().stackHeight();
167: }
168:
169: throw new IllegalArgumentException(
170: "Can't peek below stack bottom.");
171: }
172:
173: /**
174: * Pops a non-wide expression off the stack.
175: */
176: public Expr pop1() {
177: final Expr top = (Expr) stack.remove(stack.size() - 1);
178:
179: final Type type = top.type();
180:
181: if (type.isWide()) {
182: throw new IllegalArgumentException("Expected a word "
183: + ", got a long");
184: }
185:
186: height--;
187:
188: return top;
189: }
190:
191: /**
192: * Pops a (possibly) wide expression off of the stack and returns the result
193: * as an array of <tt>Expr</tt>. If the expression at the top of the
194: * stack is indeed wide, it is returned in element [0] of the array. If the
195: * expression at the top of the stack is <b>not</b> wide, the top two
196: * expressions are returned in the array as elements 0 and 1.
197: */
198: public Expr[] pop2() {
199: final Expr top = (Expr) stack.remove(stack.size() - 1);
200: Expr[] a;
201:
202: final Type type = top.type();
203:
204: if (type.isWide()) {
205: a = new Expr[1];
206: a[0] = top;
207: } else {
208: a = new Expr[2];
209: a[0] = (Expr) stack.remove(stack.size() - 1);
210: a[1] = top;
211: }
212:
213: height -= 2;
214:
215: return a;
216: }
217:
218: /**
219: * Push an expression onto the stack.
220: *
221: * @see EDU.purdue.cs.bloat.editor.Type#stackHeight
222: */
223: public void push(final Expr expr) {
224: height += expr.type().stackHeight();
225: stack.add(expr);
226: }
227:
228: /**
229: * Returns the number of expressions on the stack.
230: */
231: public int size() {
232: return stack.size();
233: }
234:
235: /**
236: * Returns the expression at index from the bottom of the stack.
237: */
238: public Expr get(final int index) {
239: final Expr expr = (Expr) stack.get(index);
240: return expr;
241: }
242:
243: /**
244: * Returns a String represntation of this stack.
245: */
246: public String toString() {
247: return stack.toString();
248: }
249: }
|