1
3 package jminusminus;
4
5 import java.util.ArrayList;
6
7 import static jminusminus.CLConstants.*;
8
9
12 class JConstructorDeclaration extends JMethodDeclaration implements JMember {
13 private boolean invokesConstructor;
15
16 private JClassDeclaration definingClass;
18
19
29 public JConstructorDeclaration(int line, ArrayList<String> mods, String name,
30 ArrayList<JFormalParameter> params,
31 ArrayList<TypeName> exceptions, JBlock body) {
32 super(line, mods, name, Type.CONSTRUCTOR, params, exceptions, body);
33 }
34
35
38 public void preAnalyze(Context context, CLEmitter partial) {
39 super.preAnalyze(context, partial);
40 if (isStatic) {
41 JAST.compilationUnit.reportSemanticError(line(), "Constructor cannot be static");
42 } else if (isAbstract) {
43 JAST.compilationUnit.reportSemanticError(line(), "Constructor cannot be abstract");
44 }
45 if (body.statements().size() > 0 &&
46 body.statements().get(0) instanceof JStatementExpression) {
47 JStatementExpression first = (JStatementExpression) body.statements().get(0);
48 if (first.expr instanceof JSuperConstruction) {
49 ((JSuperConstruction) first.expr).markProperUseOfConstructor();
50 invokesConstructor = true;
51 } else if (first.expr instanceof JThisConstruction) {
52 ((JThisConstruction) first.expr).markProperUseOfConstructor();
53 invokesConstructor = true;
54 }
55 }
56 }
57
58
61 public JAST analyze(Context context) {
62 definingClass = (JClassDeclaration) (context.classContext().definition());
64
65 MethodContext methodContext = new MethodContext(context, isStatic, returnType);
66 this.context = methodContext;
67
68 if (!isStatic) {
69 this.context.nextOffset();
71 }
72
73 for (JFormalParameter param : params) {
76 LocalVariableDefn defn = new LocalVariableDefn(param.type(), this.context.nextOffset());
77 defn.initialize();
78 this.context.addEntry(param.line(), param.name(), defn);
79 }
80
81 if (body != null) {
82 body = body.analyze(this.context);
83 }
84 return this;
85 }
86
87
90 public void partialCodegen(Context context, CLEmitter partial) {
91 partial.addMethod(mods, "<init>", descriptor, null, false);
92 if (!invokesConstructor) {
93 partial.addNoArgInstruction(ALOAD_0);
94 partial.addMemberAccessInstruction(INVOKESPECIAL,
95 ((JClassDeclaration) context.classContext().definition()).superType().jvmName(),
96 "<init>", "()V");
97 }
98 partial.addNoArgInstruction(RETURN);
99 }
100
101
104 public void codegen(CLEmitter output) {
105 output.addMethod(mods, "<init>", descriptor, null, false);
106 if (!invokesConstructor) {
107 output.addNoArgInstruction(ALOAD_0);
108 output.addMemberAccessInstruction(INVOKESPECIAL, definingClass.superType().jvmName(),
109 "<init>", "()V");
110 }
111
112 for (JFieldDeclaration field : definingClass.instanceFieldInitializations()) {
114 field.codegenInitializations(output);
115 }
116
117 body.codegen(output);
119
120 output.addNoArgInstruction(RETURN);
121 }
122
123
126 public void toJSON(JSONElement json) {
127 JSONElement e = new JSONElement();
128 json.addChild("JConstructorDeclaration:" + line, e);
129 e.addAttribute("name", name);
130 if (mods != null) {
131 ArrayList<String> value = new ArrayList<String>();
132 for (String mod : mods) {
133 value.add(String.format("\"%s\"", mod));
134 }
135 e.addAttribute("modifiers", value);
136 }
137 if (params != null) {
138 ArrayList<String> value = new ArrayList<String>();
139 for (JFormalParameter param : params) {
140 value.add(String.format("[\"%s\", \"%s\"]", param.name(),
141 param.type() == null ? "" : param.type().toString()));
142 }
143 e.addAttribute("parameters", value);
144 }
145 if (exceptions != null) {
146 ArrayList<String> value = new ArrayList<String>();
147 for (TypeName exception : exceptions) {
148 value.add(String.format("\"%s\"", exception.toString()));
149 }
150 e.addAttribute("throws", value);
151 }
152 if (context != null) {
153 context.toJSON(e);
154 }
155 if (body != null) {
156 body.toJSON(e);
157 }
158 }
159 }
160