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" array operation. It keeps track of its base type and
10   * a list of its dimensions.
11   */
12  
13  class JNewArrayOp extends JExpression {
14  
15      /** The base (component) type of the array. */
16      private Type typeSpec;
17  
18      /** Dimensions of the array. */
19      private ArrayList<JExpression> dimExprs;
20  
21      /**
22       * Construct an AST node for a "new" array operation.
23       * 
24       * @param line
25       *            the line in which the operation occurs in the source file.
26       * @param typeSpec
27       *            the type of the array being created.
28       * @param dimExprs
29       *            a list of dimension expressions.
30       */
31  
32      public JNewArrayOp(int line, Type typeSpec, ArrayList<JExpression> dimExprs) {
33          super(line);
34          this.typeSpec = typeSpec;
35          this.dimExprs = dimExprs;
36      }
37  
38      /**
39       * Analysis of a new array operation involves resolving its type and
40       * analyzing the array bounds and checking their types.
41       * 
42       * @param context
43       *            context in which names are resolved.
44       * @return the analyzed (and possibly rewritten) AST subtree.
45       */
46  
47      public JExpression analyze(Context context) {
48          type = typeSpec.resolve(context);
49          for (int i = 0; i < dimExprs.size(); i++) {
50              dimExprs.set(i, dimExprs.get(i).analyze(context));
51              dimExprs.get(i).type().mustMatchExpected(line, Type.INT);
52          }
53          return this;
54      }
55  
56      /**
57       * Generate code to push the bounds on the stack and then generate the
58       * appropriate array creation instruction.
59       * 
60       * @param output
61       *            the code emitter (basically an abstraction for producing the
62       *            .class file).
63       */
64  
65      public void codegen(CLEmitter output) {
66          // Code to push diemension exprs on to the stack
67          for (JExpression dimExpr : dimExprs) {
68              dimExpr.codegen(output);
69          }
70  
71          // Generate the appropriate array creation instruction
72          if (dimExprs.size() == 1) {
73              output.addArrayInstruction(
74                      type.componentType().isReference() ? ANEWARRAY : NEWARRAY,
75                      type.componentType().jvmName());
76          } else {
77              output.addMULTIANEWARRAYInstruction(type.toDescriptor(), dimExprs
78                      .size());
79          }
80      }
81  
82      /**
83       * @inheritDoc
84       */
85  
86      public void writeToStdOut(PrettyPrinter p) {
87          p.printf("<JNewArrayOp line=\"%d\" type=\"%s\"/>\n", line(),
88                  ((type == null) ? "" : type.toString()));
89          p.indentRight();
90          p.println("<Dimensions>");
91          if (dimExprs != null) {
92              p.indentRight();
93              for (JExpression dimExpr : dimExprs) {
94                  p.println("<Dimension>");
95                  p.indentRight();
96                  dimExpr.writeToStdOut(p);
97                  p.indentLeft();
98                  p.println("</Dimension>");
99              }
100             p.indentLeft();
101         }
102         p.println("</Dimensions>");
103         p.indentLeft();
104         p.println("</JNewArrayOp>");
105     }
106 
107 }
108