001: /*
002: * Copyright 1994-2003 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025:
026: package sun.tools.tree;
027:
028: import sun.tools.java.*;
029: import sun.tools.asm.Assembler;
030: import java.io.PrintStream;
031: import java.util.Hashtable;
032:
033: /**
034: * WARNING: The contents of this source file are not part of any
035: * supported API. Code that depends on them does so at its own risk:
036: * they are subject to change or removal without notice.
037: */
038: public class ArrayAccessExpression extends UnaryExpression {
039:
040: /**
041: * The index expression for the array access. Note that
042: * ArrayAccessExpression also `moonlights' as a structure for
043: * storing array types (like Object[]) which are used as part
044: * of cast expressions. For properly formed array types, the
045: * value of index is null. We need to be on the lookout for
046: * null indices in true array accesses, and non-null indices
047: * in array types. We also need to make sure general purpose
048: * methods (like copyInline(), which is called for both) are
049: * prepared to handle either null or non-null indices.
050: */
051: Expression index;
052:
053: /**
054: * constructor
055: */
056: public ArrayAccessExpression(long where, Expression right,
057: Expression index) {
058: super (ARRAYACCESS, where, Type.tError, right);
059: this .index = index;
060: }
061:
062: /**
063: * Check expression type
064: */
065: public Vset checkValue(Environment env, Context ctx, Vset vset,
066: Hashtable exp) {
067: vset = right.checkValue(env, ctx, vset, exp);
068: if (index == null) {
069: env.error(where, "array.index.required");
070: return vset;
071: }
072: vset = index.checkValue(env, ctx, vset, exp);
073: index = convert(env, ctx, Type.tInt, index);
074:
075: if (!right.type.isType(TC_ARRAY)) {
076: if (!right.type.isType(TC_ERROR)) {
077: env.error(where, "not.array", right.type);
078: }
079: return vset;
080: }
081:
082: type = right.type.getElementType();
083: return vset;
084: }
085:
086: public Vset checkAmbigName(Environment env, Context ctx, Vset vset,
087: Hashtable exp, UnaryExpression loc) {
088: if (index == null) {
089: vset = right.checkAmbigName(env, ctx, vset, exp, this );
090: if (right.type == Type.tPackage) {
091: FieldExpression.reportFailedPackagePrefix(env, right);
092: return vset;
093: }
094:
095: // Nope. Is this field expression a type?
096: if (right instanceof TypeExpression) {
097: Type atype = Type.tArray(right.type);
098: loc.right = new TypeExpression(where, atype);
099: return vset;
100: }
101:
102: env.error(where, "array.index.required");
103: return vset;
104: }
105: return super .checkAmbigName(env, ctx, vset, exp, loc);
106: }
107:
108: /*
109: * Check the array if it appears on the LHS of an assignment
110: */
111: public Vset checkLHS(Environment env, Context ctx, Vset vset,
112: Hashtable exp) {
113: return checkValue(env, ctx, vset, exp);
114: }
115:
116: /*
117: * Check the array if it appears on the LHS of an op= expression
118: */
119: public Vset checkAssignOp(Environment env, Context ctx, Vset vset,
120: Hashtable exp, Expression outside) {
121: return checkValue(env, ctx, vset, exp);
122: }
123:
124: /**
125: * An array access expression never requires the use of an access method to perform
126: * an assignment to an array element, though an access method may be required to
127: * fetch the array object itself.
128: */
129: public FieldUpdater getAssigner(Environment env, Context ctx) {
130: return null;
131: }
132:
133: /**
134: * An array access expression never requires a field updater.
135: */
136: public FieldUpdater getUpdater(Environment env, Context ctx) {
137: return null;
138: }
139:
140: /**
141: * Convert to a type
142: */
143: Type toType(Environment env, Context ctx) {
144: return toType(env, right.toType(env, ctx));
145: }
146:
147: Type toType(Environment env, Type t) {
148: if (index != null) {
149: env.error(index.where, "array.dim.in.type");
150: }
151: return Type.tArray(t);
152: }
153:
154: /**
155: * Inline
156: */
157: public Expression inline(Environment env, Context ctx) {
158: // It isn't possible to simply replace an array access
159: // with a CommaExpression as happens with many binary
160: // operators, because array accesses may have side effects
161: // such as NullPointerException or IndexOutOfBoundsException.
162: right = right.inlineValue(env, ctx);
163: index = index.inlineValue(env, ctx);
164: return this ;
165: }
166:
167: public Expression inlineValue(Environment env, Context ctx) {
168: // inlineValue() should not end up being called when the index is
169: // null. If it is null, we let this method fail with a
170: // NullPointerException.
171:
172: right = right.inlineValue(env, ctx);
173: index = index.inlineValue(env, ctx);
174: return this ;
175: }
176:
177: public Expression inlineLHS(Environment env, Context ctx) {
178: return inlineValue(env, ctx);
179: }
180:
181: /**
182: * Create a copy of the expression for method inlining
183: */
184: public Expression copyInline(Context ctx) {
185: ArrayAccessExpression e = (ArrayAccessExpression) clone();
186: e.right = right.copyInline(ctx);
187: if (index == null) {
188: // The index can be null when this node is being used to
189: // represent a type (e.g. Object[]) used in a cast expression.
190: // We need to copy such structures without complaint.
191: e.index = null;
192: } else {
193: e.index = index.copyInline(ctx);
194: }
195: return e;
196: }
197:
198: /**
199: * The cost of inlining this expression
200: */
201: public int costInline(int thresh, Environment env, Context ctx) {
202: // costInline() should not end up being called when the index is
203: // null. If it is null, we let this method fail with a
204: // NullPointerException.
205:
206: return 1 + right.costInline(thresh, env, ctx)
207: + index.costInline(thresh, env, ctx);
208: }
209:
210: /**
211: * Code
212: */
213: int codeLValue(Environment env, Context ctx, Assembler asm) {
214: // codeLValue() should not end up being called when the index is
215: // null. If it is null, we let this method fail with a
216: // NullPointerException.
217:
218: right.codeValue(env, ctx, asm);
219: index.codeValue(env, ctx, asm);
220: return 2;
221: }
222:
223: void codeLoad(Environment env, Context ctx, Assembler asm) {
224: switch (type.getTypeCode()) {
225: case TC_BOOLEAN:
226: case TC_BYTE:
227: asm.add(where, opc_baload);
228: break;
229: case TC_CHAR:
230: asm.add(where, opc_caload);
231: break;
232: case TC_SHORT:
233: asm.add(where, opc_saload);
234: break;
235: default:
236: asm.add(where, opc_iaload + type.getTypeCodeOffset());
237: }
238: }
239:
240: void codeStore(Environment env, Context ctx, Assembler asm) {
241: switch (type.getTypeCode()) {
242: case TC_BOOLEAN:
243: case TC_BYTE:
244: asm.add(where, opc_bastore);
245: break;
246: case TC_CHAR:
247: asm.add(where, opc_castore);
248: break;
249: case TC_SHORT:
250: asm.add(where, opc_sastore);
251: break;
252: default:
253: asm.add(where, opc_iastore + type.getTypeCodeOffset());
254: }
255: }
256:
257: public void codeValue(Environment env, Context ctx, Assembler asm) {
258: codeLValue(env, ctx, asm);
259: codeLoad(env, ctx, asm);
260: }
261:
262: /**
263: * Print
264: */
265: public void print(PrintStream out) {
266: out.print("(" + opNames[op] + " ");
267: right.print(out);
268: out.print(" ");
269: if (index != null) {
270: index.print(out);
271: } else {
272: out.print("<empty>");
273: }
274: out.print(")");
275: }
276: }
|