1
3 package jminusminus;
4
5 import java.util.ArrayList;
6
7 import static jminusminus.CLConstants.*;
8
9
13
14 class JMessageExpression extends JExpression {
15
16
17 private JExpression target;
18
19
20 private AmbiguousName ambiguousPart;
21
22
23 private String messageName;
24
25
26 private ArrayList<JExpression> arguments;
27
28
29 private Type[] argTypes;
30
31
32 private Method method;
33
34
46
47 protected JMessageExpression(int line, JExpression target,
48 String messageName, ArrayList<JExpression> arguments) {
49 this(line, target, null, messageName, arguments);
50 }
51
52
66
67 protected JMessageExpression(int line, JExpression target,
68 AmbiguousName ambiguousPart, String messageName,
69 ArrayList<JExpression> arguments) {
70 super(line);
71 this.target = target;
72 this.ambiguousPart = ambiguousPart;
73 this.messageName = messageName;
74 this.arguments = arguments;
75 }
76
77
89
90 public JExpression analyze(Context context) {
91 if (ambiguousPart != null) {
93 JExpression expr = ambiguousPart.reclassify(context);
94 if (expr != null) {
95 if (target == null) {
96 target = expr;
97 } else {
98 JAST.compilationUnit.reportSemanticError(line(),
100 "Badly formed suffix");
101 }
102 }
103 }
104
105 argTypes = new Type[arguments.size()];
108 for (int i = 0; i < arguments.size(); i++) {
109 arguments.set(i, (JExpression) arguments.get(i).analyze(context));
110 argTypes[i] = arguments.get(i).type();
111 }
112
113 Type thisType = ((JTypeDecl) context.classContext.definition())
115 .thisType();
116
117 if (target == null) {
119 if (!context.methodContext().isStatic()) {
121 target = new JThis(line()).analyze(context);
122 } else {
123 target = new JVariable(line(), context.definingType()
124 .toString()).analyze(context);
125 }
126 } else {
127 target = (JExpression) target.analyze(context);
128 if (target.type().isPrimitive()) {
129 JAST.compilationUnit.reportSemanticError(line(),
130 "cannot invoke a message on a primitive type:"
131 + target.type());
132 }
133 }
134
135 method = target.type().methodFor(messageName, argTypes);
137 if (method == null) {
138 JAST.compilationUnit.reportSemanticError(line(),
139 "Cannot find method for: "
140 + Type.signatureFor(messageName, argTypes));
141 type = Type.ANY;
142 } else {
143 context.definingType().checkAccess(line, (Member) method);
144 type = method.returnType();
145
146 if (!method.isStatic()) {
148 if (target instanceof JVariable
149 && ((JVariable) target).iDefn() instanceof TypeNameDefn) {
150 JAST.compilationUnit
151 .reportSemanticError(
152 line(),
153 "Non-static method "
154 + Type.signatureFor(messageName,
155 argTypes)
156 + "cannot be referenced from a static context");
157 }
158 }
159 }
160 return this;
161 }
162
163
175
176 public void codegen(CLEmitter output) {
177 if (!method.isStatic()) {
178 target.codegen(output);
179 }
180 for (JExpression argument : arguments) {
181 argument.codegen(output);
182 }
183 int mnemonic = method.isStatic() ? INVOKESTATIC : target.type()
184 .isInterface() ? INVOKEINTERFACE : INVOKEVIRTUAL;
185 output.addMemberAccessInstruction(mnemonic, target.type().jvmName(),
186 messageName, method.toDescriptor());
187 if (isStatementExpression && type != Type.VOID) {
188 output.addNoArgInstruction(POP);
190 }
191 }
192
193
205
206 public void codegen(CLEmitter output, String targetLabel, boolean onTrue) {
207 codegen(output);
209
210 if (onTrue) {
211 output.addBranchInstruction(IFNE, targetLabel);
213 } else {
214 output.addBranchInstruction(IFEQ, targetLabel);
216 }
217 }
218
219
222
223 public void writeToStdOut(PrettyPrinter p) {
224 p.printf("<JMessageExpression line=\"%d\" name=\"%s\">\n", line(),
225 messageName);
226 p.indentRight();
227 if (target != null) {
228 p.println("<Target>");
229 p.indentRight();
230 target.writeToStdOut(p);
231 p.indentLeft();
232 p.println("</Target>");
233 }
234 if (arguments != null) {
235 p.println("<Arguments>");
236 for (JExpression argument : arguments) {
237 p.indentRight();
238 p.println("<Argument>");
239 p.indentRight();
240 argument.writeToStdOut(p);
241 p.indentLeft();
242 p.println("</Argument>");
243 p.indentLeft();
244 }
245 p.println("</Arguments>");
246 }
247 p.indentLeft();
248 p.println("</JMessageExpression>");
249 }
250
251 }
252