1   // Copyright 2012- Bill Campbell, Swami Iyer and Bahar Akbal-Delibas
2   
3   package jminusminus;
4   
5   import java.util.ArrayList;
6   
7   import static jminusminus.CLConstants.*;
8   
9   /**
10   * The AST node for a new expression. It keeps track of the constructor representing the
11   * expression, its arguments and their types.
12   */
13  class JNewOp extends JExpression {
14      // The constructor representing this "new" expression.
15      private Constructor constructor;
16  
17      // The arguments to the constructor.
18      private ArrayList<JExpression> arguments;
19  
20      // Types of the arguments.
21      private Type[] argTypes;
22  
23      /**
24       * Constructs an AST node for a new expression.
25       *
26       * @param line      the line in which the "new" expression occurs in the source file.
27       * @param type      the type being constructed.
28       * @param arguments arguments to the constructor.
29       */
30      public JNewOp(int line, Type type, ArrayList<JExpression> arguments) {
31          super(line);
32          super.type = type;
33          this.arguments = arguments;
34      }
35  
36      /**
37       * {@inheritDoc}
38       */
39      public JExpression analyze(Context context) {
40          // First resolve the type.
41          type = type.resolve(context);
42  
43          // Analyze the arguments, collecting their types (in Class form) as argTypes.
44          argTypes = new Type[arguments.size()];
45          for (int i = 0; i < arguments.size(); i++) {
46              arguments.set(i, (JExpression) arguments.get(i).analyze(context));
47              argTypes[i] = arguments.get(i).type();
48          }
49  
50          // Can't instantiate an abstract type.
51          if (type.isAbstract()) {
52              JAST.compilationUnit.reportSemanticError(line(),
53                      "Cannot instantiate an abstract type: " + type.toString());
54          }
55  
56          // Then get the proper constructor, given the arguments.
57          constructor = type.constructorFor(argTypes);
58  
59          if (constructor == null) {
60              JAST.compilationUnit.reportSemanticError(line(),
61                      "Cannot find constructor: " + Type.signatureFor(type.toString(), argTypes));
62          }
63          return this;
64      }
65  
66      /**
67       * {@inheritDoc}
68       */
69      public void codegen(CLEmitter output) {
70          output.addReferenceInstruction(NEW, type.jvmName());
71          output.addNoArgInstruction(DUP);
72          for (JExpression argument : arguments) {
73              argument.codegen(output);
74          }
75          output.addMemberAccessInstruction(INVOKESPECIAL,
76                  type.jvmName(),
77                  "<init>",
78                  constructor.toDescriptor());
79      }
80  
81      /**
82       * {@inheritDoc}
83       */
84      public void toJSON(JSONElement json) {
85          JSONElement e = new JSONElement();
86          json.addChild("JNewOp:" + line, e);
87          e.addAttribute("type", type == null ? "" : type.toString());
88          if (arguments != null) {
89              for (JExpression argument : arguments) {
90                  JSONElement e1 = new JSONElement();
91                  e.addChild("Argument", e1);
92                  argument.toJSON(e1);
93              }
94          }
95      }
96  }
97