1   // Copyright 2012- Bill Campbell, Swami Iyer and Bahar Akbal-Delibas
2   
3   package jminusminus;
4   
5   import static jminusminus.CLConstants.*;
6   
7   /**
8    * The AST for an array indexing operation. It has an expression denoting an array object and an
9    * expression denoting an integer index.
10   */
11  class JArrayExpression extends JExpression implements JLhs {
12      // The array.
13      private JExpression theArray;
14  
15      // The array index expression.
16      private JExpression indexExpr;
17  
18      /**
19       * Constructs an AST node for an array indexing operation.
20       *
21       * @param line      line in which the operation occurs in the source file.
22       * @param theArray  the array we're indexing.
23       * @param indexExpr the index expression.
24       */
25      public JArrayExpression(int line, JExpression theArray, JExpression indexExpr) {
26          super(line);
27          this.theArray = theArray;
28          this.indexExpr = indexExpr;
29      }
30  
31      /**
32       * {@inheritDoc}
33       */
34      public JExpression analyze(Context context) {
35          theArray = (JExpression) theArray.analyze(context);
36          indexExpr = (JExpression) indexExpr.analyze(context);
37          if (!(theArray.type().isArray())) {
38              JAST.compilationUnit.reportSemanticError(line(), "attempt to index a non-array object");
39              this.type = Type.ANY;
40          } else {
41              this.type = theArray.type().componentType();
42          }
43          indexExpr.type().mustMatchExpected(line(), Type.INT);
44          return this;
45      }
46  
47      /**
48       * {@inheritDoc}
49       */
50      public JExpression analyzeLhs(Context context) {
51          analyze(context);
52          return this;
53      }
54  
55      /**
56       * {@inheritDoc}
57       */
58      public void codegen(CLEmitter output) {
59          theArray.codegen(output);
60          indexExpr.codegen(output);
61          if (type == Type.INT) {
62              output.addNoArgInstruction(IALOAD);
63          } else if (type == Type.BOOLEAN) {
64              output.addNoArgInstruction(BALOAD);
65          } else if (type == Type.CHAR) {
66              output.addNoArgInstruction(CALOAD);
67          } else if (!type.isPrimitive()) {
68              output.addNoArgInstruction(AALOAD);
69          }
70      }
71  
72      /**
73       * {@inheritDoc}
74       */
75      public void codegen(CLEmitter output, String targetLabel, boolean onTrue) {
76          codegen(output);
77          if (onTrue) {
78              output.addBranchInstruction(IFNE, targetLabel);
79          } else {
80              output.addBranchInstruction(IFEQ, targetLabel);
81          }
82      }
83  
84      /**
85       * {@inheritDoc}
86       */
87      public void codegenLoadLhsLvalue(CLEmitter output) {
88          theArray.codegen(output);
89          indexExpr.codegen(output);
90      }
91  
92      /**
93       * {@inheritDoc}
94       */
95      public void codegenLoadLhsRvalue(CLEmitter output) {
96          if (type == Type.STRING) {
97              output.addNoArgInstruction(DUP2_X1);
98          } else {
99              output.addNoArgInstruction(DUP2);
100         }
101         if (type == Type.INT) {
102             output.addNoArgInstruction(IALOAD);
103         } else if (type == Type.BOOLEAN) {
104             output.addNoArgInstruction(BALOAD);
105         } else if (type == Type.CHAR) {
106             output.addNoArgInstruction(CALOAD);
107         } else if (!type.isPrimitive()) {
108             output.addNoArgInstruction(AALOAD);
109         }
110     }
111 
112     /**
113      * {@inheritDoc}
114      */
115     public void codegenDuplicateRvalue(CLEmitter output) {
116         output.addNoArgInstruction(DUP_X2);
117     }
118 
119     /**
120      * {@inheritDoc}
121      */
122     public void codegenStore(CLEmitter output) {
123         if (type == Type.INT) {
124             output.addNoArgInstruction(IASTORE);
125         } else if (type == Type.BOOLEAN) {
126             output.addNoArgInstruction(BASTORE);
127         } else if (type == Type.CHAR) {
128             output.addNoArgInstruction(CASTORE);
129         } else if (!type.isPrimitive()) {
130             output.addNoArgInstruction(AASTORE);
131         }
132     }
133 
134     /**
135      * {@inheritDoc}
136      */
137     public void toJSON(JSONElement json) {
138         JSONElement e = new JSONElement();
139         json.addChild("JArrayExpression:" + line, e);
140         JSONElement e1 = new JSONElement();
141         e.addChild("TheArray", e1);
142         theArray.toJSON(e1);
143         JSONElement e2 = new JSONElement();
144         e.addChild("TheIndex", e2);
145         indexExpr.toJSON(e2);
146     }
147 }
148