KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > aspectj > compiler > base > ast > FieldDec


1 /* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2  *
3  * This file is part of the compiler and core tools for the AspectJ(tm)
4  * programming language; see http://aspectj.org
5  *
6  * The contents of this file are subject to the Mozilla Public License
7  * Version 1.1 (the "License"); you may not use this file except in
8  * compliance with the License. You may obtain a copy of the License at
9  * either http://www.mozilla.org/MPL/ or http://aspectj.org/MPL/.
10  *
11  * Software distributed under the License is distributed on an "AS IS" basis,
12  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13  * for the specific language governing rights and limitations under the
14  * License.
15  *
16  * The Original Code is AspectJ.
17  *
18  * The Initial Developer of the Original Code is Xerox Corporation. Portions
19  * created by Xerox Corporation are Copyright (C) 1999-2002 Xerox Corporation.
20  * All Rights Reserved.
21  *
22  * Contributor(s):
23  */

24
25 package org.aspectj.compiler.base.ast;
26
27 import org.aspectj.compiler.base.*;
28 import org.aspectj.util.JavaStrings;
29 import org.aspectj.compiler.base.cst.*;
30
31 // to get the passes for introductions
32
import org.aspectj.compiler.crosscuts.*;
33
34 import org.aspectj.compiler.base.bcg.Label;
35 import org.aspectj.compiler.base.bcg.CodeBuilder;
36 import org.aspectj.compiler.base.bcg.ClassfileBuilder;
37 import org.aspectj.compiler.base.bcg.FieldBuilder;
38
39 import java.util.*;
40
41 /**
42   * @grammar modifiers typeD id initializer
43   *
44   */

