History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/sun/tools/tree/IdentifierExpression.java (1 of 18352 files). Show all

Unified · Split

java/pkg/sun/tools/tree/IdentifierExpression.java+477−0
@@ -0,0 +1,477 @@
1/*
2 * Copyright (c) 1994, 2003, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package sun.tools.tree;
27
28import sun.tools.java.*;
29import sun.tools.asm.Assembler;
30import sun.tools.asm.LocalVariable;
31import java.io.PrintStream;
32import java.util.Hashtable;
33
34/**
35 * WARNING: The contents of this source file are not part of any
36 * supported API. Code that depends on them does so at its own risk:
37 * they are subject to change or removal without notice.
38 */
39public
40class IdentifierExpression extends Expression {
41 Identifier id;
42 MemberDefinition field;
43 Expression implementation;
44
45 /**
46 * Constructor
47 */
48 public IdentifierExpression(long where, Identifier id) {
49 super(IDENT, where, Type.tError);
50 this.id = id;
51 }
52 public IdentifierExpression(IdentifierToken id) {
53 this(id.getWhere(), id.getName());
54 }
55 public IdentifierExpression(long where, MemberDefinition field) {
56 super(IDENT, where, field.getType());
57 this.id = field.getName();
58 this.field = field;
59 }
60
61 public Expression getImplementation() {
62 if (implementation != null)
63 return implementation;
64 return this;
65 }
66
67 /**
68 * Check if the expression is equal to a value
69 */
70 public boolean equals(Identifier id) {
71 return this.id.equals(id);
72 }
73
74
75 /**
76 * Assign a value to this identifier. [It must already be "bound"]
77 */
78 private Vset assign(Environment env, Context ctx, Vset vset) {
79 if (field.isLocal()) {
80 LocalMember local = (LocalMember)field;
81 if (local.scopeNumber < ctx.frameNumber) {
82 env.error(where, "assign.to.uplevel", id);
83 }
84 if (local.isFinal()) {
85 // allow definite single assignment of blank finals
86 if (!local.isBlankFinal()) {
87 env.error(where, "assign.to.final", id);
88 } else if (!vset.testVarUnassigned(local.number)) {
89 env.error(where, "assign.to.blank.final", id);
90 }
91 }
92 vset.addVar(local.number);
93 local.writecount++;
94 } else if (field.isFinal()) {
95 vset = FieldExpression.checkFinalAssign(env, ctx, vset,
96 where, field);
97 }
98 return vset;
99 }
100
101 /**
102 * Get the value of this identifier. [ It must already be "bound"]
103 */
104 private Vset get(Environment env, Context ctx, Vset vset) {
105 if (field.isLocal()) {
106 LocalMember local = (LocalMember)field;
107 if (local.scopeNumber < ctx.frameNumber && !local.isFinal()) {
108 env.error(where, "invalid.uplevel", id);
109 }
110 if (!vset.testVar(local.number)) {
111 env.error(where, "var.not.initialized", id);
112 vset.addVar(local.number);
113 }
114 local.readcount++;
115 } else {
116 if (!field.isStatic()) {
117 if (!vset.testVar(ctx.getThisNumber())) {
118 env.error(where, "access.inst.before.super", id);
119 implementation = null;
120 }
121 }
122 if (field.isBlankFinal()) {
123 int number = ctx.getFieldNumber(field);
124 if (number >= 0 && !vset.testVar(number)) {
125 env.error(where, "var.not.initialized", id);
126 }
127 }
128 }
129 return vset;
130 }
131
132 /**
133 * Bind to a field
134 */
135 boolean bind(Environment env, Context ctx) {
136 try {
137 field = ctx.getField(env, id);
138 if (field == null) {
139 for (ClassDefinition cdef = ctx.field.getClassDefinition();
140 cdef != null; cdef = cdef.getOuterClass()) {
141 if (cdef.findAnyMethod(env, id) != null) {
142 env.error(where, "invalid.var", id,
143 ctx.field.getClassDeclaration());
144 return false;
145 }
146 }
147 env.error(where, "undef.var", id);
148 return false;
149 }
150
151 type = field.getType();
152
153 // Check access permission
154 if (!ctx.field.getClassDefinition().canAccess(env, field)) {
155 env.error(where, "no.field.access",
156 id, field.getClassDeclaration(),
157 ctx.field.getClassDeclaration());
158 return false;
159 }
160
161 // Find out how to access this variable.
162 if (field.isLocal()) {
163 LocalMember local = (LocalMember)field;
164 if (local.scopeNumber < ctx.frameNumber) {
165 // get a "val$x" copy via the current object
166 implementation = ctx.makeReference(env, local);
167 }
168 } else {
169 MemberDefinition f = field;
170
171 if (f.reportDeprecated(env)) {
172 env.error(where, "warn.field.is.deprecated",
173 id, f.getClassDefinition());
174 }
175
176 ClassDefinition fclass = f.getClassDefinition();
177 if (fclass != ctx.field.getClassDefinition()) {
178 // Maybe an inherited field hides an apparent variable.
179 MemberDefinition f2 = ctx.getApparentField(env, id);
180 if (f2 != null && f2 != f) {
181 ClassDefinition c = ctx.findScope(env, fclass);
182 if (c == null) c = f.getClassDefinition();
183 if (f2.isLocal()) {
184 env.error(where, "inherited.hides.local",
185 id, c.getClassDeclaration());
186 } else {
187 env.error(where, "inherited.hides.field",
188 id, c.getClassDeclaration(),
189 f2.getClassDeclaration());
190 }
191 }
192 }
193
194 // Rewrite as a FieldExpression.
195 // Access methods for private fields, if needed, will be added
196 // during subsequent processing of the FieldExpression. See
197 // method 'FieldExpression.checkCommon'. This division of labor
198 // is somewhat awkward, as most further processing of a
199 // FieldExpression during the checking phase is suppressed when
200 // the referenced field is pre-set as it is here.
201
202 if (f.isStatic()) {
203 Expression base = new TypeExpression(where,
204 f.getClassDeclaration().getType());
205 implementation = new FieldExpression(where, null, f);
206 } else {
207 Expression base = ctx.findOuterLink(env, where, f);
208 if (base != null) {
209 implementation = new FieldExpression(where, base, f);
210 }
211 }
212 }
213
214 // Check forward reference
215 if (!ctx.canReach(env, field)) {
216 env.error(where, "forward.ref",
217 id, field.getClassDeclaration());
218 return false;
219 }
220 return true;
221 } catch (ClassNotFound e) {
222 env.error(where, "class.not.found", e.name, ctx.field);
223 } catch (AmbiguousMember e) {
224 env.error(where, "ambig.field", id,
225 e.field1.getClassDeclaration(),
226 e.field2.getClassDeclaration());
227 }
228 return false;
229 }
230
231 /**
232 * Check expression
233 */
234 public Vset checkValue(Environment env, Context ctx, Vset vset, Hashtable exp) {
235 if (field != null) {
236 // An internally pre-set field, such as an argument copying
237 // an uplevel value. Do not re-check it.
238 return vset;
239 }
240 if (bind(env, ctx)) {
241 vset = get(env, ctx, vset);
242 ctx.field.getClassDefinition().addDependency(field.getClassDeclaration());
243 if (implementation != null)
244 vset = implementation.checkValue(env, ctx, vset, exp);
245 }
246 return vset;
247 }
248
249 /**
250 * Check the expression if it appears on the LHS of an assignment
251 */
252 public Vset checkLHS(Environment env, Context ctx,
253 Vset vset, Hashtable exp) {
254 if (!bind(env, ctx))
255 return vset;
256 vset = assign(env, ctx, vset);
257 if (implementation != null)
258 vset = implementation.checkValue(env, ctx, vset, exp);
259 return vset;
260 }
261
262 /**
263 * Check the expression if it appears on the LHS of an op= expression
264 */
265 public Vset checkAssignOp(Environment env, Context ctx,
266 Vset vset, Hashtable exp, Expression outside) {
267 if (!bind(env, ctx))
268 return vset;
269 vset = assign(env, ctx, get(env, ctx, vset));
270 if (implementation != null)
271 vset = implementation.checkValue(env, ctx, vset, exp);
272 return vset;
273 }
274
275 /**
276 * Return an accessor if one is needed for assignments to this expression.
277 */
278 public FieldUpdater getAssigner(Environment env, Context ctx) {
279 if (implementation != null)
280 return implementation.getAssigner(env, ctx);
281 return null;
282 }
283
284 /**
285 * Return an updater if one is needed for assignments to this expression.
286 */
287 public FieldUpdater getUpdater(Environment env, Context ctx) {
288 if (implementation != null)
289 return implementation.getUpdater(env, ctx);
290 return null;
291 }
292
293 /**
294 * Check if the present name is part of a scoping prefix.
295 */
296 public Vset checkAmbigName(Environment env, Context ctx, Vset vset, Hashtable exp,
297 UnaryExpression loc) {
298 try {
299 if (ctx.getField(env, id) != null) {
300 // if this is a local field, there's nothing more to do.
301 return checkValue(env, ctx, vset, exp);
302 }
303 } catch (ClassNotFound ee) {
304 } catch (AmbiguousMember ee) {
305 }
306 // Can this be interpreted as a type?
307 ClassDefinition c = toResolvedType(env, ctx, true);
308 // Is it a real type??
309 if (c != null) {
310 loc.right = new TypeExpression(where, c.getType());
311 return vset;
312 }
313 // We hope it is a package prefix. Let the caller decide.
314 type = Type.tPackage;
315 return vset;
316 }
317
318 /**
319 * Convert an identifier to a known type, or null.
320 */
321 private ClassDefinition toResolvedType(Environment env, Context ctx,
322 boolean pkgOK) {
323 Identifier rid = ctx.resolveName(env, id);
324 Type t = Type.tClass(rid);
325 if (pkgOK && !env.classExists(t)) {
326 return null;
327 }
328 if (env.resolve(where, ctx.field.getClassDefinition(), t)) {
329 try {
330 ClassDefinition c = env.getClassDefinition(t);
331
332 // Maybe an inherited class hides an apparent class.
333 if (c.isMember()) {
334 ClassDefinition sc = ctx.findScope(env, c.getOuterClass());
335 if (sc != c.getOuterClass()) {
336 Identifier rid2 = ctx.getApparentClassName(env, id);
337 if (!rid2.equals(idNull) && !rid2.equals(rid)) {
338 env.error(where, "inherited.hides.type",
339 id, sc.getClassDeclaration());
340 }
341 }
342 }
343
344 if (!c.getLocalName().equals(id.getFlatName().getName())) {
345 env.error(where, "illegal.mangled.name", id, c);
346 }
347
348 return c;
349 } catch (ClassNotFound ee) {
350 }
351 }
352 return null;
353 }
354
355 /**
356 * Convert an identifier to a type.
357 * If one is not known, use the current package as a qualifier.
358 */
359 Type toType(Environment env, Context ctx) {
360 ClassDefinition c = toResolvedType(env, ctx, false);
361 if (c != null) {
362 return c.getType();
363 }
364 return Type.tError;
365 }
366
367 /**
368 * Convert an expresion to a type in a context where a qualified
369 * type name is expected, e.g., in the prefix of a qualified type
370 * name. We do not necessarily know where the package prefix ends,
371 * so we operate similarly to 'checkAmbiguousName'. This is the
372 * base case -- the first component of the qualified name.
373 */
374 /*-------------------------------------------------------*
375 Type toQualifiedType(Environment env, Context ctx) {
376 // We do not look for non-type fields. Is this correct?
377 ClassDefinition c = toResolvedType(env, ctx, true);
378 // Is it a real type?
379 if (c != null) {
380 return c.getType();
381 }
382 // We hope it is a package prefix. Let the caller decide.
383 return Type.tPackage;
384 }
385 *-------------------------------------------------------*/
386
387 /**
388 * Check if constant: Will it inline away?
389 */
390 public boolean isConstant() {
391 if (implementation != null)
392 return implementation.isConstant();
393 if (field != null) {
394 return field.isConstant();
395 }
396 return false;
397 }
398
399 /**
400 * Inline
401 */
402 public Expression inline(Environment env, Context ctx) {
403 return null;
404 }
405 public Expression inlineValue(Environment env, Context ctx) {
406 if (implementation != null)
407 return implementation.inlineValue(env, ctx);
408 if (field == null) {
409 return this;
410 }
411 try {
412 if (field.isLocal()) {
413 if (field.isInlineable(env, false)) {
414 Expression e = (Expression)field.getValue(env);
415 return (e == null) ? this : e.inlineValue(env, ctx);
416 }
417 return this;
418 }
419 return this;
420 } catch (ClassNotFound e) {
421 throw new CompilerError(e);
422 }
423 }
424 public Expression inlineLHS(Environment env, Context ctx) {
425 if (implementation != null)
426 return implementation.inlineLHS(env, ctx);
427 return this;
428 }
429
430 public Expression copyInline(Context ctx) {
431 if (implementation != null)
432 return implementation.copyInline(ctx);
433 IdentifierExpression e =
434 (IdentifierExpression)super.copyInline(ctx);
435 if (field != null && field.isLocal()) {
436 e.field = ((LocalMember)field).getCurrentInlineCopy(ctx);
437 }
438 return e;
439 }
440
441 public int costInline(int thresh, Environment env, Context ctx) {
442 if (implementation != null)
443 return implementation.costInline(thresh, env, ctx);
444 return super.costInline(thresh, env, ctx);
445 }
446
447 /**
448 * Code local vars (object fields have been inlined away)
449 */
450 int codeLValue(Environment env, Context ctx, Assembler asm) {
451 return 0;
452 }
453 void codeLoad(Environment env, Context ctx, Assembler asm) {
454 asm.add(where, opc_iload + type.getTypeCodeOffset(),
455 new Integer(((LocalMember)field).number));
456 }
457 void codeStore(Environment env, Context ctx, Assembler asm) {
458 LocalMember local = (LocalMember)field;
459 asm.add(where, opc_istore + type.getTypeCodeOffset(),
460 new LocalVariable(local, local.number));
461 }
462 public void codeValue(Environment env, Context ctx, Assembler asm) {
463 codeLValue(env, ctx, asm);
464 codeLoad(env, ctx, asm);
465 }
466
467 /**
468 * Print
469 */
470 public void print(PrintStream out) {
471 out.print(id + "#" + ((field != null) ? field.hashCode() : 0));
472 if (implementation != null) {
473 out.print("/IMPL=");
474 implementation.print(out);
475 }
476 }
477}