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+
26+package sun.tools.tree;
27+
28+import sun.tools.java.*;
29+import sun.tools.asm.Assembler;
30+import sun.tools.asm.LocalVariable;
31+import java.io.PrintStream;
32+import 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+ */
39+public
40+class 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+}