45
46 public class FieldDec extends VarDec {
47     public Dec getEnclosingDec() {
48         return this;
49     }
50
51     /**
52     * We need to do this because we can't properly do name binding of
53     * a reference to a field until we've done constant folding.
54     * Actually what we can't do is type checking of assignment
55     * statements until we've done folding.
56     *
57     * This isn't true for method look-up...
58     *
59     * <pre> static final int x = 2;
60     * byte b = x + 1; // this can't be type checked until we know whether or not x
61     * // is a constant
62     * </pre>
63     *
64     * We can fix this by splitting into:
65     * name-binding
66     * constant-folding: this unfortunately can't be just a walker
67     * assignment type checking */

68
69     // ------------------------------
70
// INTRO from AssignmentCheckerPass (defined in AspectJCompiler)
71

72     public void walkAssignmentCheck(AssignmentCheckerPass walker) {
73         this.ensureFolded(walker);
74     }
75
76     private boolean isFoldedFlag = false;
77     public boolean isFolded() {
78         //System.err.println("in FieldDec E " + this + " " + isFoldedFlag);
79
return isFoldedFlag;
80     }
81     private void setFolded(boolean isFoldedFlag) {
82         this.isFoldedFlag = isFoldedFlag;
83     }
84
85     public /* syncrhonized */ void ensureFolded(AssignmentCheckerPass walker) {
86         //System.err.println("in FieldDec C " + this);
87
if (! isFolded()) {
88             //System.err.println(" in FieldDec D ");
89
setFolded(true);
90             preAssignmentCheck(walker);
91             this.walk(walker);
92             postAssignmentCheck(walker);
93         }
94     }
95     // end intro
96

97     public boolean isField() {
98         return true;
99     }
100
101     public String JavaDoc toShortString() {
102         return addIntroducedFromType(
103              getDeclaringType().toShortString() + "." + getId());
104     }
105
106     public SemanticObject makeCorrespondingSemanticObject() {
107         return new Field(this);
108     }
109
110     public Field getField() { return (Field)getCorrespondingSemanticObject(); }
111
112     public String JavaDoc getKind() { return "field"; }
113
114     public ASTObject postFixAST(final ASTFixerPass fixer) {
115         if (getBytecodeTypeDec() instanceof InterfaceDec) {
116             getModifiers().setValue(Modifiers.FINAL|Modifiers.PUBLIC|Modifiers.STATIC);
117         }
118         //??? don't output any blank finals to javac or .class files for now
119
if (isFinal() && initializer == null) {
120             modifiers.setFinal(false);
121         }
122         return this;
123     }
124
125     //INTRO from MixinImplementationPass
126
public ASTObject postImplementMixin(MixinImplementationPass fixer) {
127         final TypeDec inTypeDec = getBytecodeTypeDec();
128
129         if (!(inTypeDec instanceof InterfaceDec)) return this;
130
131         if (isFinal() && isStatic()) return this;
132
133         if (isStatic()) {
134             ((InterfaceDec)inTypeDec).addToHelperClass(this);
135             return null;
136         }
137
138         Type onInterfaceType = getDeclaringType();
139
140         getBackdoorSetterMethod().setBody(null);
141         getBackdoorGetterMethod().setBody(null);
142
143         Set topmostImplementors =
144             Type.filterTopTypes(Type.filterConcreteTypes(inTypeDec.getType().getSubTypes()));
145
146         for (Iterator i = topmostImplementors.iterator(); i.hasNext(); ) {
147             final Type implType = (Type)i.next();
148             TypeDec implDec = implType.getTypeDec();
149
150             FieldDec newDec = (FieldDec)fixer.copyToClass(this, implDec);
151             implDec.getBody().add(0, newDec);
152             newDec.setDeclaringType(implType); //this.getLexicalType());
153
//newDec.setLexicalType(implType);
154
newDec.getBackdoorGetterMethod();
155             newDec.getBackdoorSetterMethod();
156         }
157
158         return null;
159     }
160
161     //XXX We need to better handle the block/code scope of field initializers
162
//INTRO from ScopePass
163
public void walkScope(ScopeWalker walker) {
164         //XXX there must be a more elegant way to do this
165
Expr saveInitializer = initializer; initializer = null;
166         super.walkScope(walker);
167         initializer = saveInitializer;
168
169         if (!walker.walkBodies() || initializer == null) return;
170
171         walker.pushScope(makeBlockScope(walker));
172         //System.out.println("walking scope for init: " + initializer);
173
setInitializer((Expr)walker.process(initializer));
174 // System.out.println(" walked: " + initializer + ", " + initializer.unparse() +
175
// ", " + initializer.getType());
176
walker.popScope();
177     }
178
179     private String JavaDoc makeBackdoorId(String JavaDoc kind) {
180         //??? need to add type into mangled name for no inheritance surprises
181
String JavaDoc ret = getBytecodeId() + "_aj" + kind;
182         return getAST().makeGeneratedName(ret);
183     }
184
185
186     /** This refers backdoor method for privileged aspects and
187      * for access from inner classes (for bytecode compilation)
188      * for getting field's value
189      */

190     private MethodDec backdoorGetterMethod;
191
192     /** This refers backdoor method for privileged aspects and
193      * for access from inner classes (for bytecode compilation)
194      * for setting field's value
195      */

196     private MethodDec backdoorSetterMethod;
197
198     public MethodDec getBackdoorGetterMethod() {
199         if (backdoorGetterMethod != null) return backdoorGetterMethod;
200
201         final AST ast = getAST();
202
203         String JavaDoc id = makeBackdoorId("get");
204         Modifiers modifiers = ast.makeModifiers(Modifiers.PUBLIC);
205         if (isStatic()) modifiers.setStatic(true);
206
207         Formals formals = ast.makeFormals();
208         Expr thisExpr;
209         if (isStatic()) thisExpr = ast.makeTypeExpr(getBytecodeTypeDec().getType());
210         else thisExpr = ast.makeThis(getBytecodeTypeDec().getType());
211         Stmt stmt = ast.makeReturn(ast.makeGet(thisExpr, this));
212
213         MethodDec ret = ast.makeMethod(modifiers, getTypeD().getType(), id, formals,
214                    ast.makeBlock(stmt));
215
216         getBytecodeTypeDec().addToBody(ret);
217
218         backdoorGetterMethod = ret;
219         return backdoorGetterMethod;
220     }
221
222     public MethodDec getBackdoorSetterMethod() {
223         if (backdoorSetterMethod != null) return backdoorSetterMethod;
224
225         final AST ast = getAST();
226
227         String JavaDoc id = makeBackdoorId("set");
228         Modifiers modifiers = ast.makeModifiers(Modifiers.PUBLIC);
229         if (isStatic()) modifiers.setStatic(true);
230
231         FormalDec newValue = ast.makeFormal(getTypeD().getType(), "newValue");
232         Formals formals = ast.makeFormals(newValue);
233
234         Stmt stmt = ast.makeReturn(ast.makeSet(this, ast.makeVar(newValue)));
235
236         MethodDec ret = ast.makeMethod(modifiers, getTypeD().getType(), id, formals,
237                    ast.makeBlock(stmt));
238
239         getBytecodeTypeDec().addToBody(ret);
240
241         backdoorSetterMethod = ret;
242         return backdoorSetterMethod;
243     }
244
245     public void unparse(CodeWriter writer) {
246         super.unparse(writer);
247     }
248
249     public boolean isConstant() {
250         // according to section 15.28 of the JLS non-static finals are constants
251
return isFinal() && /*isStatic() &&*/ !getType().isObject() &&
252             initializer != null && initializer instanceof LiteralExpr;
253     }
254
255     private AssignExpr assignExpr = null;
256
257     public AssignExpr getAssignExpr() {
258         if (assignExpr != null) return assignExpr;
259
260         //XXX this is a mistake
261
if (isStatic() && getDeclaringType().isInterface() &&getOptions().usejavac) {
262             return null;
263         }
264
265         Expr fieldInit = getInitializer();
266         final AST ast = getAST();
267
268         if (fieldInit != null && !isConstant()) {
269             setInitializer(null);
270             if (isFinal() && isSynthetic()) getModifiers().setFinal(false);
271             fieldInit.clearParent();
272             assignExpr = isStatic() ? ast.makeSet(this, fieldInit)
273                                     : ast.makeSet(ast.makeThis(getBytecodeTypeDec().getType()), this, fieldInit);
274             Stmt stmt = new FromDecStmt(ast.getSourceLocation(),
275                 ast.makeStmt(assignExpr), this);
276
277             Stmts stmts = ast.makeStmts(stmt);
278             Dec init;
279             if (isStatic()) init = ast.makeStaticInitializer(stmts);
280             else init = ast.makeInitializer(stmts);
281
282             init.setSource(this);
283
284             int index = getBytecodeTypeDec().getBody().indexOf(this);
285             getBytecodeTypeDec().getBody().add(index+1, init);
286             assignExpr.setSource(this); //Location(getSourceLocation());
287
return assignExpr;
288         } else {
289             return null;
290         }
291     }
292
293     // ------------------------------
294
// Intro: ForwardReferenceChecker
295

296     public void walkForwardReference(ForwardReferenceChecker w) {
297         this.walk(w.createInitializerChecker(isStatic()));
298         w.addFieldDec(this);
299     }
300
301     // ------------------------------
302
// INTRO from InnerInfoPass
303

304     public void walkInnerInfo(InnerInfoPass w) {
305         int context = w.inMember(isStatic());
306         super.walkInnerInfo(w);
307         w.restoreContext(context);
308     }
309
310     // ------------------------------
311
// Intro: FrameLocPass
312

313     // We don't assign frame locations here
314

315     public void walkFrameLoc(FrameLocPass walker) {
316     }
317
318     // ------------------------------
319
// bcg
320
/** This method takes care of generating code for Member decs. At
321         this point, we should not have initializers unless they're
322         constants. */

323     protected void cgMember(ClassfileBuilder cb) {
324         if (getOptions().bcgverbose) System.err.println("generating for " + this);
325         FieldBuilder fb = cb.getFieldBuilder();
326         fb.addAccessFlags(getModifiers().getValue());
327         fb.setName(getBytecodeId());
328         fb.setDescriptor(getDescriptor());
329         if (isDeprecated()) fb.setDeprecated();
330         //XXX get this right -- if (isSynthetic()) fb.setSynthetic();
331
Expr init = getInitializer();
332         if (init != null) {
333             if (!(init instanceof LiteralExpr)) {
334                 this.showError("expected literal here: " + toShortString());
335             }
336             getType().foldCast((LiteralExpr) init).addConstant(fb);
337         }
338         cb.addField(fb);
339     }
340
341     //BEGIN: Generated from @child and @property
342

343     public FieldDec(SourceLocation location, Modifiers _modifiers, TypeD _typeD, String JavaDoc _id, Expr _initializer) {
344         super(location, _modifiers, _typeD, _id, _initializer);
345
346     }
347     protected FieldDec(SourceLocation source) {
348         super(source);
349     }
350
351     public ASTObject copyWalk(CopyWalker walker) {
352         FieldDec ret = new FieldDec(getSourceLocation());
353         ret.preCopy(walker, this);
354         if (modifiers != null) ret.setModifiers( (Modifiers)walker.process(modifiers) );
355         if (typeD != null) ret.setTypeD( (TypeD)walker.process(typeD) );
356         ret.id = id;
357         if (initializer != null) ret.setInitializer( (Expr)walker.process(initializer) );
358         return ret;
359     }
360
361
362     public String JavaDoc getDefaultDisplayName() {
363         return "FieldDec(id: "+id+")";
364     }
365
366     //END: Generated from @child and @property
367
}
368
Popular Tags