1   // Copyright 2013 Bill Campbell, Swami Iyer and Bahar Akbal-Delibas
2   
3   package jminusminus;
4   
5   import java.util.ArrayList;
6   import static jminusminus.CLConstants.*;
7   
8   /**
9    * The AST node for a "new" expression. It keeps track of its type, the
10   * Constructor representing the expression, its arguments and their types.
11   */
12  
13  class JNewOp extends JExpression {
14  
15      /** The constructor representing this "new" expression. */
16      private Constructor constructor;
17  
18      /** The arguments to the constructor. */
19      private ArrayList<JExpression> arguments;
20  
21      /** Types of the arguments. */
22      private Type[] argTypes;
23  
24      /**
25       * Construct an AST node for a "new" expression.
26       * 
27       * @param line
28       *            the line in which the "new" expression occurs in the source
29       *            file.
30       * @param type
31       *            the type being constructed.
32       * @param arguments
33       *            arguments to the constructor.
34       */
35  
36      public JNewOp(int line, Type type, ArrayList<JExpression> arguments) {
37          super(line);
38          this.type = type;
39          this.arguments = arguments;
40      }
41  
42      /**
43       * To analyze the new operation, we (1) resolve the type, (2) analyze its
44       * arguments, (3) check accessibility of the type, (3) find the appropriate
45       * Constructor.
46       * 
47       * @param context
48       *            context in which names are resolved.
49       * @return the analyzed (and possibly rewritten) AST subtree.
50       */
51  
52      public JExpression analyze(Context context) {
53          // First resolve the type
54          type = type.resolve(context);
55  
56          // Analyze the arguments, collecting
57          // their types (in Class form) as argTypes.
58          argTypes = new Type[arguments.size()];
59          for (int i = 0; i < arguments.size(); i++) {
60              arguments.set(i, (JExpression) arguments.get(i).analyze(context));
61              argTypes[i] = arguments.get(i).type();
62          }
63  
64          // Can't instantiate an abstract type
65          if (type.isAbstract()) {
66              JAST.compilationUnit.reportSemanticError(line(),
67                      "Cannot instantiate an abstract type:" + type.toString());
68          }
69  
70          // Where are we now? Check accessability of type
71          // resolve() checks accessibility, so the following two
72          // is commented
73          // Type thisType = context.definingType();
74          // thisType.checkAccess( line, type );
75  
76          // Then get the proper constructor, given the arguments
77          constructor = type.constructorFor(argTypes);
78  
79          if (constructor == null) {
80              JAST.compilationUnit.reportSemanticError(line(),
81                      "Cannot find constructor: "
82                              + Type.signatureFor(type.toString(), argTypes));
83          }
84          return this;
85      }
86  
87      /**
88       * Generating code for a new operation involves generating the NEW
89       * instruction for creating the object on the stack, then gnerating the code
90       * for the actual arguments, and then code for invoking the constructor (the
91       * initialization method).
92       * 
93       * @param output
94       *            the code emitter (basically an abstraction for producing the
95       *            .class file).
96       */
97  
98      public void codegen(CLEmitter output) {
99          output.addReferenceInstruction(NEW, type.jvmName());
100         output.addNoArgInstruction(DUP);
101         for (JExpression argument : arguments) {
102             argument.codegen(output);
103         }
104         output.addMemberAccessInstruction(INVOKESPECIAL, type.jvmName(),
105                 "<init>", constructor.toDescriptor());
106     }
107 
108     /**
109      * @inheritDoc
110      */
111 
112     public void writeToStdOut(PrettyPrinter p) {
113         p.printf("<JNewOp line=\"%d\" type=\"%s\"/>\n", line(),
114                 ((type == null) ? "" : type.toString()));
115         p.indentRight();
116         if (arguments != null) {
117             p.println("<Arguments>");
118             for (JExpression argument : arguments) {
119                 p.indentRight();
120                 p.println("<Argument>");
121                 p.indentRight();
122                 argument.writeToStdOut(p);
123                 p.indentLeft();
124                 p.println("</Argument>");
125                 p.indentLeft();
126             }
127             p.println("</Arguments>");
128         }
129         p.indentLeft();
130         p.println("</JNewOp>");
131     }
132 
133 }
134