1
3 package jminusminus;
4
5 import java.util.ArrayList;
6 import static jminusminus.CLConstants.*;
7
8
12
13 class JConstructorDeclaration extends JMethodDeclaration implements JMember {
14
15
16 private boolean invokesConstructor;
17
18
19 JClassDeclaration definingClass;
20
21
38
39 public JConstructorDeclaration(int line, ArrayList<String> mods,
40 String name, ArrayList<JFormalParameter> params, JBlock body)
41
42 {
43 super(line, mods, name, Type.CONSTRUCTOR, params, body);
44 }
45
46
55
56 public void preAnalyze(Context context, CLEmitter partial) {
57 super.preAnalyze(context, partial);
58 if (isStatic) {
59 JAST.compilationUnit.reportSemanticError(line(),
60 "Constructor cannot be declared static");
61 } else if (isAbstract) {
62 JAST.compilationUnit.reportSemanticError(line(),
63 "Constructor cannot be declared abstract");
64 }
65 if (body.statements().size() > 0
66 && body.statements().get(0) instanceof JStatementExpression) {
67 JStatementExpression first = (JStatementExpression) body
68 .statements().get(0);
69 if (first.expr instanceof JSuperConstruction) {
70 ((JSuperConstruction) first.expr).markProperUseOfConstructor();
71 invokesConstructor = true;
72 } else if (first.expr instanceof JThisConstruction) {
73 ((JThisConstruction) first.expr).markProperUseOfConstructor();
74 invokesConstructor = true;
75 }
76 }
77 }
78
79
87
88 public JAST analyze(Context context) {
89 definingClass =
91 (JClassDeclaration) context.classContext().definition();
92 MethodContext methodContext =
93 new MethodContext(context, isStatic, returnType);
94 this.context = methodContext;
95
96 if (!isStatic) {
97 this.context.nextOffset();
99 }
100
101 for (JFormalParameter param : params) {
104 LocalVariableDefn defn =
105 new LocalVariableDefn(param.type(),
106 this.context.nextOffset());
107 defn.initialize();
108 this.context.addEntry(param.line(), param.name(), defn);
109 }
110 if (body != null) {
111 body = body.analyze(this.context);
112 }
113 return this;
114
115 }
116
117
126
127 public void partialCodegen(Context context, CLEmitter partial) {
128 partial.addMethod(mods, "<init>", descriptor, null, false);
129 if (!invokesConstructor) {
130 partial.addNoArgInstruction(ALOAD_0);
131 partial.addMemberAccessInstruction(INVOKESPECIAL,
132 ((JTypeDecl) context.classContext().definition())
133 .superType().jvmName(), "<init>", "()V");
134 }
135 partial.addNoArgInstruction(RETURN);
136 }
137
138
145
146 public void codegen(CLEmitter output) {
147 output.addMethod(mods, "<init>", descriptor, null, false);
148 if (!invokesConstructor) {
149 output.addNoArgInstruction(ALOAD_0);
150 output.addMemberAccessInstruction(INVOKESPECIAL,
151 ((JTypeDecl) context.classContext().definition())
152 .superType().jvmName(), "<init>", "()V");
153 }
154 for (JFieldDeclaration field : definingClass
156 .instanceFieldInitializations()) {
157 field.codegenInitializations(output);
158 }
159 body.codegen(output);
161 output.addNoArgInstruction(RETURN);
162 }
163
164
167
168 public void writeToStdOut(PrettyPrinter p) {
169 p.printf("<JConstructorDeclaration line=\"%d\" " + "name=\"%s\">\n",
170 line(), name);
171 p.indentRight();
172 if (context != null) {
173 context.writeToStdOut(p);
174 }
175 if (mods != null) {
176 p.println("<Modifiers>");
177 p.indentRight();
178 for (String mod : mods) {
179 p.printf("<Modifier name=\"%s\"/>\n", mod);
180 }
181 p.indentLeft();
182 p.println("</Modifiers>");
183 }
184 if (params != null) {
185 p.println("<FormalParameters>");
186 for (JFormalParameter param : params) {
187 p.indentRight();
188 param.writeToStdOut(p);
189 p.indentLeft();
190 }
191 p.println("</FormalParameters>");
192 }
193 if (body != null) {
194 p.println("<Body>");
195 p.indentRight();
196 body.writeToStdOut(p);
197 p.indentLeft();
198 p.println("</Body>");
199 }
200 p.indentLeft();
201 p.println("</JConstructorDeclaration>");
202 }
203
204 }
205