1
3 package jminusminus;
4
5 import static jminusminus.CLConstants.*;
6
7
10 class JVariable extends JExpression implements JLhs {
11 private String name;
13
14 private IDefn iDefn;
16
17 private boolean analyzeLhs;
19
20
26 public JVariable(int line, String name) {
27 super(line);
28 this.name = name;
29 }
30
31
36 public String name() {
37 return name;
38 }
39
40
45 public IDefn iDefn() {
46 return iDefn;
47 }
48
49
52 public JExpression analyze(Context context) {
53 iDefn = context.lookup(name);
54 if (iDefn == null) {
55 Type definingType = context.definingType();
57 Field field = definingType.fieldFor(name);
58 if (field == null) {
59 type = Type.ANY;
60 JAST.compilationUnit.reportSemanticError(line, "Cannot find name: " + name);
61 } else {
62 type = field.type();
64 JExpression newTree = new JFieldSelection(line(),
65 field.isStatic() || (context.methodContext() != null &&
66 context.methodContext().isStatic()) ?
67 new JVariable(line(), definingType.toString()) : new JThis(line),
68 name);
69 return (JExpression) newTree.analyze(context);
70 }
71 } else {
72 if (!analyzeLhs && iDefn instanceof LocalVariableDefn &&
73 !((LocalVariableDefn) iDefn).isInitialized()) {
74 JAST.compilationUnit.reportSemanticError(line, "Variable " + name +
75 " might not have been initialized");
76 }
77 type = iDefn.type();
78 }
79 return this;
80 }
81
82
85 public JExpression analyzeLhs(Context context) {
86 analyzeLhs = true;
87 JExpression newTree = analyze(context);
88 if (newTree instanceof JVariable) {
89 if (iDefn != null && !(iDefn instanceof LocalVariableDefn)) {
91 JAST.compilationUnit.reportSemanticError(line(), name + " is a bad LHS to a =");
92 }
93 }
94 return newTree;
95 }
96
97
100 public void codegen(CLEmitter output) {
101 if (iDefn instanceof LocalVariableDefn) {
102 int offset = ((LocalVariableDefn) iDefn).offset();
103 if (type.isReference()) {
104 switch (offset) {
105 case 0:
106 output.addNoArgInstruction(ALOAD_0);
107 break;
108 case 1:
109 output.addNoArgInstruction(ALOAD_1);
110 break;
111 case 2:
112 output.addNoArgInstruction(ALOAD_2);
113 break;
114 case 3:
115 output.addNoArgInstruction(ALOAD_3);
116 break;
117 default:
118 output.addOneArgInstruction(ALOAD, offset);
119 break;
120 }
121 } else {
122 if (type == Type.INT || type == Type.BOOLEAN || type == Type.CHAR) {
124 switch (offset) {
125 case 0:
126 output.addNoArgInstruction(ILOAD_0);
127 break;
128 case 1:
129 output.addNoArgInstruction(ILOAD_1);
130 break;
131 case 2:
132 output.addNoArgInstruction(ILOAD_2);
133 break;
134 case 3:
135 output.addNoArgInstruction(ILOAD_3);
136 break;
137 default:
138 output.addOneArgInstruction(ILOAD, offset);
139 break;
140 }
141 }
142 }
143 }
144 }
145
146
149 public void codegen(CLEmitter output, String targetLabel, boolean onTrue) {
150 if (iDefn instanceof LocalVariableDefn) {
151 codegen(output);
152 if (onTrue) {
153 output.addBranchInstruction(IFNE, targetLabel);
154 } else {
155 output.addBranchInstruction(IFEQ, targetLabel);
156 }
157 }
158 }
159
160
163 public void codegenLoadLhsLvalue(CLEmitter output) {
164 }
166
167
170 public void codegenLoadLhsRvalue(CLEmitter output) {
171 codegen(output);
172 }
173
174
177 public void codegenDuplicateRvalue(CLEmitter output) {
178 if (iDefn instanceof LocalVariableDefn) {
179 output.addNoArgInstruction(DUP);
181 }
182 }
183
184
187 public void codegenStore(CLEmitter output) {
188 if (iDefn instanceof LocalVariableDefn) {
189 int offset = ((LocalVariableDefn) iDefn).offset();
190 if (type.isReference()) {
191 switch (offset) {
192 case 0:
193 output.addNoArgInstruction(ASTORE_0);
194 break;
195 case 1:
196 output.addNoArgInstruction(ASTORE_1);
197 break;
198 case 2:
199 output.addNoArgInstruction(ASTORE_2);
200 break;
201 case 3:
202 output.addNoArgInstruction(ASTORE_3);
203 break;
204 default:
205 output.addOneArgInstruction(ASTORE, offset);
206 break;
207 }
208 } else {
209 if (type == Type.INT || type == Type.BOOLEAN || type == Type.CHAR) {
211 switch (offset) {
212 case 0:
213 output.addNoArgInstruction(ISTORE_0);
214 break;
215 case 1:
216 output.addNoArgInstruction(ISTORE_1);
217 break;
218 case 2:
219 output.addNoArgInstruction(ISTORE_2);
220 break;
221 case 3:
222 output.addNoArgInstruction(ISTORE_3);
223 break;
224 default:
225 output.addOneArgInstruction(ISTORE, offset);
226 break;
227 }
228 }
229 }
230 }
231 }
232
233
236 public void toJSON(JSONElement json) {
237 JSONElement e = new JSONElement();
238 json.addChild("JVariable:" + line, e);
239 e.addAttribute("name", name());
240 }
241 }
242