KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > polyglot > ext > jl > ast > MethodDecl_c


1 package polyglot.ext.jl.ast;
2
3 import java.util.*;
4
5 import polyglot.ast.*;
6 import polyglot.main.Report;
7 import polyglot.types.*;
8 import polyglot.util.CodeWriter;
9 import polyglot.util.CollectionUtil;
10 import polyglot.util.Position;
11 import polyglot.util.SubtypeSet;
12 import polyglot.util.TypedList;
13 import polyglot.visit.*;
14
15 /**
16  * A method declaration.
17  */

18 public class MethodDecl_c extends Term_c implements MethodDecl
19 {
20     protected Flags flags;
21     protected TypeNode returnType;
22     protected String JavaDoc name;
23     protected List formals;
24     protected List throwTypes;
25     protected Block body;
26     protected MethodInstance mi;
27
28     public MethodDecl_c(Position pos, Flags flags, TypeNode returnType, String JavaDoc name, List formals, List throwTypes, Block body) {
29     super(pos);
30     this.flags = flags;
31     this.returnType = returnType;
32     this.name = name;
33     this.formals = TypedList.copyAndCheck(formals, Formal.class, true);
34     this.throwTypes = TypedList.copyAndCheck(throwTypes, TypeNode.class, true);
35     this.body = body;
36     }
37
38     /** Get the flags of the method. */
39     public Flags flags() {
40     return this.flags;
41     }
42
43     /** Set the flags of the method. */
44     public MethodDecl flags(Flags flags) {
45     MethodDecl_c n = (MethodDecl_c) copy();
46     n.flags = flags;
47     return n;
48     }
49
50     /** Get the return type of the method. */
51     public TypeNode returnType() {
52     return this.returnType;
53     }
54
55     /** Set the return type of the method. */
56     public MethodDecl returnType(TypeNode returnType) {
57     MethodDecl_c n = (MethodDecl_c) copy();
58     n.returnType = returnType;
59     return n;
60     }
61
62     /** Get the name of the method. */
63     public String JavaDoc name() {
64     return this.name;
65     }
66
67     /** Set the name of the method. */
68     public MethodDecl name(String JavaDoc name) {
69     MethodDecl_c n = (MethodDecl_c) copy();
70     n.name = name;
71     return n;
72     }
73
74     /** Get the formals of the method. */
75     public List formals() {
76     return Collections.unmodifiableList(this.formals);
77     }
78
79     /** Set the formals of the method. */
80     public MethodDecl formals(List formals) {
81     MethodDecl_c n = (MethodDecl_c) copy();
82     n.formals = TypedList.copyAndCheck(formals, Formal.class, true);
83     return n;
84     }
85
86     /** Get the exception types of the method. */
87     public List throwTypes() {
88     return Collections.unmodifiableList(this.throwTypes);
89     }
90
91     /** Set the exception types of the method. */
92     public MethodDecl throwTypes(List throwTypes) {
93     MethodDecl_c n = (MethodDecl_c) copy();
94     n.throwTypes = TypedList.copyAndCheck(throwTypes, TypeNode.class, true);
95     return n;
96     }
97
98     /** Get the body of the method. */
99     public Block body() {
100     return this.body;
101     }
102
103     /** Set the body of the method. */
104     public CodeDecl body(Block body) {
105     MethodDecl_c n = (MethodDecl_c) copy();
106     n.body = body;
107     return n;
108     }
109
110     /** Get the method instance of the method. */
111     public MethodInstance methodInstance() {
112     return mi;
113     }
114
115     /** Set the method instance of the method. */
116     public MethodDecl methodInstance(MethodInstance mi) {
117     MethodDecl_c n = (MethodDecl_c) copy();
118     n.mi = mi;
119     return n;
120     }
121
122     public CodeInstance codeInstance() {
123     return procedureInstance();
124     }
125
126     /** Get the procedure instance of the method. */
127     public ProcedureInstance procedureInstance() {
128     return mi;
129     }
130
131     /** Reconstruct the method. */
132     protected MethodDecl_c reconstruct(TypeNode returnType, List formals, List throwTypes, Block body) {
133     if (returnType != this.returnType || ! CollectionUtil.equals(formals, this.formals) || ! CollectionUtil.equals(throwTypes, this.throwTypes) || body != this.body) {
134         MethodDecl_c n = (MethodDecl_c) copy();
135         n.returnType = returnType;
136         n.formals = TypedList.copyAndCheck(formals, Formal.class, true);
137         n.throwTypes = TypedList.copyAndCheck(throwTypes, TypeNode.class, true);
138         n.body = body;
139         return n;
140     }
141
142     return this;
143     }
144
145     /** Visit the children of the method. */
146     public Node visitChildren(NodeVisitor v) {
147         List formals = visitList(this.formals, v);
148     TypeNode returnType = (TypeNode) visitChild(this.returnType, v);
149     List throwTypes = visitList(this.throwTypes, v);
150     Block body = (Block) visitChild(this.body, v);
151     return reconstruct(returnType, formals, throwTypes, body);
152     }
153
154     public NodeVisitor buildTypesEnter(TypeBuilder tb) throws SemanticException {
155         return tb.pushCode();
156     }
157
158     public Node buildTypes(TypeBuilder tb) throws SemanticException {
159         TypeSystem ts = tb.typeSystem();
160
161         List l = new ArrayList(formals.size());
162         for (int i = 0; i < formals.size(); i++) {
163           l.add(ts.unknownType(position()));
164         }
165
166         List m = new ArrayList(throwTypes().size());
167         for (int i = 0; i < throwTypes().size(); i++) {
168           m.add(ts.unknownType(position()));
169         }
170
171         MethodInstance mi = ts.methodInstance(position(), ts.Object(),
172                                               Flags.NONE,
173                                               ts.unknownType(position()),
174                                               name, l, m);
175         return methodInstance(mi);
176     }
177
178     /** Build type objects for the method. */
179     public NodeVisitor disambiguateEnter(AmbiguityRemover ar) throws SemanticException {
180         if (ar.kind() == AmbiguityRemover.SUPER) {
181             return ar.bypassChildren(this);
182         }
183         else if (ar.kind() == AmbiguityRemover.SIGNATURES) {
184             if (body != null) {
185                 return ar.bypass(body);
186             }
187         }
188
189         return ar;
190     }
191
192     public Node disambiguate(AmbiguityRemover ar) throws SemanticException {
193         if (ar.kind() == AmbiguityRemover.SIGNATURES) {
194             Context c = ar.context();
195             TypeSystem ts = ar.typeSystem();
196
197             ParsedClassType ct = c.currentClassScope();
198
199             MethodInstance mi = makeMethodInstance(ct, ts);
200
201             return flags(mi.flags()).methodInstance(mi);
202         }
203
204         return this;
205     }
206
207     public NodeVisitor addMembersEnter(AddMemberVisitor am) {
208         ParsedClassType ct = am.context().currentClassScope();
209         ct.addMethod(mi);
210         return am.bypassChildren(this);
211     }
212      
213     public Context enterScope(Context c) {
214         if (Report.should_report(TOPICS, 5))
215         Report.report(5, "enter scope of method " + name);
216         c = c.pushCode(mi);
217         return c;
218     }
219
220     /** Type check the method. */
221     public Node typeCheck(TypeChecker tc) throws SemanticException {
222     TypeSystem ts = tc.typeSystem();
223
224         if (tc.context().currentClass().flags().isInterface()) {
225             if (flags().isProtected() || flags().isPrivate()) {
226                 throw new SemanticException("Interface methods must be public.",
227                                             position());
228             }
229         }
230
231         try {
232             ts.checkMethodFlags(flags());
233         }
234         catch (SemanticException e) {
235             throw new SemanticException(e.getMessage(), position());
236         }
237
238     if (body == null && ! (flags().isAbstract() || flags().isNative())) {
239         throw new SemanticException("Missing method body.", position());
240     }
241
242     if (body != null && flags().isAbstract()) {
243         throw new SemanticException(
244         "An abstract method cannot have a body.", position());
245     }
246
247     if (body != null && flags().isNative()) {
248         throw new SemanticException(
249         "A native method cannot have a body.", position());
250     }
251
252         for (Iterator i = throwTypes().iterator(); i.hasNext(); ) {
253             TypeNode tn = (TypeNode) i.next();
254             Type t = tn.type();
255             if (! t.isThrowable()) {
256                 throw new SemanticException("Type \"" + t +
257                     "\" is not a subclass of \"" + ts.Throwable() + "\".",
258                     tn.position());
259             }
260         }
261
262         // check that inner classes do not declare static methods
263
if (flags().isStatic() &&
264               methodInstance().container().toClass().isInnerClass()) {
265             // it's a static method in an inner class.
266
throw new SemanticException("Inner classes cannot declare " +
267                     "static methods.", this.position());
268         }
269
270         overrideMethodCheck(tc);
271
272     return this;
273     }
274
275     protected void overrideMethodCheck(TypeChecker tc) throws SemanticException {
276         TypeSystem ts = tc.typeSystem();
277
278         for (Iterator j = mi.implemented().iterator(); j.hasNext(); ) {
279             MethodInstance mj = (MethodInstance) j.next();
280
281             if (! ts.isAccessible(mj, tc.context())) {
282                 continue;
283             }
284
285             ts.checkOverride(mi, mj);
286         }
287     }
288
289     /** Check exceptions thrown by the method. */
290     public Node exceptionCheck(ExceptionChecker ec) throws SemanticException {
291     TypeSystem ts = ec.typeSystem();
292
293     SubtypeSet s = (SubtypeSet) ec.throwsSet();
294
295     for (Iterator i = s.iterator(); i.hasNext(); ) {
296         Type t = (Type) i.next();
297
298         boolean throwDeclared = false;
299
300         if (! t.isUncheckedException()) {
301         for (Iterator j = throwTypes().iterator(); j.hasNext(); ) {
302             TypeNode tn = (TypeNode) j.next();
303             Type tj = tn.type();
304
305             if (ts.isSubtype(t, tj)) {
306             throwDeclared = true;
307             break;
308             }
309         }
310
311         if (! throwDeclared) {
312                     ec.throwsSet().clear();
313                     Position pos = ec.exceptionPosition(t);
314                     throw new SemanticException("The exception \"" + t +
315                         "\" must either be caught or declared to be thrown.",
316                 pos==null?position():pos);
317         }
318         }
319     }
320
321     ec.throwsSet().clear();
322
323     return super.exceptionCheck(ec);
324     }
325
326     public String JavaDoc toString() {
327     return flags.translate() + returnType + " " + name + "(...)";
328     }
329
330     /** Write the method to an output file. */
331     public void prettyPrintHeader(Flags flags, CodeWriter w, PrettyPrinter tr) {
332     w.begin(0);
333     w.write(flags.translate());
334     print(returnType, w, tr);
335     w.write(" " + name + "(");
336
337     w.begin(0);
338
339     for (Iterator i = formals.iterator(); i.hasNext(); ) {
340         Formal f = (Formal) i.next();
341         print(f, w, tr);
342
343         if (i.hasNext()) {
344         w.write(",");
345         w.allowBreak(0, " ");
346         }
347     }
348
349     w.end();
350     w.write(")");
351
352     if (! throwTypes().isEmpty()) {
353         w.allowBreak(6);
354         w.write("throws ");
355
356         for (Iterator i = throwTypes().iterator(); i.hasNext(); ) {
357             TypeNode tn = (TypeNode) i.next();
358         print(tn, w, tr);
359
360         if (i.hasNext()) {
361             w.write(",");
362             w.allowBreak(4, " ");
363         }
364         }
365     }
366
367     w.end();
368     }
369
370     public void prettyPrint(CodeWriter w, PrettyPrinter tr) {
371         prettyPrintHeader(flags(), w, tr);
372
373     if (body != null) {
374         printSubStmt(body, w, tr);
375     }
376     else {
377         w.write(";");
378     }
379     }
380
381     public void translate(CodeWriter w, Translator tr) {
382         Context c = tr.context();
383     Flags flags = flags();
384
385     if (c.currentClass().flags().isInterface()) {
386         flags = flags.clearPublic();
387         flags = flags.clearAbstract();
388     }
389
390         prettyPrintHeader(flags, w, tr);
391
392     if (body != null) {
393         printSubStmt(body, w, tr);
394     }
395     else {
396         w.write(";");
397     }
398     }
399
400     public void dump(CodeWriter w) {
401     super.dump(w);
402
403     if (mi != null) {
404         w.allowBreak(4, " ");
405         w.begin(0);
406         w.write("(instance " + mi + ")");
407         w.end();
408     }
409
410         w.allowBreak(4, " ");
411         w.begin(0);
412         w.write("(name " + name + ")");
413         w.end();
414     }
415
416     protected MethodInstance makeMethodInstance(ClassType ct, TypeSystem ts)
417     throws SemanticException {
418
419     List argTypes = new LinkedList();
420     List excTypes = new LinkedList();
421
422     for (Iterator i = formals.iterator(); i.hasNext(); ) {
423         Formal f = (Formal) i.next();
424         argTypes.add(f.declType());
425     }
426
427     for (Iterator i = throwTypes().iterator(); i.hasNext(); ) {
428         TypeNode tn = (TypeNode) i.next();
429         excTypes.add(tn.type());
430     }
431
432     Flags flags = this.flags;
433
434     if (ct.flags().isInterface()) {
435         flags = flags.Public().Abstract();
436     }
437
438     return ts.methodInstance(position(),
439                      ct, flags, returnType.type(), name,
440                              argTypes, excTypes);
441     }
442
443     /**
444      * Return the first (sub)term performed when evaluating this
445      * term.
446      */

447     public Term entry() {
448         return listEntry(formals(), (body()==null? this : body().entry()));
449     }
450
451     /**
452      * Visit this term in evaluation order.
453      */

454     public List acceptCFG(CFGBuilder v, List succs) {
455         if (body() == null) {
456             v.visitCFGList(formals(), this);
457         }
458         else {
459             v.visitCFGList(formals(), body().entry());
460             v.visitCFG(body(), this);
461         }
462         return succs;
463     }
464
465     private static final Collection TOPICS =
466             CollectionUtil.list(Report.types, Report.context);
467
468 }
469
Popular Tags