1   // Copyright 2012- Bill Campbell, Swami Iyer and Bahar Akbal-Delibas
2   
3   package jminusminus;
4   
5   import static jminusminus.CLConstants.*;
6   
7   /**
8    * This abstract base class is the AST node for an unary expression --- an expression with a
9    * single operand.
10   */
11  abstract class JUnaryExpression extends JExpression {
12      /**
13       * The unary operator.
14       */
15      protected String operator;
16  
17      /**
18       * The operand.
19       */
20      protected JExpression operand;
21  
22      /**
23       * Constructs an AST node for an unary expression.
24       *
25       * @param line     line in which the unary expression occurs in the source file.
26       * @param operator the unary operator.
27       * @param operand  the operand.
28       */
29      protected JUnaryExpression(int line, String operator, JExpression operand) {
30          super(line);
31          this.operator = operator;
32          this.operand = operand;
33      }
34  
35      /**
36       * {@inheritDoc}
37       */
38      public void toJSON(JSONElement json) {
39          JSONElement e = new JSONElement();
40          json.addChild("JUnaryExpression:" + line, e);
41          e.addAttribute("operator", operator);
42          e.addAttribute("type", type == null ? "" : type.toString());
43          JSONElement e1 = new JSONElement();
44          e.addChild("Operand", e1);
45          operand.toJSON(e1);
46      }
47  }
48  
49  /**
50   * The AST node for a logical NOT (!) expression.
51   */
52  class JLogicalNotOp extends JUnaryExpression {
53      /**
54       * Constructs an AST for a logical NOT expression.
55       *
56       * @param line line in which the logical NOT expression occurs in the source file.
57       * @param arg  the operand.
58       */
59      public JLogicalNotOp(int line, JExpression arg) {
60          super(line, "!", arg);
61      }
62  
63      /**
64       * {@inheritDoc}
65       */
66      public JExpression analyze(Context context) {
67          operand = (JExpression) operand.analyze(context);
68          operand.type().mustMatchExpected(line(), Type.BOOLEAN);
69          type = Type.BOOLEAN;
70          return this;
71      }
72  
73      /**
74       * {@inheritDoc}
75       */
76      public void codegen(CLEmitter output) {
77          String falseLabel = output.createLabel();
78          String trueLabel = output.createLabel();
79          this.codegen(output, falseLabel, false);
80          output.addNoArgInstruction(ICONST_1); // true
81          output.addBranchInstruction(GOTO, trueLabel);
82          output.addLabel(falseLabel);
83          output.addNoArgInstruction(ICONST_0); // false
84          output.addLabel(trueLabel);
85      }
86  
87      /**
88       * {@inheritDoc}
89       */
90      public void codegen(CLEmitter output, String targetLabel, boolean onTrue) {
91          operand.codegen(output, targetLabel, !onTrue);
92      }
93  }
94  
95  /**
96   * The AST node for a unary negation (-) expression.
97   */
98  class JNegateOp extends JUnaryExpression {
99      /**
100      * Constructs an AST node for a negation expression.
101      *
102      * @param line    line in which the negation expression occurs in the source file.
103      * @param operand the operand.
104      */
105     public JNegateOp(int line, JExpression operand) {
106         super(line, "-", operand);
107     }
108 
109     /**
110      * {@inheritDoc}
111      */
112     public JExpression analyze(Context context) {
113         operand = operand.analyze(context);
114         operand.type().mustMatchExpected(line(), Type.INT);
115         type = Type.INT;
116         return this;
117     }
118 
119     /**
120      * {@inheritDoc}
121      */
122     public void codegen(CLEmitter output) {
123         operand.codegen(output);
124         output.addNoArgInstruction(INEG);
125     }
126 }
127 
128 /**
129  * The AST node for a post-decrement (--) expression.
130  */
131 class JPostDecrementOp extends JUnaryExpression {
132     /**
133      * Constructs an AST node for a post-decrement expression.
134      *
135      * @param line    line in which the expression occurs in the source file.
136      * @param operand the operand.
137      */
138     public JPostDecrementOp(int line, JExpression operand) {
139         super(line, "-- (post)", operand);
140     }
141 
142     /**
143      * {@inheritDoc}
144      */
145     public JExpression analyze(Context context) {
146         if (!(operand instanceof JLhs)) {
147             JAST.compilationUnit.reportSemanticError(line, "Operand to -- must have an LValue.");
148             type = Type.ANY;
149         } else {
150             operand = (JExpression) operand.analyze(context);
151             operand.type().mustMatchExpected(line(), Type.INT);
152             type = Type.INT;
153         }
154         return this;
155     }
156 
157     /**
158      * {@inheritDoc}
159      */
160     public void codegen(CLEmitter output) {
161         if (operand instanceof JVariable) {
162             // A local variable; otherwise analyze() would have replaced it with an explicit
163             // field selection.
164             int offset = ((LocalVariableDefn) ((JVariable) operand).iDefn()).offset();
165             if (!isStatementExpression) {
166                 // Loading its original rvalue.
167                 operand.codegen(output);
168             }
169             output.addIINCInstruction(offset, -1);
170         } else {
171             ((JLhs) operand).codegenLoadLhsLvalue(output);
172             ((JLhs) operand).codegenLoadLhsRvalue(output);
173             if (!isStatementExpression) {
174                 // Loading its original rvalue.
175                 ((JLhs) operand).codegenDuplicateRvalue(output);
176             }
177             output.addNoArgInstruction(ICONST_1);
178             output.addNoArgInstruction(ISUB);
179             ((JLhs) operand).codegenStore(output);
180         }
181     }
182 }
183 
184 /**
185  * The AST node for pre-increment (++) expression.
186  */
187 class JPreIncrementOp extends JUnaryExpression {
188     /**
189      * Constructs an AST node for a pre-increment expression.
190      *
191      * @param line    line in which the expression occurs in the source file.
192      * @param operand the operand.
193      */
194     public JPreIncrementOp(int line, JExpression operand) {
195         super(line, "++ (pre)", operand);
196     }
197 
198     /**
199      * {@inheritDoc}
200      */
201     public JExpression analyze(Context context) {
202         if (!(operand instanceof JLhs)) {
203             JAST.compilationUnit.reportSemanticError(line, "Operand to ++ must have an LValue.");
204             type = Type.ANY;
205         } else {
206             operand = (JExpression) operand.analyze(context);
207             operand.type().mustMatchExpected(line(), Type.INT);
208             type = Type.INT;
209         }
210         return this;
211     }
212 
213     /**
214      * {@inheritDoc}
215      */
216     public void codegen(CLEmitter output) {
217         if (operand instanceof JVariable) {
218             // A local variable; otherwise analyze() would have replaced it with an explicit
219             // field selection.
220             int offset = ((LocalVariableDefn) ((JVariable) operand).iDefn()).offset();
221             output.addIINCInstruction(offset, 1);
222             if (!isStatementExpression) {
223                 // Loading its original rvalue.
224                 operand.codegen(output);
225             }
226         } else {
227             ((JLhs) operand).codegenLoadLhsLvalue(output);
228             ((JLhs) operand).codegenLoadLhsRvalue(output);
229             output.addNoArgInstruction(ICONST_1);
230             output.addNoArgInstruction(IADD);
231             if (!isStatementExpression) {
232                 // Loading its original rvalue.
233                 ((JLhs) operand).codegenDuplicateRvalue(output);
234             }
235             ((JLhs) operand).codegenStore(output);
236         }
237     }
238 }
239 
240 /**
241  * The AST node for a unary plus (+) expression.
242  */
243 class JUnaryPlusOp extends JUnaryExpression {
244     /**
245      * Constructs an AST node for a unary plus expression.
246      *
247      * @param line    line in which the unary plus expression occurs in the source file.
248      * @param operand the operand.
249      */
250     public JUnaryPlusOp(int line, JExpression operand) {
251         super(line, "+", operand);
252     }
253 
254     /**
255      * {@inheritDoc}
256      */
257     public JExpression analyze(Context context) {
258         // TODO
259         return this;
260     }
261 
262     /**
263      * {@inheritDoc}
264      */
265     public void codegen(CLEmitter output) {
266         // TODO
267     }
268 }
269 
270 /**
271  * The AST node for a unary complement (~) expression.
272  */
273 class JComplementOp extends JUnaryExpression {
274     /**
275      * Constructs an AST node for a unary complement expression.
276      *
277      * @param line    line in which the unary complement expression occurs in the source file.
278      * @param operand the operand.
279      */
280     public JComplementOp(int line, JExpression operand) {
281         super(line, "~", operand);
282     }
283 
284     /**
285      * {@inheritDoc}
286      */
287     public JExpression analyze(Context context) {
288         // TODO
289         return this;
290     }
291 
292     /**
293      * {@inheritDoc}
294      */
295     public void codegen(CLEmitter output) {
296         // TODO
297     }
298 }
299 
300 /**
301  * The AST node for post-increment (++) expression.
302  */
303 class JPostIncrementOp extends JUnaryExpression {
304     /**
305      * Constructs an AST node for a post-increment expression.
306      *
307      * @param line    line in which the expression occurs in the source file.
308      * @param operand the operand.
309      */
310     public JPostIncrementOp(int line, JExpression operand) {
311         super(line, "++ (post)", operand);
312     }
313 
314     /**
315      * {@inheritDoc}
316      */
317     public JExpression analyze(Context context) {
318         // TODO
319         return this;
320     }
321 
322     /**
323      * {@inheritDoc}
324      */
325     public void codegen(CLEmitter output) {
326         // TODO
327     }
328 }
329 
330 /**
331  * The AST node for a pre-decrement (--) expression.
332  */
333 class JPreDecrementOp extends JUnaryExpression {
334     /**
335      * Constructs an AST node for a pre-decrement expression.
336      *
337      * @param line    line in which the expression occurs in the source file.
338      * @param operand the operand.
339      */
340     public JPreDecrementOp(int line, JExpression operand) {
341         super(line, "-- (pre)", operand);
342     }
343 
344     /**
345      * {@inheritDoc}
346      */
347     public JExpression analyze(Context context) {
348         // TODO
349         return this;
350     }
351 
352     /**
353      * {@inheritDoc}
354      */
355     public void codegen(CLEmitter output) {
356         // TODO
357     }
358 }