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 an array initializer. Basically a list of initializing
10   * expressions.
11   */
12  
13  class JArrayInitializer extends JExpression {
14  
15      /** The initializations. */
16      private ArrayList<JExpression> initials;
17  
18      /**
19       * Construct an AST node for an array initializer given the (expected) array
20       * type and initial values.
21       * 
22       * @param line
23       *            line in which this array initializer occurs in the source
24       *            file.
25       * @param expected
26       *            the type of the array we're initializing.
27       * @param initials
28       *            initializations.
29       */
30  
31      public JArrayInitializer(int line, Type expected,
32              ArrayList<JExpression> initials) {
33          super(line);
34          type = expected;
35          this.initials = initials;
36      }
37  
38      /**
39       * Analysis of array initializer involves making sure that that the type of
40       * the initials is the same as the component type.
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 = type.resolve(context);
49          if (!type.isArray()) {
50              JAST.compilationUnit.reportSemanticError(line,
51                      "Cannot initialize a " + type.toString()
52                              + " with an array sequence {...}");
53              return this; // un-analyzed
54          }
55          Type componentType = type.componentType();
56          for (int i = 0; i < initials.size(); i++) {
57              JExpression component = initials.get(i);
58              initials.set(i, component = component.analyze(context));
59              if (!(component instanceof JArrayInitializer)) {
60                  component.type().mustMatchExpected(line, componentType);
61              }
62          }
63          return this;
64      }
65  
66      /**
67       * Perform code generation necessary to construct the initializing array and
68       * leave it on top of the stack.
69       * 
70       * @param output
71       *            the code emitter (basically an abstraction for producing the
72       *            .class file).
73       */
74  
75      public void codegen(CLEmitter output) {
76          Type componentType = type.componentType();
77  
78          // Code to push array length.
79          new JLiteralInt(line, String.valueOf(initials.size())).codegen(output);
80  
81          // Code to create the (empty) array
82          output.addArrayInstruction(componentType.isReference() ? ANEWARRAY
83                  : NEWARRAY, componentType.jvmName());
84  
85          // Code to load initial values and store them as
86          // elements in the newly created array.
87          for (int i = 0; i < initials.size(); i++) {
88              JExpression initExpr = initials.get(i);
89  
90              // Duplicate the array for each element store
91              output.addNoArgInstruction(DUP);
92  
93              // Code to push index for store
94              new JLiteralInt(line, String.valueOf(i)).codegen(output);
95  
96              // Code to compute the initial value.
97              initExpr.codegen(output);
98  
99              // Code to store the initial value in the array
100             output.addNoArgInstruction(componentType.isReference() ? AASTORE
101                     : IASTORE);
102         }
103     }
104 
105     /**
106      * @inheritDoc
107      */
108 
109     public void writeToStdOut(PrettyPrinter p) {
110         p.println("<JArrayInitializer>");
111         if (initials != null) {
112             for (JAST initial : initials) {
113                 p.indentRight();
114                 initial.writeToStdOut(p);
115                 p.indentLeft();
116             }
117         }
118         p.println("</JArrayInitializer>");
119     }
120 
121 }
122