1
3 package jminusminus;
4
5 import static jminusminus.CLConstants.*;
6
7
11
12 class JFieldSelection extends JExpression implements JLhs {
13
14
15 protected JExpression target;
16
17
18 private AmbiguousName ambiguousPart;
19
20
21 private String fieldName;
22
23
24 private Field field;
25
26
36
37 public JFieldSelection(int line, JExpression target, String fieldName) {
38 this(line, null, target, fieldName);
39 }
40
41
53
54 public JFieldSelection(int line, AmbiguousName ambiguousPart,
55 JExpression target, String fieldName) {
56 super(line);
57 this.ambiguousPart = ambiguousPart;
58 this.target = target;
59 this.fieldName = fieldName;
60 }
61
62
72
73 public JExpression analyze(Context context) {
74 if (ambiguousPart != null) {
76 JExpression expr = ambiguousPart.reclassify(context);
77 if (expr != null) {
78 if (target == null)
79 target = expr;
80 else {
81 JAST.compilationUnit.reportSemanticError(line(),
83 "Badly formed suffix");
84 }
85 }
86 }
87 target = (JExpression) target.analyze(context);
88 Type targetType = target.type();
89
90 if ((targetType.isArray()) && fieldName.equals("length")) {
92 type = Type.INT;
93 } else {
94 if (targetType.isPrimitive()) {
97 JAST.compilationUnit.reportSemanticError(line(),
98 "Target of a field selection must "
99 + "be a defined type");
100 type = Type.ANY;
101 return this;
102 }
103 field = targetType.fieldFor(fieldName);
104 if (field == null) {
105 JAST.compilationUnit.reportSemanticError(line(),
106 "Cannot find a field: " + fieldName);
107 type = Type.ANY;
108 } else {
109 context.definingType().checkAccess(line, (Member) field);
110 type = field.type();
111
112 if (!field.isStatic()) {
114 if (target instanceof JVariable
115 && ((JVariable) target).iDefn() instanceof TypeNameDefn) {
116 JAST.compilationUnit
117 .reportSemanticError(
118 line(),
119 "Non-static field "
120 + fieldName
121 + " cannot be referenced from a static context");
122 }
123 }
124 }
125 }
126 return this;
127 }
128
129
138
139 public JExpression analyzeLhs(Context context) {
140 JExpression result = analyze(context);
141 if (field.isFinal()) {
142 JAST.compilationUnit.reportSemanticError(line, "The field "
143 + fieldName + " in type " + target.type.toString()
144 + " is declared final.");
145 }
146 return result;
147 }
148
149
156
157 public void codegen(CLEmitter output) {
158 target.codegen(output);
159
160 if ((target.type().isArray()) && fieldName.equals("length")) {
162 output.addNoArgInstruction(ARRAYLENGTH);
163 } else {
164 int mnemonic = field.isStatic() ? GETSTATIC : GETFIELD;
165 output.addMemberAccessInstruction(mnemonic,
166 target.type().jvmName(), fieldName, type.toDescriptor());
167 }
168 }
169
170
182
183 public void codegen(CLEmitter output, String targetLabel, boolean onTrue) {
184 codegen(output);
186
187 if (onTrue) {
188 output.addBranchInstruction(IFNE, targetLabel);
190 } else {
191 output.addBranchInstruction(IFEQ, targetLabel);
193 }
194 }
195
196
204
205 public void codegenLoadLhsLvalue(CLEmitter output) {
206 if (!field.isStatic()) {
208 target.codegen(output);
210 }
211 }
212
213
221
222 public void codegenLoadLhsRvalue(CLEmitter output) {
223 String descriptor = field.type().toDescriptor();
224 if (field.isStatic()) {
225 output.addMemberAccessInstruction(GETSTATIC, target.type()
226 .jvmName(), fieldName, descriptor);
227 } else {
228 output.addNoArgInstruction(type == Type.STRING ? DUP_X1 : DUP);
229 output.addMemberAccessInstruction(GETFIELD,
230 target.type().jvmName(), fieldName, descriptor);
231 }
232 }
233
234
243
244 public void codegenDuplicateRvalue(CLEmitter output) {
245 if (field.isStatic()) {
246 output.addNoArgInstruction(DUP);
247 } else {
248 output.addNoArgInstruction(DUP_X1);
249 }
250 }
251
252
259
260 public void codegenStore(CLEmitter output) {
261 String descriptor = field.type().toDescriptor();
262 if (field.isStatic()) {
263 output.addMemberAccessInstruction(PUTSTATIC, target.type()
264 .jvmName(), fieldName, descriptor);
265 } else {
266 output.addMemberAccessInstruction(PUTFIELD,
267 target.type().jvmName(), fieldName, descriptor);
268 }
269 }
270
271
274
275 public void writeToStdOut(PrettyPrinter p) {
276 p.printf("<JFieldSelection line=\"%d\" name=\"%s\"/>\n", line(),
277 fieldName);
278 p.indentRight();
279 if (target != null) {
280 p.println("<Target>");
281 p.indentRight();
282 target.writeToStdOut(p);
283 p.indentLeft();
284 p.println("</Target>");
285 }
286 p.indentLeft();
287 p.println("</JFieldSelection>");
288 }
289
290 }
291