1
3 package jminusminus;
4
5 import static jminusminus.CLConstants.*;
6
7
11 abstract class JUnaryExpression extends JExpression {
12
15 protected String operator;
16
17
20 protected JExpression operand;
21
22
29 protected JUnaryExpression(int line, String operator, JExpression operand) {
30 super(line);
31 this.operator = operator;
32 this.operand = operand;
33 }
34
35
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
52 class JLogicalNotOp extends JUnaryExpression {
53
59 public JLogicalNotOp(int line, JExpression arg) {
60 super(line, "!", arg);
61 }
62
63
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
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); output.addBranchInstruction(GOTO, trueLabel);
82 output.addLabel(falseLabel);
83 output.addNoArgInstruction(ICONST_0); output.addLabel(trueLabel);
85 }
86
87
90 public void codegen(CLEmitter output, String targetLabel, boolean onTrue) {
91 operand.codegen(output, targetLabel, !onTrue);
92 }
93 }
94
95
98 class JNegateOp extends JUnaryExpression {
99
105 public JNegateOp(int line, JExpression operand) {
106 super(line, "-", operand);
107 }
108
109
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
122 public void codegen(CLEmitter output) {
123 operand.codegen(output);
124 output.addNoArgInstruction(INEG);
125 }
126 }
127
128
131 class JPostDecrementOp extends JUnaryExpression {
132
138 public JPostDecrementOp(int line, JExpression operand) {
139 super(line, "-- (post)", operand);
140 }
141
142
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
160 public void codegen(CLEmitter output) {
161 if (operand instanceof JVariable) {
162 int offset = ((LocalVariableDefn) ((JVariable) operand).iDefn()).offset();
165 if (!isStatementExpression) {
166 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 ((JLhs) operand).codegenDuplicateRvalue(output);
176 }
177 output.addNoArgInstruction(ICONST_1);
178 output.addNoArgInstruction(ISUB);
179 ((JLhs) operand).codegenStore(output);
180 }
181 }
182 }
183
184
187 class JPreIncrementOp extends JUnaryExpression {
188
194 public JPreIncrementOp(int line, JExpression operand) {
195 super(line, "++ (pre)", operand);
196 }
197
198
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
216 public void codegen(CLEmitter output) {
217 if (operand instanceof JVariable) {
218 int offset = ((LocalVariableDefn) ((JVariable) operand).iDefn()).offset();
221 output.addIINCInstruction(offset, 1);
222 if (!isStatementExpression) {
223 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 ((JLhs) operand).codegenDuplicateRvalue(output);
234 }
235 ((JLhs) operand).codegenStore(output);
236 }
237 }
238 }
239
240
243 class JUnaryPlusOp extends JUnaryExpression {
244
250 public JUnaryPlusOp(int line, JExpression operand) {
251 super(line, "+", operand);
252 }
253
254
257 public JExpression analyze(Context context) {
258 return this;
260 }
261
262
265 public void codegen(CLEmitter output) {
266 }
268 }
269
270
273 class JComplementOp extends JUnaryExpression {
274
280 public JComplementOp(int line, JExpression operand) {
281 super(line, "~", operand);
282 }
283
284
287 public JExpression analyze(Context context) {
288 return this;
290 }
291
292
295 public void codegen(CLEmitter output) {
296 }
298 }
299
300
303 class JPostIncrementOp extends JUnaryExpression {
304
310 public JPostIncrementOp(int line, JExpression operand) {
311 super(line, "++ (post)", operand);
312 }
313
314
317 public JExpression analyze(Context context) {
318 return this;
320 }
321
322
325 public void codegen(CLEmitter output) {
326 }
328 }
329
330
333 class JPreDecrementOp extends JUnaryExpression {
334
340 public JPreDecrementOp(int line, JExpression operand) {
341 super(line, "-- (pre)", operand);
342 }
343
344
347 public JExpression analyze(Context context) {
348 return this;
350 }
351
352
355 public void codegen(CLEmitter output) {
356 }
358 }