1
3 package jminusminus;
4
5 import java.util.ArrayList;
6 import static jminusminus.CLConstants.*;
7
8
11
12 class JMethodDeclaration extends JAST implements JMember {
13
14
15 protected ArrayList<String> mods;
16
17
18 protected String name;
19
20
21 private Type returnType;
22
23
24 protected ArrayList<JFormalParameter> params;
25
26
27 protected JBlock body;
28
29
30 protected MethodContext context;
31
32
33 protected String descriptor;
34
35
36 protected boolean isAbstract;
37
38
39 protected boolean isStatic;
40
41
42 protected boolean isPrivate;
43
44
62
63 public JMethodDeclaration(int line, ArrayList<String> mods, String name,
64 Type returnType, ArrayList<JFormalParameter> params, JBlock body)
65
66 {
67 super(line);
68 this.mods = mods;
69 this.name = name;
70 this.returnType = returnType;
71 this.params = params;
72 this.body = body;
73 this.isAbstract = mods.contains("abstract");
74 this.isStatic = mods.contains("static");
75 this.isPrivate = mods.contains("private");
76 }
77
78
87
88 public void preAnalyze(Context context, CLEmitter partial) {
89 for (JFormalParameter param : params) {
91 param.setType(param.type().resolve(context));
92 }
93
94 returnType = returnType.resolve(context);
96
97 if (isAbstract && body != null) {
99 JAST.compilationUnit.reportSemanticError(line(),
100 "abstract method cannot have a body");
101 } else if (body == null && !isAbstract) {
102 JAST.compilationUnit.reportSemanticError(line(),
103 "Method with null body must be abstarct");
104 } else if (isAbstract && isPrivate) {
105 JAST.compilationUnit.reportSemanticError(line(),
106 "private method cannot be declared abstract");
107 } else if (isAbstract && isStatic) {
108 JAST.compilationUnit.reportSemanticError(line(),
109 "static method cannot be declared abstract");
110 }
111
112 descriptor = "(";
114 for (JFormalParameter param : params) {
115 descriptor += param.type().toDescriptor();
116 }
117 descriptor += ")" + returnType.toDescriptor();
118
119 partialCodegen(context, partial);
121 }
122
123
134
135 public JAST analyze(Context context) {
136 this.context = new MethodContext(context, isStatic, returnType);
137
138 if (!isStatic) {
139 this.context.nextOffset();
141 }
142
143 for (JFormalParameter param : params) {
146 LocalVariableDefn defn = new LocalVariableDefn(param.type(),
147 this.context.nextOffset());
148 defn.initialize();
149 this.context.addEntry(param.line(), param.name(), defn);
150 }
151
152 if (body != null) {
153 body = body.analyze(this.context);
154 }
155 return this;
156 }
157
158
167
168 public void partialCodegen(Context context, CLEmitter partial) {
169 partial.addMethod(mods, name, descriptor, null, false);
173
174 if (returnType == Type.VOID) {
176 partial.addNoArgInstruction(RETURN);
177 } else if (returnType == Type.INT || returnType == Type.BOOLEAN
178 || returnType == Type.CHAR) {
179 partial.addNoArgInstruction(ICONST_0);
180 partial.addNoArgInstruction(IRETURN);
181 } else {
182 partial.addNoArgInstruction(ACONST_NULL);
184 partial.addNoArgInstruction(ARETURN);
185 }
186 }
187
188
195
196 public void codegen(CLEmitter output) {
197 output.addMethod(mods, name, descriptor, null, false);
198 if (body != null) {
199 body.codegen(output);
200 }
201
202 if (returnType == Type.VOID) {
204 output.addNoArgInstruction(RETURN);
205 }
206 }
207
208
211
212 public void writeToStdOut(PrettyPrinter p) {
213 p.printf("<JMethodDeclaration line=\"%d\" name=\"%s\" "
214 + "returnType=\"%s\">\n", line(), name, returnType.toString());
215 p.indentRight();
216 if (context != null) {
217 context.writeToStdOut(p);
218 }
219 if (mods != null) {
220 p.println("<Modifiers>");
221 p.indentRight();
222 for (String mod : mods) {
223 p.printf("<Modifier name=\"%s\"/>\n", mod);
224 }
225 p.indentLeft();
226 p.println("</Modifiers>");
227 }
228 if (params != null) {
229 p.println("<FormalParameters>");
230 for (JFormalParameter param : params) {
231 p.indentRight();
232 param.writeToStdOut(p);
233 p.indentLeft();
234 }
235 p.println("</FormalParameters>");
236 }
237 if (body != null) {
238 p.println("<Body>");
239 p.indentRight();
240 body.writeToStdOut(p);
241 p.indentLeft();
242 p.println("</Body>");
243 }
244 p.indentLeft();
245 p.println("</JMethodDeclaration>");
246 }
247
248 }
249