1
3 package jminusminus;
4
5 import static jminusminus.CLConstants.*;
6
7
10
11 class JVariable extends JExpression implements JLhs {
12
13
14 private String name;
15
16
17 private IDefn iDefn;
18
19
20 private boolean analyzeLhs;
21
22
30
31 public JVariable(int line, String name) {
32 super(line);
33 this.name = name;
34 }
35
36
41
42 public String name() {
43 return name;
44 }
45
46
51
52 public IDefn iDefn() {
53 return iDefn;
54 }
55
56
65
66 public JExpression analyze(Context context) {
67 iDefn = context.lookup(name);
68 if (iDefn == null) {
69 Type definingType = context.definingType();
71 Field field = definingType.fieldFor(name);
72 if (field == null) {
73 type = Type.ANY;
74 JAST.compilationUnit.reportSemanticError(line,
75 "Cannot find name: " + name);
76 } else {
77 type = field.type();
80 JExpression newTree = new JFieldSelection(line(), field
81 .isStatic()
82 || (context.methodContext() != null && context
83 .methodContext().isStatic()) ? new JVariable(
84 line(), definingType.toString()) : new JThis(line),
85 name);
86 return (JExpression) newTree.analyze(context);
87 }
88 } else {
89 if (!analyzeLhs && iDefn instanceof LocalVariableDefn
90 && !((LocalVariableDefn) iDefn).isInitialized()) {
91 JAST.compilationUnit.reportSemanticError(line, "Variable "
92 + name + " might not have been initialized");
93 }
94 type = iDefn.type();
95 }
96 return this;
97 }
98
99
106
107 public JExpression analyzeLhs(Context context) {
108 analyzeLhs = true;
109 JExpression newTree = analyze(context);
110 if (newTree instanceof JVariable) {
111 if (iDefn != null && !(iDefn instanceof LocalVariableDefn)) {
114 JAST.compilationUnit.reportSemanticError(line(), name
115 + " is a bad lhs to a =");
116 }
117 }
118 return newTree;
119 }
120
121
128
129 public void codegen(CLEmitter output) {
130 if (iDefn instanceof LocalVariableDefn) {
131 int offset = ((LocalVariableDefn) iDefn).offset();
132 if (type.isReference()) {
133 switch (offset) {
134 case 0:
135 output.addNoArgInstruction(ALOAD_0);
136 break;
137 case 1:
138 output.addNoArgInstruction(ALOAD_1);
139 break;
140 case 2:
141 output.addNoArgInstruction(ALOAD_2);
142 break;
143 case 3:
144 output.addNoArgInstruction(ALOAD_3);
145 break;
146 default:
147 output.addOneArgInstruction(ALOAD, offset);
148 break;
149 }
150 } else {
151 if (type == Type.INT || type == Type.BOOLEAN
153 || type == Type.CHAR) {
154 switch (offset) {
155 case 0:
156 output.addNoArgInstruction(ILOAD_0);
157 break;
158 case 1:
159 output.addNoArgInstruction(ILOAD_1);
160 break;
161 case 2:
162 output.addNoArgInstruction(ILOAD_2);
163 break;
164 case 3:
165 output.addNoArgInstruction(ILOAD_3);
166 break;
167 default:
168 output.addOneArgInstruction(ILOAD, offset);
169 break;
170 }
171 }
172 }
173 }
174 }
175
176
188
189 public void codegen(CLEmitter output, String targetLabel, boolean onTrue) {
190 if (iDefn instanceof LocalVariableDefn) {
191 codegen(output);
193
194 if (onTrue) {
195 output.addBranchInstruction(IFNE, targetLabel);
197 } else {
198 output.addBranchInstruction(IFEQ, targetLabel);
200 }
201 }
202 }
203
204
212
213 public void codegenLoadLhsLvalue(CLEmitter output) {
214 }
216
217
224
225 public void codegenLoadLhsRvalue(CLEmitter output) {
226 codegen(output);
227 }
228
229
239
240 public void codegenDuplicateRvalue(CLEmitter output) {
241 if (iDefn instanceof LocalVariableDefn) {
242 output.addNoArgInstruction(DUP);
244 }
245 }
246
247
255
256 public void codegenStore(CLEmitter output) {
257 if (iDefn instanceof LocalVariableDefn) {
258 int offset = ((LocalVariableDefn) iDefn).offset();
259 if (type.isReference()) {
260 switch (offset) {
261 case 0:
262 output.addNoArgInstruction(ASTORE_0);
263 break;
264 case 1:
265 output.addNoArgInstruction(ASTORE_1);
266 break;
267 case 2:
268 output.addNoArgInstruction(ASTORE_2);
269 break;
270 case 3:
271 output.addNoArgInstruction(ASTORE_3);
272 break;
273 default:
274 output.addOneArgInstruction(ASTORE, offset);
275 break;
276 }
277 } else {
278 if (type == Type.INT || type == Type.BOOLEAN
280 || type == Type.CHAR) {
281 switch (offset) {
282 case 0:
283 output.addNoArgInstruction(ISTORE_0);
284 break;
285 case 1:
286 output.addNoArgInstruction(ISTORE_1);
287 break;
288 case 2:
289 output.addNoArgInstruction(ISTORE_2);
290 break;
291 case 3:
292 output.addNoArgInstruction(ISTORE_3);
293 break;
294 default:
295 output.addOneArgInstruction(ISTORE, offset);
296 break;
297 }
298 }
299 }
300 }
301 }
302
303
306
307 public void writeToStdOut(PrettyPrinter p) {
308 p.println("<JVariable name=\"" + name + "\"/>");
309 }
310
311 }
312