1
3 package jminusminus;
4
5 import java.util.ArrayList;
6 import static jminusminus.CLConstants.*;
7
8
11
12 class JMethodDeclaration
13 extends JAST implements JMember {
14
15
16 protected ArrayList<String> mods;
17
18
19 protected String name;
20
21
22 protected Type returnType;
23
24
25 protected ArrayList<JFormalParameter> params;
26
27
28 protected JBlock body;
29
30
31 protected MethodContext context;
32
33
34 protected String descriptor;
35
36
37 protected boolean isAbstract;
38
39
40 protected boolean isStatic;
41
42
43 protected boolean isPrivate;
44
45
64
65 public JMethodDeclaration(int line, ArrayList<String> mods,
66 String name, Type returnType,
67 ArrayList<JFormalParameter> params, JBlock body)
68
69 {
70 super(line);
71 this.mods = mods;
72 this.name = name;
73 this.returnType = returnType;
74 this.params = params;
75 this.body = body;
76 this.isAbstract = mods.contains("abstract");
77 this.isStatic = mods.contains("static");
78 this.isPrivate = mods.contains("private");
79 }
80
81
90
91 public void preAnalyze(Context context, CLEmitter partial) {
92 for (JFormalParameter param : params) {
94 param.setType(param.type().resolve(context));
95 }
96
97 returnType = returnType.resolve(context);
99
100 if (isAbstract && body != null) {
102 JAST.compilationUnit.reportSemanticError(line(),
103 "abstract method cannot have a body");
104 } else if (body == null && !isAbstract) {
105 JAST.compilationUnit.reportSemanticError(line(),
106 "Method with null body must be abstarct");
107 } else if (isAbstract && isPrivate) {
108 JAST.compilationUnit.reportSemanticError(line(),
109 "private method cannot be declared abstract");
110 } else if (isAbstract && isStatic) {
111 JAST.compilationUnit.reportSemanticError(line(),
112 "static method cannot be declared abstract");
113 }
114
115 descriptor = "(";
117 for (JFormalParameter param : params) {
118 descriptor += param.type().toDescriptor();
119 }
120 descriptor += ")" + returnType.toDescriptor();
121
122 partialCodegen(context, partial);
124 }
125
126
138
139 public JAST analyze(Context context) {
140 MethodContext methodContext =
141 new MethodContext(context, isStatic, returnType);
142 this.context = methodContext;
143
144 if (!isStatic) {
145 this.context.nextOffset();
147 }
148
149 for (JFormalParameter param : params) {
152 LocalVariableDefn defn = new LocalVariableDefn(param.type(),
153 this.context.nextOffset());
154 defn.initialize();
155 this.context.addEntry(param.line(), param.name(), defn);
156 }
157 if (body != null) {
158 body = body.analyze(this.context);
159 if (returnType!=Type.VOID && ! methodContext.methodHasReturn()){
160 JAST.compilationUnit.reportSemanticError(line(),
161 "Non-void method must have a return statement");
162 }
163 }
164 return this;
165 }
166
167
176
177 public void partialCodegen(Context context, CLEmitter partial) {
178 partial.addMethod(mods, name, descriptor, null, false);
182
183 if (returnType == Type.VOID) {
185 partial.addNoArgInstruction(RETURN);
186 } else if (returnType == Type.INT
187 || returnType == Type.BOOLEAN || returnType == Type.CHAR) {
188 partial.addNoArgInstruction(ICONST_0);
189 partial.addNoArgInstruction(IRETURN);
190 } else {
191 partial.addNoArgInstruction(ACONST_NULL);
193 partial.addNoArgInstruction(ARETURN);
194 }
195 }
196
197
204
205 public void codegen(CLEmitter output) {
206 output.addMethod(mods, name, descriptor, null, false);
207 if (body != null) {
208 body.codegen(output);
209 }
210
211 if (returnType == Type.VOID) {
213 output.addNoArgInstruction(RETURN);
214 }
215 }
216
217
220
221 public void writeToStdOut(PrettyPrinter p) {
222 p.printf("<JMethodDeclaration line=\"%d\" name=\"%s\" "
223 + "returnType=\"%s\">\n", line(), name, returnType
224 .toString());
225 p.indentRight();
226 if (context != null) {
227 context.writeToStdOut(p);
228 }
229 if (mods != null) {
230 p.println("<Modifiers>");
231 p.indentRight();
232 for (String mod : mods) {
233 p.printf("<Modifier name=\"%s\"/>\n", mod);
234 }
235 p.indentLeft();
236 p.println("</Modifiers>");
237 }
238 if (params != null) {
239 p.println("<FormalParameters>");
240 for (JFormalParameter param : params) {
241 p.indentRight();
242 param.writeToStdOut(p);
243 p.indentLeft();
244 }
245 p.println("</FormalParameters>");
246 }
247 if (body != null) {
248 p.println("<Body>");
249 p.indentRight();
250 body.writeToStdOut(p);
251 p.indentLeft();
252 p.println("</Body>");
253 }
254 p.indentLeft();
255 p.println("</JMethodDeclaration>");
256 }
257 }
258