KickJava   Java API By Example, From Geeks To Geeks.

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


1 /* -*- 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 import org.aspectj.compiler.base.ExceptionFinder;
27
28 import org.aspectj.compiler.base.*;
29
30 import java.util.*;
31
32 import org.aspectj.compiler.base.cst.*;
33
34 import org.aspectj.compiler.base.bcg.CodeBuilder;
35 import org.aspectj.compiler.base.bcg.MethodBuilder;
36 import org.aspectj.compiler.base.bcg.ClassfileBuilder;
37
38 /**
39   * @grammar ...
40   * @child Modifiers modifiers
41   * @child Formals formals
42   * @child TypeDs throws
43   * @child CodeBody body
44   */

45 public abstract class CodeDec extends Dec implements PossibleSoftThrowable {
46     private boolean _isSoft = false;
47     public boolean isSoftThrowable() { return _isSoft; }
48     public void setSoftThrowable() { _isSoft = true; }
49
50     // ------------------------------
51
// INTRO from FlowCheckerPass
52

53     // overridden in InitializerDec, should not be overridden elsewhere
54
public void walkFlow(FlowCheckerPass w) {
55         if (getBody() != null) {
56             setupFlowWalker(w);
57             w.setLive(true);
58             w.process(getBody());
59
60             if (! getResultType().isVoid() && w.isLive()) {
61                 showError("missing return statement");
62             }
63         }
64     }
65
66     /** set up the flow walker, by adding implicit variables like
67         thisJoinPoint, etc */

68
69     protected void setupFlowWalker(FlowCheckerPass w) { }
70
71     // ------------------------------
72
// INTRO from ByteCodeCleanupPass
73

74     public final void walkCleanup(ByteCodeCleanupPass w) {
75         w.setLive(true);
76         super.walkCleanup(w);
77     }
78
79     public ASTObject postCleanup(ByteCodeCleanupPass w) {
80         if (getBody() != null
81                 && getResultType().isVoid()
82                 && w.isLive()) {
83             ReturnStmt s =
84                 (ReturnStmt) getAST().makeReturn(null).setSource(getBody());
85             s.setCompletesNormally(false);
86             getBody().getStmts().add(s);
87             getBody().setCompletesNormally(false);
88         }
89         return this;
90     }
91
92     // ------------------------------
93
// INTRO from InnerInfoPass
94

95     public void walkInnerInfo(InnerInfoPass w) {
96         int context = w.inMember(isStatic());
97         super.walkInnerInfo(w);
98         w.restoreContext(context);
99     }
100     // end intro
101

102     public static CodeBody blockToBody(BlockStmt block) {
103         if (block == null) return null;
104         block.getStmts().clearParent();
105         CodeBody body = new CodeBody(block.getSourceLocation(),block.getStmts(),true);
106         body.setSource(block);
107         return body;
108     }
109
110     public void setBody(BlockStmt block) {
111         setBody(blockToBody(block));
112     }
113
114
115     public abstract String JavaDoc getId();
116     public abstract TypeD getResultTypeD();
117
118     //XXX ugly
119
public Type getResultType() {
120         return getResultTypeD().getType();
121     }
122
123     public boolean canThrow(Type t) {
124         if (t.isUncheckedThrowable()) return true;
125         if (_throws == null) return false;
126         for (int i=0; i<_throws.size(); i++) {
127             if (t.isSubtypeOf(_throws.get(i).getType())) return true;
128         }
129         return false;
130     }
131     
132     
133     public void addThrowsType(Type t) {
134         if (canThrow(t)) return;
135         
136         if (_throws == null) {
137             _throws = getAST().makeTypeDs();
138         }
139         
140         _throws.add(t.makeTypeD());
141     }
142     
143     public void addThrows(Collection throwTypes) {
144         for (Iterator i = throwTypes.iterator(); i.hasNext(); ) {
145             addThrowsType((Type)i.next());
146         }
147     }
148     /**
149      * returns the checked exceptions that the context expects could be thrown here
150      *
151      * guarantees that if x is a member then no subtype(x) is a member
152      *
153      * XXX figure out what the performance issues are and if we should cache this
154      */

155     public Set getPossibleCheckedExceptions() {
156         if (_throws == null) return Collections.EMPTY_SET;
157         Set ret = new HashSet();
158         
159         for (int i=0; i<_throws.size(); i++) {
160             ret.add(_throws.get(i).getType());
161         }
162         
163         return Type.filterTopTypes(ret);
164     }
165
166     public void checkSpec() {
167         // checks that all entries in 'throws' are subtypes of Throwable
168
if (_throws == null) return;
169         Type throwableType = getTypeManager().getThrowableType();
170         for (int i=0; i<_throws.size(); i++) {
171             TypeD throwsTypeD = _throws.get(i);
172             if (!throwsTypeD.getType().isSubtypeOf(throwableType)) {
173                 throwsTypeD.showTypeError(throwsTypeD.getType(), throwableType);
174             }
175         }
176     }
177
178     public boolean appearsStaticToCaller() { return isStatic(); }
179
180
181     public boolean hasThis() {
182         return !isStatic();
183     }
184
185     public boolean isAlmostApplicable(Exprs params) {
186         return params.size() == getFormals().size();
187     }
188
189     public boolean isApplicable(Exprs parameters) {
190         return getFormals().canBeCalledWith(parameters);
191     }
192
193     public boolean conflictsWith(Dec otherDec) {
194         if (!getId().equals(otherDec.getId())) return false;
195         if (!this.isAccessible(otherDec) && !otherDec.isAccessible(this)) return false;
196
197         if (!(otherDec instanceof CodeDec)) return false;
198
199         CodeDec otherCodeDec = (CodeDec)otherDec;
200
201 // System.out.println("matching formals: " + getFormals().toShortString() + " with " +
202
// otherCodeDec.getFormals().toShortString() + " == " +
203
// getFormals().matches(otherCodeDec.getFormals()));
204

205         return getFormals().matches(otherCodeDec.getFormals());
206     }
207
208
209     public boolean isMoreSpecificThan(Dec otherDec) {
210         if (!(otherDec instanceof CodeDec)) return false;
211
212         CodeDec other = (CodeDec)otherDec;
213
214         if (!super.isMoreSpecificThan(other)) return false;
215         // is m1 more specific than m2?
216

217         // require that A1i is method convertable to A2i
218
Formals formals1 = getFormals();
219         Formals formals2 = other.getFormals();
220         if (formals1.size() != formals2.size()) return false;
221         for(int i=0; i<formals1.size(); i++) {
222             if (!formals1.get(i).getType().isMethodConvertableTo(formals2.get(i).getType())) {
223                 return false;
224             }
225         }
226
227         return true;
228     }
229     
230     public Set getEffectivelyFinalFormals() {
231     FinalFinderWalker ffw = new FinalFinderWalker(getCompiler(), getFormals().makeSet());
232     ffw.process(getBody());
233     return ffw.curr;
234     }
235     
236     private class FinalFinderWalker extends Walker {
237     Set /* FormalDec */ curr;
238             
239     FinalFinderWalker(JavaCompiler c, Set curr) {
240         super(c);
241         this.curr = curr;
242     }
243     
244     public void postProcess(ASTObject o) {
245         if (o instanceof BangExpr) {
246             BangExpr be = (BangExpr) o;
247             Expr lhs = be.getLhs();
248             if (lhs instanceof VarExpr) {
249                 VarDec vd = ((VarExpr)lhs).getVarDec();
250                 curr.remove(vd);
251             }
252         }
253     }
254         
255     }
256
257
258     //INTRO from ScopePass
259
public void preScope(ScopeWalker walker) {
260         walker.pushScope(makeBlockScope(walker));
261     }
262     public ASTObject postScope(ScopeWalker walker) { walker.popScope(); return this; }
263
264     //XXX yet another non-thread-safe hack
265
boolean computingMinimalThrows = false;
266     public void computeMinimalThrows() {
267         //getCompiler().showMessage("compute minimal throws for: " + this.getId());
268
//System.out.println("compute minimal throws for: " + this.toShortString());
269
//this.display(2);
270
if (computingMinimalThrows || getBody() == null) return;
271
272         computingMinimalThrows = true;
273         Set exceptions = ExceptionFinder.getPossibleExceptions(getBody(), false);
274         //System.out.println(exceptions);
275
computingMinimalThrows = false;
276
277         final int N = exceptions.size();
278         if (N == 0) {
279             setThrows(null);
280             return;
281         }
282
283         exceptions = Type.filterTopTypes(exceptions);
284
285         TypeDs newThrows = getAST().makeTypeDs(); //new TypeDs(getCompiler());
286
for(Iterator iter = exceptions.iterator(); iter.hasNext(); ) {
287             Type type = (Type)iter.next();
288             newThrows.add(type.makeTypeD());
289         }
290         setThrows(newThrows);
291     }
292
293 // private Set callExprs; // = new HashSet();
294
public Set getCallExprs() {
295 // return callExprs;
296
return null;
297     }
298 //
299
// public void noteCallExpr(Expr callExpr) {
300
// if (callExprs == null)
301
// callExprs = new HashSet();
302
// callExprs.add(callExpr);
303
// }
304
//
305
// public void cleanupCrossRefs() {
306
// callExprs = null;
307
// }
308

309     public void cleanup() {
310         //callExprs = null;
311
if (body != null)
312             body.cleanup();
313         super.cleanup();
314     }
315
316     // ------------------------------
317
// Intro: FrameLocPass
318

319     private int frameSize;
320     public int getFrameSize() { return frameSize; }
321     public void setFrameSize(int frameSize) { this.frameSize = frameSize; }
322
323     public void walkFrameLoc(FrameLocPass walker) {
324         walker.setfs((!isStatic() || this instanceof ConstructorDec) ?
325                      1 : 0);
326         super.walkFrameLoc(walker); // this will walk the formals first.
327
setFrameSize(walker.getmaxfs());
328     }
329
330     // ------------------------------
331
// INTRO: LocalClassPass.AnalysisWalker
332

333     public void walkAnalysis(LocalClassPass.AnalysisWalker walker) {
334         walker.enterCodeDec(this);
335         walker.inCode(isStatic());
336         this.walk(walker);
337         walker.leaveCodeDec();
338     }
339
340     // ------------------------------
341
// bcg
342

343     /** This method takes care of generating code for Member decs. At
344         this point, we have a number of invariants:
345
346         <ul>
347           <li> implicit return statements are inserted</li>
348
349           <li> all return statements are typechecked, with appropriate
350                casts inserted, so we know what kind of return bytecode to
351                generate based on the return stmt rather than on the return
352                type of the method.</li>
353         </ul>
354     */

355     protected void cgMember(ClassfileBuilder cfb) {
356         if (getOptions().bcgverbose) System.err.println("generating for " + this);
357         MethodBuilder mb = cfb.getMethodBuilder();
358         mb.addAccessFlags(getModifiers().getValue());
359         mb.setName(getInternalId());
360         mb.setDescriptor(getDescriptor());
361         if (isDeprecated()) mb.setDeprecated();
362         //XXX get this right -- if (isSynthetic()) mb.setSynthetic();
363
TypeDs exns = getThrows();
364         if (exns != null) {
365             for (Iterator i = exns.iterator(); i.hasNext(); ) {
366                 TypeD typeD = (TypeD)i.next();
367                 mb.addToExceptionsAttribute((NameType)typeD.getType());
368             }
369         }
370
371         if (getBody() != null) {
372             CodeBuilder cb = mb.getCodeBuilder();
373             cgCodeMember(cb);
374             mb.setCode(cb);
375         }
376         cfb.addMethod(mb);
377     }
378
379     /** generate code for the body. Assumes there is a body.
380
381         @param cb the codeBuilder into which to generate code
382     */

383     protected void cgCodeMember(CodeBuilder cb) {
384         throw new RuntimeException JavaDoc("unsupported " + this);
385     }
386
387     /** return the bytecode type descriptor for the member. */
388     public String JavaDoc getDescriptor() {
389         throw new RuntimeException JavaDoc("unsupported " + this);
390     }
391
392     /** return the change in stack that would result from invoking
393         this codeDec. This is the size of the return value minus the
394         size of the argument values (including the implicit this
395         object). It is typically negative for coded members with
396         arguments. */

397     public int getStackDelta() {
398         throw new RuntimeException JavaDoc("unsupported " + this);
399     }
400
401     String JavaDoc getInternalId() {
402         return getBytecodeId();
403     }
404
405     //BEGIN: Generated from @child and @property
406
protected Modifiers modifiers;
407     public Modifiers getModifiers() { return modifiers; }
408     public void setModifiers(Modifiers _modifiers) {
409         if (_modifiers != null) _modifiers.setParent(this);
410         modifiers = _modifiers;
411     }
412
413     protected Formals formals;
414     public Formals getFormals() { return formals; }
415     public void setFormals(Formals _formals) {
416         if (_formals != null) _formals.setParent(this);
417         formals = _formals;
418     }
419
420     protected TypeDs _throws;
421     public TypeDs getThrows() { return _throws; }
422     public void setThrows(TypeDs __throws) {
423         if (__throws != null) __throws.setParent(this);
424         _throws = __throws;
425     }
426
427     protected CodeBody body;
428     public CodeBody getBody() { return body; }
429     public void setBody(CodeBody _body) {
430         if (_body != null) _body.setParent(this);
431         body = _body;
432     }
433
434     public CodeDec(SourceLocation location, Modifiers _modifiers, Formals _formals, TypeDs __throws, CodeBody _body) {
435         super(location);
436         setModifiers(_modifiers);
437         setFormals(_formals);
438         setThrows(__throws);
439         setBody(_body);
440     }
441     protected CodeDec(SourceLocation source) {
442         super(source);
443     }
444
445     public ASTObject getChildAt(int childIndex) {
446         switch(childIndex) {
447         case 0: return modifiers;
448         case 1: return formals;
449         case 2: return _throws;
450         case 3: return body;
451         default: return super.getChildAt(childIndex);
452         }
453     }
454      public String JavaDoc getChildNameAt(int childIndex) {
455         switch(childIndex) {
456         case 0: return "modifiers";
457         case 1: return "formals";
458         case 2: return "throws";
459         case 3: return "body";
460         default: return super.getChildNameAt(childIndex);
461         }
462     }
463      public void setChildAt(int childIndex, ASTObject child) {
464         switch(childIndex) {
465         case 0: setModifiers((Modifiers)child); return;
466         case 1: setFormals((Formals)child); return;
467         case 2: setThrows((TypeDs)child); return;
468         case 3: setBody((CodeBody)child); return;
469         default: super.setChildAt(childIndex, child); return;
470         }
471     }
472      public int getChildCount() {
473         return 4;
474     }
475
476     public String JavaDoc getDefaultDisplayName() {
477         return "CodeDec()";
478     }
479
480     //END: Generated from @child and @property
481
}
482
Popular Tags