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 an array initializer.
11   */
12  class JArrayInitializer extends JExpression {
13      // The initializations.
14      private ArrayList<JExpression> initials;
15  
16      /**
17       * Constructs an AST node for an array initializer.
18       *
19       * @param line     line in which this array initializer occurs in the source file.
20       * @param type     the type of the array we're initializing.
21       * @param initials initializations.
22       */
23      public JArrayInitializer(int line, Type type, ArrayList<JExpression> initials) {
24          super(line);
25          this.type = type;
26          this.initials = initials;
27      }
28  
29      /**
30       * {@inheritDoc}
31       */
32      public JExpression analyze(Context context) {
33          type = type.resolve(context);
34          if (!type.isArray()) {
35              JAST.compilationUnit.reportSemanticError(line, "Cannot initialize a " + type.toString()
36                      + " with an array sequence {...}");
37              return this;
38          }
39          Type componentType = type.componentType();
40          for (int i = 0; i < initials.size(); i++) {
41              JExpression initial = initials.get(i);
42              initials.set(i, initial = initial.analyze(context));
43              if (!(initial instanceof JArrayInitializer)) {
44                  initial.type().mustMatchExpected(line, componentType);
45              }
46          }
47          return this;
48      }
49  
50      /**
51       * {@inheritDoc}
52       */
53      public void codegen(CLEmitter output) {
54          Type componentType = type.componentType();
55  
56          // Code to push array length.
57          (new JLiteralInt(line, String.valueOf(initials.size()))).codegen(output);
58  
59          // Code to create the (empty) array.
60          output.addArrayInstruction(componentType.isReference() ? ANEWARRAY : NEWARRAY,
61                  componentType.jvmName());
62  
63          // Code to load initial values and store them as elements in the newly created array.
64          for (int i = 0; i < initials.size(); i++) {
65              JExpression initial = initials.get(i);
66  
67              // Duplicate the array for each element store.
68              output.addNoArgInstruction(DUP);
69  
70              // Code to push index for store.
71              (new JLiteralInt(line, String.valueOf(i))).codegen(output);
72  
73              // Code to compute the initial value.
74              initial.codegen(output);
75  
76              // Code to store the initial value in the array.
77              if (componentType == Type.INT) {
78                  output.addNoArgInstruction(IASTORE);
79              } else if (componentType == Type.BOOLEAN) {
80                  output.addNoArgInstruction(BASTORE);
81              } else if (componentType == Type.CHAR) {
82                  output.addNoArgInstruction(CASTORE);
83              } else if (!componentType.isPrimitive()) {
84                  output.addNoArgInstruction(AASTORE);
85              }
86          }
87      }
88  
89      /**
90       * {@inheritDoc}
91       */
92      public void toJSON(JSONElement json) {
93          JSONElement e = new JSONElement();
94          json.addChild("JArrayInitializer:" + line, e);
95          if (initials != null) {
96              for (JExpression initial : initials) {
97                  initial.toJSON(e);
98              }
99          }
100     }
101 }
102