KickJava   Java API By Example, From Geeks To Geeks.

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


1 package polyglot.ext.jl.ast;
2
3 import java.util.*;
4
5 import polyglot.ast.*;
6 import polyglot.frontend.Pass;
7 import polyglot.frontend.Job;
8 import polyglot.types.*;
9 import polyglot.util.*;
10 import polyglot.visit.*;
11
12 /**
13  * A <code>New</code> is an immutable representation of the use of the
14  * <code>new</code> operator to create a new instance of a class. In
15  * addition to the type of the class being created, a <code>New</code> has a
16  * list of arguments to be passed to the constructor of the object and an
17  * optional <code>ClassBody</code> used to support anonymous classes.
18  */

19 public class New_c extends Expr_c implements New
20 {
21     protected Expr qualifier;
22     protected TypeNode tn;
23     protected List arguments;
24     protected ClassBody body;
25     protected ConstructorInstance ci;
26     protected ParsedClassType anonType;
27
28     public New_c(Position pos, Expr qualifier, TypeNode tn, List arguments, ClassBody body) {
29     super(pos);
30         this.qualifier = qualifier;
31         this.tn = tn;
32     this.arguments = TypedList.copyAndCheck(arguments, Expr.class, true);
33     this.body = body;
34     }
35
36     /** Get the qualifier expression of the allocation. */
37     public Expr qualifier() {
38         return this.qualifier;
39     }
40
41     /** Set the qualifier expression of the allocation. */
42     public New qualifier(Expr qualifier) {
43         New_c n = (New_c) copy();
44         n.qualifier = qualifier;
45         return n;
46     }
47
48     /** Get the type we are instantiating. */
49     public TypeNode objectType() {
50         return this.tn;
51     }
52
53     /** Set the type we are instantiating. */
54     public New objectType(TypeNode tn) {
55         New_c n = (New_c) copy();
56     n.tn = tn;
57     return n;
58     }
59
60     public ParsedClassType anonType() {
61     return this.anonType;
62     }
63
64     public New anonType(ParsedClassType anonType) {
65     New_c n = (New_c) copy();
66     n.anonType = anonType;
67     return n;
68     }
69
70     public ProcedureInstance procedureInstance() {
71     return constructorInstance();
72     }
73
74     public ConstructorInstance constructorInstance() {
75     return this.ci;
76     }
77
78     public New constructorInstance(ConstructorInstance ci) {
79     New_c n = (New_c) copy();
80     n.ci = ci;
81     return n;
82     }
83
84     public List arguments() {
85     return this.arguments;
86     }
87
88     public ProcedureCall arguments(List arguments) {
89     New_c n = (New_c) copy();
90     n.arguments = TypedList.copyAndCheck(arguments, Expr.class, true);
91     return n;
92     }
93
94     public ClassBody body() {
95     return this.body;
96     }
97
98     public New body(ClassBody body) {
99     New_c n = (New_c) copy();
100     n.body = body;
101     return n;
102     }
103
104     /** Reconstruct the expression. */
105     protected New_c reconstruct(Expr qualifier, TypeNode tn, List arguments, ClassBody body) {
106     if (qualifier != this.qualifier || tn != this.tn || ! CollectionUtil.equals(arguments, this.arguments) || body != this.body) {
107         New_c n = (New_c) copy();
108         n.tn = tn;
109         n.qualifier = qualifier;
110         n.arguments = TypedList.copyAndCheck(arguments, Expr.class, true);
111         n.body = body;
112         return n;
113     }
114
115     return this;
116     }
117
118     /** Visit the children of the expression. */
119     public Node visitChildren(NodeVisitor v) {
120     Expr qualifier = (Expr) visitChild(this.qualifier, v);
121     TypeNode tn = (TypeNode) visitChild(this.tn, v);
122     List arguments = visitList(this.arguments, v);
123     ClassBody body = (ClassBody) visitChild(this.body, v);
124     return reconstruct(qualifier, tn, arguments, body);
125     }
126
127     public Context enterScope(Node child, Context c) {
128         if (child == body && anonType != null && body != null) {
129             c = c.pushClass(anonType, anonType);
130         }
131         return super.enterScope(child, c);
132     }
133
134     public NodeVisitor buildTypesEnter(TypeBuilder tb) throws SemanticException {
135         if (body != null) {
136             // bybass the visiting of the body of the anonymous class. We'll
137
// get around to visiting it in the buildTypes method.
138
// We do this because we need to visit the body of the anonymous
139
// class after we've pushed an anon class onto the type builder,
140
// but we need to check the arguments, and qualifier, etc. outside
141
// of the scope of the anon class.
142
return tb.bypass(body);
143         }
144         
145
146         return tb;
147     }
148
149     public Node buildTypes(TypeBuilder tb) throws SemanticException {
150         New_c n = this;
151         
152         if (n.body() != null) {
153             // let's get a type builder that is prepared to visit the
154
// body; tb wants to bypass it, due to the builtTypesEnter method.
155
TypeBuilder bodyTB = (TypeBuilder)tb.visitChildren();
156             
157             // push an anonymous class on the stack.
158
bodyTB = bodyTB.pushAnonClass(position());
159
160             n = (New_c) n.body((ClassBody)n.body().visit(bodyTB));
161             ParsedClassType type = (ParsedClassType) bodyTB.currentClass();
162             n = (New_c) n.anonType(type);
163         }
164
165         TypeSystem ts = tb.typeSystem();
166
167         List l = new ArrayList(n.arguments.size());
168         for (int i = 0; i < n.arguments.size(); i++) {
169             l.add(ts.unknownType(position()));
170         }
171
172         ConstructorInstance ci = ts.constructorInstance(position(), ts.Object(),
173                                                         Flags.NONE, l,
174                                                         Collections.EMPTY_LIST);
175         n = (New_c) n.constructorInstance(ci);
176
177         return n.type(ts.unknownType(position()));
178     }
179
180     public NodeVisitor disambiguateEnter(AmbiguityRemover ar)
181         throws SemanticException
182     {
183         // We can't disambiguate the type node if we have a qualifier. The
184
// type node represents an inner class of the qualifier, and we don't
185
// know which outer class to look in until the qualifier is type
186
// checked.
187
if (qualifier != null) {
188             ar = (AmbiguityRemover) ar.bypass(tn);
189         }
190
191         if (body != null) {
192             ar = (AmbiguityRemover) ar.bypass(body);
193         }
194
195         return ar;
196     }
197
198     public Node disambiguate(AmbiguityRemover ar) throws SemanticException {
199         if (ar.kind() != AmbiguityRemover.ALL) {
200             return this;
201         }
202
203         if (qualifier == null) {
204             ClassType ct = tn.type().toClass();
205
206             if (! ct.isMember() || ct.flags().isStatic()) {
207                 return this;
208             }
209
210             // If we're instantiating a non-static member class, add a "this"
211
// qualifier.
212
NodeFactory nf = ar.nodeFactory();
213             TypeSystem ts = ar.typeSystem();
214             Context c = ar.context();
215
216             // Search for the outer class of the member. The outer class is
217
// not just ct.outer(); it may be a subclass of ct.outer().
218
Type outer = null;
219
220             String JavaDoc name = ct.name();
221             ClassType t = c.currentClass();
222
223             // We're in one scope too many.
224
if (t == anonType) {
225                 t = t.outer();
226             }
227
228             while (t != null) {
229                 try {
230                     // HACK: PolyJ outer() doesn't work
231
t = ts.staticTarget(t).toClass();
232                     ClassType mt = ts.findMemberClass(t, name, c.currentClass());
233
234                     if (ts.equals(mt, ct)) {
235                         outer = t;
236                         break;
237                     }
238                 }
239                 catch (SemanticException e) {
240                 }
241
242                 t = t.outer();
243             }
244
245             if (outer == null) {
246                 throw new SemanticException("Could not find non-static member class \"" +
247                                             name + "\".", position());
248             }
249
250             // Create the qualifier.
251
Expr q;
252
253             if (outer.equals(c.currentClass())) {
254                 q = nf.This(position());
255             }
256             else {
257                 q = nf.This(position(),
258                             nf.CanonicalTypeNode(position(),
259                                                  outer));
260             }
261
262             return qualifier(q);
263         }
264
265         return this;
266     }
267
268     public NodeVisitor typeCheckEnter(TypeChecker tc) throws SemanticException {
269         if (qualifier != null) {
270             tc = (TypeChecker) tc.bypass(tn);
271         }
272
273         if (body != null) {
274             tc = (TypeChecker) tc.bypass(body);
275         }
276
277         return tc;
278     }
279
280     public Node typeCheck(TypeChecker tc) throws SemanticException {
281         New_c n = this;
282
283         if (qualifier != null) {
284             // We have not disambiguated the type node yet.
285

286             // Get the qualifier type first.
287
Type qt = qualifier.type();
288
289             if (! qt.isClass()) {
290                 throw new SemanticException(
291                     "Cannot instantiate member class of a non-class type.",
292                     qualifier.position());
293             }
294
295             // Disambiguate the type node as a member of the qualifier type.
296
TypeNode tn = disambiguateTypeNode(tc, qt.toClass());
297             ClassType ct = tn.type().toClass();
298
299             /*
300 FIXME: check super types as well.
301             if (! ct.isMember() || ! ts.isEnclosed(ct, qt.toClass())) {
302                 throw new SemanticException("Class \"" + qt +
303                     "\" does not enclose \"" + ct + "\".",
304                     qualifier.position());
305             }
306             */

307
308             // According to JLS2 15.9.1, the class type being
309
// instantiated must be inner.
310
if (! ct.isInnerClass()) {
311                 throw new SemanticException(
312                     "Cannot provide a containing instance for non-inner class " +
313             ct.fullName() + ".", qualifier.position());
314             }
315
316             n = (New_c) n.objectType(tn);
317         }
318         else {
319             ClassType ct = tn.type().toClass();
320
321             if (ct.isMember()) {
322                 for (ClassType t = ct; t.isMember(); t = t.outer()) {
323                     if (! t.flags().isStatic()) {
324                         throw new SemanticException(
325                             "Cannot allocate non-static member class \"" +
326                             t + "\".", position());
327                     }
328                 }
329             }
330         }
331
332         return n.typeCheckEpilogue(tc);
333     }
334
335     protected Node typeCheckEpilogue(TypeChecker tc) throws SemanticException {
336         TypeSystem ts = tc.typeSystem();
337
338     List argTypes = new ArrayList(arguments.size());
339
340     for (Iterator i = this.arguments.iterator(); i.hasNext(); ) {
341         Expr e = (Expr) i.next();
342         argTypes.add(e.type());
343     }
344
345         ClassType ct = tn.type().toClass();
346
347     if (this.body == null) {
348         if (ct.flags().isInterface()) {
349         throw new SemanticException(
350             "Cannot instantiate an interface.", position());
351         }
352
353         if (ct.flags().isAbstract()) {
354         throw new SemanticException(
355             "Cannot instantiate an abstract class.", position());
356         }
357     }
358     else {
359         if (ct.flags().isFinal()) {
360         throw new SemanticException(
361             "Cannot create an anonymous subclass of a final class.",
362                     position());
363             }
364
365         if (ct.flags().isInterface() && ! arguments.isEmpty()) {
366             throw new SemanticException(
367             "Cannot pass arguments to an anonymous class that " +
368             "implements an interface.",
369             ((Expr) arguments.get(0)).position());
370         }
371     }
372
373
374         if (! ct.flags().isInterface()) {
375             Context c = tc.context();
376             if (body != null) {
377                 // Enter the body of this class so we can access protected
378
// super-constructors.
379

380                 // temporarily set the super type; we'll set it correctly below
381
anonType.superType(ct);
382
383                 c = c.pushClass(anonType, anonType);
384             }
385             ci = ts.findConstructor(ct, argTypes, c.currentClass());
386         }
387         else {
388             ci = ts.defaultConstructor(position(), ct);
389         }
390
391     New_c n = (New_c) this.constructorInstance(ci).type(ct);
392
393     if (n.body == null) {
394         return n;
395     }
396
397     // Now, need to read symbols, clean, disambiguate, and type check
398
// the body.
399

400     if (! ct.flags().isInterface()) {
401         anonType.superType(ct);
402     }
403     else {
404         anonType.superType(ts.Object());
405         anonType.addInterface(ct);
406     }
407
408         // The type of the new expression is actually the anon type.
409
n = (New_c)n.type(anonType);
410         
411     // Now, run the four passes on the body.
412
ClassBody body = n.typeCheckBody(tc, ct);
413
414     return n.body(body);
415     }
416
417     protected TypeNode partialDisambTypeNode(TypeNode tn, TypeChecker tc, ClassType outer) throws SemanticException
418     {
419         // We have to disambiguate the type node as if it were a member of the
420
// outer class. For Java this is simple: outer is just a name and we
421
// use that name to lookup a member of the outer class. For some
422
// extensions (e.g., PolyJ), the type node may be more complex than
423
// just a name. We'll just punt here and let the extensions handle
424
// this complexity.
425

426         if (tn instanceof CanonicalTypeNode) {
427             return tn;
428         }
429
430         String JavaDoc name = null;
431
432         if (tn instanceof AmbTypeNode && ((AmbTypeNode) tn).qual() == null) {
433             name = ((AmbTypeNode) tn).name();
434         }
435         else {
436             throw new SemanticException(
437                 "Cannot instantiate an member class.",
438                 tn.position());
439         }
440
441         TypeSystem ts = tc.typeSystem();
442         NodeFactory nf = tc.nodeFactory();
443         Context c = tc.context();
444
445         ClassType ct = ts.findMemberClass(outer, name, c.currentClass());
446         return nf.CanonicalTypeNode(tn.position(), ct);
447     }
448
449     protected TypeNode disambiguateTypeNode(TypeChecker tc, ClassType ct)
450         throws SemanticException
451     {
452         TypeNode tn = this.partialDisambTypeNode(this.tn, tc, ct);
453
454         if (tn instanceof CanonicalTypeNode) {
455             return tn;
456         }
457
458         // Run the disambiguation passes on the node.
459
Job sj = tc.job().spawn(tc.context(), tn,
460                                 Pass.CLEAN_SUPER, Pass.DISAM_ALL);
461
462         if (! sj.status()) {
463             if (! sj.reportedErrors()) {
464                 throw new SemanticException("Could not disambiguate type.",
465                                             this.tn.position());
466             }
467             throw new SemanticException();
468         }
469
470         tn = (TypeNode) sj.ast();
471
472         // Now, type-check the type node.
473
return (TypeNode) visitChild(tn, tc);
474     }
475
476     protected ClassBody typeCheckBody(TypeChecker tc, ClassType superType)
477         throws SemanticException
478     {
479         Context bodyCtxt = tc.context().pushClass(anonType, anonType);
480         Job sj = tc.job().spawn(bodyCtxt, body,
481                                 Pass.CLEAN_SUPER, Pass.DISAM_ALL);
482
483         if (! sj.status()) {
484             if (! sj.reportedErrors()) {
485                 throw new SemanticException("Could not disambiguate body of " +
486                                             "anonymous " +
487                                             (superType.flags().isInterface() ?
488                                              "implementor" : "subclass") +
489                                             " of \"" + superType + "\".");
490             }
491             throw new SemanticException();
492         }
493
494         ClassBody b = (ClassBody) sj.ast();
495
496         // Now, type-check the body.
497
TypeChecker bodyTC = (TypeChecker)tc.context(bodyCtxt);
498         b = (ClassBody) visitChild(b, bodyTC.visitChildren());
499
500         // check the class implements all abstract methods that it needs to.
501
bodyTC.typeSystem().checkClassConformance(anonType());
502
503         return b;
504     }
505
506     public Type childExpectedType(Expr child, AscriptionVisitor av) {
507         if (child == qualifier) {
508             ReferenceType t = ci.container();
509                      
510             if (t.isClass() && t.toClass().isMember()) {
511                 t = t.toClass().container();
512                 return t;
513             }
514
515             return child.type();
516         }
517
518         Iterator i = this.arguments.iterator();
519         Iterator j = ci.formalTypes().iterator();
520
521         while (i.hasNext() && j.hasNext()) {
522         Expr e = (Expr) i.next();
523         Type t = (Type) j.next();
524
525             if (e == child) {
526                 return t;
527             }
528         }
529
530         return child.type();
531     }
532
533     public Node exceptionCheck(ExceptionChecker ec) throws SemanticException {
534     // something didn't work in the type check phase, so just ignore it.
535
if (ci == null) {
536         throw new InternalCompilerError(position(),
537         "Null constructor instance after type check.");
538     }
539
540     for (Iterator i = ci.throwTypes().iterator(); i.hasNext(); ) {
541         Type t = (Type) i.next();
542         ec.throwsException(t, position());
543     }
544
545     return super.exceptionCheck(ec);
546     }
547
548     /** Get the precedence of the expression. */
549     public Precedence precedence() {
550         return Precedence.LITERAL;
551     }
552
553     public String JavaDoc toString() {
554     return (qualifier != null ? (qualifier.toString() + ".") : "") +
555             "new " + tn + "(...)" + (body != null ? " " + body : "");
556     }
557
558     protected void printQualifier(CodeWriter w, PrettyPrinter tr) {
559         if (qualifier != null) {
560             print(qualifier, w, tr);
561             w.write(".");
562         }
563     }
564
565     protected void printArgs(CodeWriter w, PrettyPrinter tr) {
566     w.write("(");
567     w.begin(0);
568
569     for (Iterator i = arguments.iterator(); i.hasNext();) {
570         Expr e = (Expr) i.next();
571
572         print(e, w, tr);
573
574         if (i.hasNext()) {
575         w.write(",");
576         w.allowBreak(0);
577         }
578     }
579
580     w.end();
581     w.write(")");
582     }
583
584     protected void printBody(CodeWriter w, PrettyPrinter tr) {
585     if (body != null) {
586         w.write(" {");
587         print(body, w, tr);
588             w.write("}");
589     }
590     }
591
592     public void prettyPrint(CodeWriter w, PrettyPrinter tr) {
593         printQualifier(w, tr);
594     w.write("new ");
595         print(tn, w, tr);
596         printArgs(w, tr);
597         printBody(w, tr);
598     }
599
600     public void translate(CodeWriter w, Translator tr) {
601         printQualifier(w, tr);
602
603     w.write("new ");
604
605         if (qualifier != null) {
606             ClassType ct = tn.type().toClass();
607
608             if (! ct.isMember()) {
609                 throw new InternalCompilerError("Cannot qualify a non-member " +
610                                                 "class.", position());
611             }
612
613             tr.setOuterClass(ct.outer());
614             print(tn, w, tr);
615             tr.setOuterClass(null);
616         }
617         else {
618             print(tn, w, tr);
619         }
620
621         printArgs(w, tr);
622         printBody(w, tr);
623     }
624
625     public Term entry() {
626         if (qualifier != null) return qualifier.entry();
627         Term afterArgs = this;
628         if (body() != null) {
629             afterArgs = body();
630         }
631         return listEntry(arguments, afterArgs);
632     }
633
634     public List acceptCFG(CFGBuilder v, List succs) {
635         Term afterArgs = this;
636         if (body() != null) {
637             afterArgs = body();
638         }
639
640         if (qualifier != null) {
641             v.visitCFG(qualifier, listEntry(arguments, afterArgs));
642         }
643
644         v.visitCFGList(arguments, afterArgs);
645
646         if (body() != null) {
647             v.visitCFG(body(), this);
648         }
649
650         return succs;
651     }
652
653     public List throwTypes(TypeSystem ts) {
654       List l = new LinkedList();
655       l.addAll(ci.throwTypes());
656       l.addAll(ts.uncheckedExceptions());
657       return l;
658     }
659 }
660
Popular Tags