135 final MemberInfo setter = scriptClassInfo.findSetter(memInfo);
136 linkerAddGetterSetter(mi, scriptClassInfo.getJavaName(), memInfo, setter);
137 }
138 }
139 emitStaticInitSuffix(mi, className);
140 }
141
142 private void emitConstructor() {
143 final MethodGenerator mi = makeConstructor();
144 mi.visitCode();
145 callSuper(mi);
146
147 if (memberCount > 0) {
148 // initialize Function type fields
149 initFunctionFields(mi);
150 // initialize data fields
151 initDataFields(mi);
152 }
153
154 if (constructor != null) {
155 final int arity = constructor.getArity();
156 if (arity != MemberInfo.DEFAULT_ARITY) {
157 mi.loadThis();
158 mi.push(arity);
159 mi.invokeVirtual(SCRIPTFUNCTION_TYPE, SCRIPTFUNCTION_SETARITY,
160 SCRIPTFUNCTION_SETARITY_DESC);
161 }
162 }
163 mi.returnVoid();
164 mi.computeMaxs();
165 mi.visitEnd();
166 }
167
168 private void loadMap(final MethodGenerator mi) {
169 if (memberCount > 0) {
170 mi.getStatic(className, PROPERTYMAP_FIELD_NAME, PROPERTYMAP_DESC);
171 }
172 }
173
174 private void callSuper(final MethodGenerator mi) {
176 mi.loadThis();
177 if (constructor == null) {
178 // call ScriptObject.<init>
179 superClass = SCRIPTOBJECT_TYPE;
180 superDesc = (memberCount > 0) ? SCRIPTOBJECT_INIT_DESC : DEFAULT_INIT_DESC;
181 loadMap(mi);
182 } else {
183 // call Function.<init>
184 superClass = SCRIPTFUNCTIONIMPL_TYPE;
185 superDesc = (memberCount > 0) ? SCRIPTFUNCTIONIMPL_INIT_DESC4 : SCRIPTFUNCTIONIMPL_INIT_DESC3;
186 mi.loadLiteral(constructor.getName());
187 mi.visitLdcInsn(new Handle(H_INVOKESTATIC, scriptClassInfo.getJavaName(), constructor.getJavaName(), constructor.getJavaDesc()));
188 loadMap(mi);
189 mi.memberInfoArray(scriptClassInfo.getJavaName(), specs); //pushes null if specs empty
190 }
191
192 mi.invokeSpecial(superClass, INIT, superDesc);
193 }
194
195 private void initFunctionFields(final MethodGenerator mi) {
196 for (final MemberInfo memInfo : scriptClassInfo.getMembers()) {
197 if (!memInfo.isConstructorFunction()) {
198 continue;
199 }
200 mi.loadThis();
201 newFunction(mi, scriptClassInfo.getJavaName(), memInfo, scriptClassInfo.findSpecializations(memInfo.getJavaName()));
202 mi.putField(className, memInfo.getJavaName(), OBJECT_DESC);
203 }
204 }
205
206 private void initDataFields(final MethodGenerator mi) {
207 for (final MemberInfo memInfo : scriptClassInfo.getMembers()) {
208 if (!memInfo.isConstructorProperty() || memInfo.isFinal()) {
209 continue;
210 }
211 final Object value = memInfo.getValue();
212 if (value != null) {
213 mi.loadThis();
214 mi.loadLiteral(value);
215 mi.putField(className, memInfo.getJavaName(), memInfo.getJavaDesc());
216 } else if (!memInfo.getInitClass().isEmpty()) {
217 final String clazz = memInfo.getInitClass();
218 mi.loadThis();
219 mi.newObject(clazz);
220 mi.dup();
221 mi.invokeSpecial(clazz, INIT, DEFAULT_INIT_DESC);
222 mi.putField(className, memInfo.getJavaName(), memInfo.getJavaDesc());
223 }
224 }
225
226 if (constructor != null) {
227 mi.loadThis();
228 final String protoName = scriptClassInfo.getPrototypeClassName();
229 mi.newObject(protoName);
230 mi.dup();
231 mi.invokeSpecial(protoName, INIT, DEFAULT_INIT_DESC);
232 mi.dup();
233 mi.loadThis();
234 mi.invokeStatic(PROTOTYPEOBJECT_TYPE, PROTOTYPEOBJECT_SETCONSTRUCTOR,
235 PROTOTYPEOBJECT_SETCONSTRUCTOR_DESC);
236 mi.invokeVirtual(SCRIPTFUNCTION_TYPE, SCRIPTFUNCTION_SETPROTOTYPE, SCRIPTFUNCTION_SETPROTOTYPE_DESC);
237 }
238 }
239
240 /**
241 * Entry point for ConstructorGenerator run separately as an application. Will display
242 * usage. Takes one argument, a class name.
243 * @param args args vector
244 * @throws IOException if class can't be read
245 */
246 public static void main(final String[] args) throws IOException {
247 if (args.length != 1) {
248 System.err.println("Usage: " + ConstructorGenerator.class.getName() + " <class>");
249 System.exit(1);
250 }
251
252 final String className = args[0].replace('.', '/');
253 final ScriptClassInfo sci = getScriptClassInfo(className + ".class");
254 if (sci == null) {
255 System.err.println("No @ScriptClass in " + className);
256 System.exit(2);
257 throw new IOException(); // get rid of warning for sci.verify() below - may be null
|
135 final MemberInfo setter = scriptClassInfo.findSetter(memInfo);
136 linkerAddGetterSetter(mi, scriptClassInfo.getJavaName(), memInfo, setter);
137 }
138 }
139 emitStaticInitSuffix(mi, className);
140 }
141
142 private void emitConstructor() {
143 final MethodGenerator mi = makeConstructor();
144 mi.visitCode();
145 callSuper(mi);
146
147 if (memberCount > 0) {
148 // initialize Function type fields
149 initFunctionFields(mi);
150 // initialize data fields
151 initDataFields(mi);
152 }
153
154 if (constructor != null) {
155 initPrototype(mi);
156 final int arity = constructor.getArity();
157 if (arity != MemberInfo.DEFAULT_ARITY) {
158 mi.loadThis();
159 mi.push(arity);
160 mi.invokeVirtual(SCRIPTFUNCTION_TYPE, SCRIPTFUNCTION_SETARITY,
161 SCRIPTFUNCTION_SETARITY_DESC);
162 }
163 }
164 mi.returnVoid();
165 mi.computeMaxs();
166 mi.visitEnd();
167 }
168
169 private void loadMap(final MethodGenerator mi) {
170 if (memberCount > 0) {
171 mi.getStatic(className, PROPERTYMAP_FIELD_NAME, PROPERTYMAP_DESC);
172 }
173 }
174
175 private void callSuper(final MethodGenerator mi) {
177 mi.loadThis();
178 if (constructor == null) {
179 // call ScriptObject.<init>
180 superClass = SCRIPTOBJECT_TYPE;
181 superDesc = (memberCount > 0) ? SCRIPTOBJECT_INIT_DESC : DEFAULT_INIT_DESC;
182 loadMap(mi);
183 } else {
184 // call Function.<init>
185 superClass = SCRIPTFUNCTIONIMPL_TYPE;
186 superDesc = (memberCount > 0) ? SCRIPTFUNCTIONIMPL_INIT_DESC4 : SCRIPTFUNCTIONIMPL_INIT_DESC3;
187 mi.loadLiteral(constructor.getName());
188 mi.visitLdcInsn(new Handle(H_INVOKESTATIC, scriptClassInfo.getJavaName(), constructor.getJavaName(), constructor.getJavaDesc()));
189 loadMap(mi);
190 mi.memberInfoArray(scriptClassInfo.getJavaName(), specs); //pushes null if specs empty
191 }
192
193 mi.invokeSpecial(superClass, INIT, superDesc);
194 }
195
196 private void initFunctionFields(final MethodGenerator mi) {
197 assert memberCount > 0;
198 for (final MemberInfo memInfo : scriptClassInfo.getMembers()) {
199 if (!memInfo.isConstructorFunction()) {
200 continue;
201 }
202 mi.loadThis();
203 newFunction(mi, scriptClassInfo.getJavaName(), memInfo, scriptClassInfo.findSpecializations(memInfo.getJavaName()));
204 mi.putField(className, memInfo.getJavaName(), OBJECT_DESC);
205 }
206 }
207
208 private void initDataFields(final MethodGenerator mi) {
209 assert memberCount > 0;
210 for (final MemberInfo memInfo : scriptClassInfo.getMembers()) {
211 if (!memInfo.isConstructorProperty() || memInfo.isFinal()) {
212 continue;
213 }
214 final Object value = memInfo.getValue();
215 if (value != null) {
216 mi.loadThis();
217 mi.loadLiteral(value);
218 mi.putField(className, memInfo.getJavaName(), memInfo.getJavaDesc());
219 } else if (!memInfo.getInitClass().isEmpty()) {
220 final String clazz = memInfo.getInitClass();
221 mi.loadThis();
222 mi.newObject(clazz);
223 mi.dup();
224 mi.invokeSpecial(clazz, INIT, DEFAULT_INIT_DESC);
225 mi.putField(className, memInfo.getJavaName(), memInfo.getJavaDesc());
226 }
227 }
228 }
229
230 private void initPrototype(final MethodGenerator mi) {
231 assert constructor != null;
232 mi.loadThis();
233 final String protoName = scriptClassInfo.getPrototypeClassName();
234 mi.newObject(protoName);
235 mi.dup();
236 mi.invokeSpecial(protoName, INIT, DEFAULT_INIT_DESC);
237 mi.dup();
238 mi.loadThis();
239 mi.invokeStatic(PROTOTYPEOBJECT_TYPE, PROTOTYPEOBJECT_SETCONSTRUCTOR,
240 PROTOTYPEOBJECT_SETCONSTRUCTOR_DESC);
241 mi.invokeVirtual(SCRIPTFUNCTION_TYPE, SCRIPTFUNCTION_SETPROTOTYPE, SCRIPTFUNCTION_SETPROTOTYPE_DESC);
242 }
243
244 /**
245 * Entry point for ConstructorGenerator run separately as an application. Will display
246 * usage. Takes one argument, a class name.
247 * @param args args vector
248 * @throws IOException if class can't be read
249 */
250 public static void main(final String[] args) throws IOException {
251 if (args.length != 1) {
252 System.err.println("Usage: " + ConstructorGenerator.class.getName() + " <class>");
253 System.exit(1);
254 }
255
256 final String className = args[0].replace('.', '/');
257 final ScriptClassInfo sci = getScriptClassInfo(className + ".class");
258 if (sci == null) {
259 System.err.println("No @ScriptClass in " + className);
260 System.exit(2);
261 throw new IOException(); // get rid of warning for sci.verify() below - may be null
|