KickJava   Java API By Example, From Geeks To Geeks.

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


1 package polyglot.ext.jl.ast;
2
3 import java.util.*;
4 import polyglot.ast.*;
5 import polyglot.types.*;
6 import polyglot.util.*;
7 import polyglot.visit.*;
8
9 /**
10  * A <code>ConstructorCall_c</code> represents a direct call to a constructor.
11  * For instance, <code>super(...)</code> or <code>this(...)</code>.
12  */

13 public class ConstructorCall_c extends Stmt_c implements ConstructorCall
14 {
15     protected Kind kind;
16     protected Expr qualifier;
17     protected List arguments;
18     protected ConstructorInstance ci;
19
20     public ConstructorCall_c(Position pos, Kind kind, Expr qualifier, List arguments) {
21     super(pos);
22     this.kind = kind;
23     this.qualifier = qualifier;
24     this.arguments = TypedList.copyAndCheck(arguments, Expr.class, true);
25     }
26
27     /** Get the qualifier of the constructor call. */
28     public Expr qualifier() {
29     return this.qualifier;
30     }
31
32     /** Set the qualifier of the constructor call. */
33     public ConstructorCall qualifier(Expr qualifier) {
34     ConstructorCall_c n = (ConstructorCall_c) copy();
35     n.qualifier = qualifier;
36     return n;
37     }
38
39     /** Get the kind of the constructor call. */
40     public Kind kind() {
41     return this.kind;
42     }
43
44     /** Set the kind of the constructor call. */
45     public ConstructorCall kind(Kind kind) {
46     ConstructorCall_c n = (ConstructorCall_c) copy();
47     n.kind = kind;
48     return n;
49     }
50
51     /** Get the actual arguments of the constructor call. */
52     public List arguments() {
53     return Collections.unmodifiableList(this.arguments);
54     }
55
56     /** Set the actual arguments of the constructor call. */
57     public ProcedureCall arguments(List arguments) {
58     ConstructorCall_c n = (ConstructorCall_c) copy();
59     n.arguments = TypedList.copyAndCheck(arguments, Expr.class, true);
60     return n;
61     }
62
63     public ProcedureInstance procedureInstance() {
64     return constructorInstance();
65     }
66
67     /** Get the constructor we are calling. */
68     public ConstructorInstance constructorInstance() {
69         return ci;
70     }
71
72     /** Set the constructor we are calling. */
73     public ConstructorCall constructorInstance(ConstructorInstance ci) {
74     ConstructorCall_c n = (ConstructorCall_c) copy();
75     n.ci = ci;
76     return n;
77     }
78
79     /**
80      * An explicit constructor call is a static context. We need to record
81      * this.
82      */

83     public Context enterScope(Context c) {
84         return c.pushStatic();
85     }
86
87     /** Reconstruct the constructor call. */
88     protected ConstructorCall_c reconstruct(Expr qualifier, List arguments) {
89     if (qualifier != this.qualifier || ! CollectionUtil.equals(arguments, this.arguments)) {
90         ConstructorCall_c n = (ConstructorCall_c) copy();
91         n.qualifier = qualifier;
92         n.arguments = TypedList.copyAndCheck(arguments, Expr.class, true);
93         return n;
94     }
95
96     return this;
97     }
98
99     /** Visit the children of the call. */
100     public Node visitChildren(NodeVisitor v) {
101     Expr qualifier = (Expr) visitChild(this.qualifier, v);
102     List arguments = visitList(this.arguments, v);
103     return reconstruct(qualifier, arguments);
104     }
105
106     public Node buildTypes(TypeBuilder tb) throws SemanticException {
107         TypeSystem ts = tb.typeSystem();
108
109         // Remove super() calls for java.lang.Object.
110
if (kind == SUPER && tb.currentClass() == ts.Object()) {
111             return tb.nodeFactory().Empty(position());
112         }
113
114         ConstructorCall_c n = (ConstructorCall_c) super.buildTypes(tb);
115
116         List l = new ArrayList(arguments.size());
117         for (int i = 0; i < arguments.size(); i++) {
118           l.add(ts.unknownType(position()));
119         }
120
121         ConstructorInstance ci = ts.constructorInstance(position(), ts.Object(),
122                                                         Flags.NONE, l,
123                                                         Collections.EMPTY_LIST);
124         return n.constructorInstance(ci);
125     }
126
127     /** Type check the call. */
128     public Node typeCheck(TypeChecker tc) throws SemanticException {
129     TypeSystem ts = tc.typeSystem();
130     Context c = tc.context();
131
132     ClassType ct = c.currentClass();
133         Type superType = ct.superType();
134
135         // The qualifier specifies the enclosing instance of this inner class.
136
// The type of the qualifier must be the outer class of this
137
// inner class or one of its super types.
138
//
139
// Example:
140
//
141
// class Outer {
142
// class Inner { }
143
// }
144
//
145
// class ChildOfInner extends Outer.Inner {
146
// ChildOfInner() { (new Outer()).super(); }
147
// }
148
if (qualifier != null) {
149             if (kind != SUPER) {
150                 throw new SemanticException("Can only qualify a \"super\"" +
151                                             "constructor invocation.",
152                                             position());
153             }
154             
155             if (!superType.isClass() || !superType.toClass().isInnerClass() ||
156                 superType.toClass().inStaticContext()) {
157                 throw new SemanticException("The class \"" + superType + "\"" +
158                     " is not an inner class, or was declared in a static " +
159                     "context; a qualified constructor invocation cannot " +
160                     "be used.", position());
161             }
162
163             Type qt = qualifier.type();
164
165             if (! qt.isClass() || !qt.isSubtype(superType.toClass().outer())) {
166                 throw new SemanticException("The type of the qualifier " +
167                     "\"" + qt + "\" does not match the immediately enclosing " +
168                     "class of the super class \"" +
169                     superType.toClass().outer() + "\".", qualifier.position());
170             }
171         }
172
173     if (kind == SUPER) {
174         if (! superType.isClass()) {
175             throw new SemanticException("Super type of " + ct +
176             " is not a class.", position());
177         }
178
179             // If the super class is an inner class (i.e., has an enclosing
180
// instance of its container class), then either a qualifier
181
// must be provided, or ct must have an enclosing instance of the
182
// super class's container class, or a subclass thereof.
183
if (qualifier == null && superType.isClass() && superType.toClass().isInnerClass()) {
184                 ClassType superContainer = superType.toClass().outer();
185                 // ct needs an enclosing instance of superContainer,
186
// or a subclass of superContainer.
187
ClassType e = ct;
188                 
189                 while (e != null) {
190                     if (e.isSubtype(superContainer) && ct.hasEnclosingInstance(e)) {
191                         break;
192                     }
193                     e = e.outer();
194                 }
195                 
196                 if (e == null) {
197                     throw new SemanticException(ct + " must have an enclosing instance" +
198                         " that is a subtype of " + superContainer, position());
199                 }
200                 if (e == ct) {
201                     throw new SemanticException(ct + " is a subtype of " + superContainer +
202                         "; an enclosing instance that is a subtype of " + superContainer +
203                         " must be specified in the super constructor call.", position());
204                 }
205             }
206
207         ct = ct.superType().toClass();
208     }
209
210     List argTypes = new LinkedList();
211
212     for (Iterator iter = this.arguments.iterator(); iter.hasNext();) {
213         Expr e = (Expr) iter.next();
214         argTypes.add(e.type());
215     }
216
217     ConstructorInstance ci = ts.findConstructor(ct, argTypes, c.currentClass());
218
219     return constructorInstance(ci);
220     }
221
222     public Type childExpectedType(Expr child, AscriptionVisitor av) {
223         TypeSystem ts = av.typeSystem();
224
225         if (child == qualifier) {
226             // FIXME: Can be more specific
227
return ts.Object();
228         }
229
230         Iterator i = this.arguments.iterator();
231         Iterator j = ci.formalTypes().iterator();
232
233         while (i.hasNext() && j.hasNext()) {
234         Expr e = (Expr) i.next();
235         Type t = (Type) j.next();
236
237             if (e == child) {
238                 return t;
239             }
240         }
241
242         return child.type();
243     }
244
245     public String JavaDoc toString() {
246     return (qualifier != null ? qualifier + "." : "") + kind + "(...)";
247     }
248
249     /** Write the call to an output file. */
250     public void prettyPrint(CodeWriter w, PrettyPrinter tr) {
251     if (qualifier != null) {
252         print(qualifier, w, tr);
253         w.write(".");
254     }
255
256     w.write(kind + "(");
257
258     w.begin(0);
259
260     for (Iterator i = arguments.iterator(); i.hasNext(); ) {
261         Expr e = (Expr) i.next();
262         print(e, w, tr);
263
264         if (i.hasNext()) {
265         w.write(",");
266         w.allowBreak(0);
267         }
268     }
269
270     w.end();
271
272     w.write(");");
273     }
274
275     public Term entry() {
276         if (qualifier != null) {
277             return qualifier.entry();
278         }
279         return listEntry(arguments, this);
280     }
281
282     public List acceptCFG(CFGBuilder v, List succs) {
283         if (qualifier != null) {
284             v.visitCFG(qualifier, listEntry(arguments, this));
285         }
286
287         v.visitCFGList(arguments, this);
288
289         return succs;
290     }
291
292     public List throwTypes(TypeSystem ts) {
293         List l = new LinkedList();
294         l.addAll(ci.throwTypes());
295         l.addAll(ts.uncheckedExceptions());
296         return l;
297     }
298 }
299
Popular Tags