1 package org.simantics.scl.compiler.constants.generic;
3 import org.cojen.classfile.TypeDesc;
4 import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
5 import org.simantics.scl.compiler.internal.codegen.references.Val;
6 import org.simantics.scl.compiler.internal.codegen.utils.ClassBuilder;
7 import org.simantics.scl.compiler.internal.codegen.utils.MethodBuilder;
8 import org.simantics.scl.compiler.top.SCLCompilerConfiguration;
11 * This interface represents a method for accessing the members of Java classes.
12 * This interface is implemented by <ul>
13 * <li>{@link StaticMethodRef}</li>
14 * <li>{@link ObjectMethodRef}</li>
15 * <li>{@link ConstructorRef}</li>
16 * <li>{@link StaticFieldRef}</li>
17 * <li>{@link FieldRef}</li>
18 * <li>{@link SetStaticFieldRef}</li>
19 * <li>{@link SetFieldRef}</li>
22 * It provides the method {@link #invoke(MethodBuilder, StackItem[], Val[])} for creating the Java byte code
23 * for calling the method or manipulating the field value.
25 * Parameter and return value type can be accessed using {@link #getParameterTypes()} and {@link #getReturnType()}.
27 public interface MethodRef {
30 * Build code for invoking the referenced function using a given MethodBuilder.
31 * @param mb a method builder
32 * @param stackItems a set of StackItem objects into which the call parameters are pushed
33 * @param parameters the method call parameters
35 void invoke(MethodBuilder mb, StackItem[] stackItems, Val[] parameters);
38 * Get the parameter types for a method. For (non-static) object methods and field accessors, the first
39 * parameter represents the object itself, as passed in the {@code this} variable.
41 public TypeDesc[] getParameterTypes();
44 * Get the return type of the method.
46 public TypeDesc getReturnType();
49 * This class represents a static Java class method.
51 public static class StaticMethodRef implements MethodRef {
58 public StaticMethodRef(String className, String methodName,
59 TypeDesc ret, TypeDesc[] params) {
60 this.className = className;
61 this.methodName = methodName;
67 public void invoke(MethodBuilder mb, StackItem[] stackItems, Val[] parameters) {
68 if(SCLCompilerConfiguration.DEBUG)
69 if(stackItems.length != params.length)
70 throw new InternalCompilerError();
71 for(StackItem stackItem : stackItems)
72 stackItem.push(mb, parameters);
73 mb.invokeStatic(className, methodName, ret, params);
77 public TypeDesc[] getParameterTypes() {
82 public TypeDesc getReturnType() {
87 public String toString() {
88 StringBuilder b = new StringBuilder();
89 b.append("public static ");
90 b.append(ret.getFullName());
95 for(TypeDesc param : params) {
100 b.append(param.getFullName());
107 public String getName() {
108 return className + "." + methodName;
113 * This class represents a (non-static) java object method.
115 public static class ObjectMethodRef implements MethodRef {
122 TypeDesc[] realParams;
124 public ObjectMethodRef(boolean isInterface, String className, String methodName,
125 TypeDesc ret, TypeDesc[] params) {
126 this.isInterface = isInterface;
127 ClassBuilder.checkClassName(className);
128 this.className = className;
129 this.methodName = methodName;
131 this.params = params;
132 this.realParams = new TypeDesc[params.length+1];
133 realParams[0] = TypeDesc.forClass(className);
134 for(int i=0;i<params.length;++i)
135 realParams[i+1] = params[i];
139 public void invoke(MethodBuilder mb, StackItem[] stackItems, Val[] parameters) {
140 if(SCLCompilerConfiguration.DEBUG)
141 if(stackItems.length != realParams.length)
142 throw new InternalCompilerError();
143 for(StackItem stackItem : stackItems)
144 stackItem.push(mb, parameters);
146 mb.invokeInterface(className, methodName, ret, params);
148 mb.invokeVirtual(className, methodName, ret, params);
152 public TypeDesc[] getParameterTypes() {
157 public TypeDesc getReturnType() {
162 public String toString() {
163 StringBuilder b = new StringBuilder();
165 b.append(ret.getFullName());
167 b.append(methodName);
169 boolean first = true;
170 for(TypeDesc param : params) {
175 b.append(param.getFullName());
182 public String getName() {
183 return className + "." + methodName;
188 * This class represents a Java constructor.
190 public static class ConstructorRef implements MethodRef {
196 public ConstructorRef(String className, TypeDesc[] params) {
197 this.className = className;
198 this.params = params;
199 this.ret = TypeDesc.forClass(className);
203 public void invoke(MethodBuilder mb, StackItem[] stackItems, Val[] parameters) {
204 if(SCLCompilerConfiguration.DEBUG)
205 if(stackItems.length != params.length)
206 throw new InternalCompilerError();
209 for(StackItem stackItem : stackItems)
210 stackItem.push(mb, parameters);
211 mb.invokeConstructor(className, params);
215 public TypeDesc[] getParameterTypes() {
220 public TypeDesc getReturnType() {
225 public String toString() {
226 StringBuilder b = new StringBuilder();
230 boolean first = true;
231 for(TypeDesc param : params) {
236 b.append(param.getFullName());
243 public String getName() {
244 return className + ".<init>";
249 * This class represents a read access to a static Java field, represented as a zero-arity {@link MethodRef}.
251 public static class StaticFieldRef implements MethodRef {
257 public StaticFieldRef(String className, String fieldName, TypeDesc ret) {
258 this.className = className;
259 this.fieldName = fieldName;
264 public void invoke(MethodBuilder mb, StackItem[] stackItems, Val[] parameters) {
265 if(SCLCompilerConfiguration.DEBUG)
266 if(stackItems.length != 0)
267 throw new InternalCompilerError();
268 mb.loadStaticField(className, fieldName, ret);
272 public TypeDesc[] getParameterTypes() {
273 return ClassRef.NO_PARAMS;
277 public TypeDesc getReturnType() {
282 public String toString() {
283 StringBuilder b = new StringBuilder();
284 b.append("public static ");
285 b.append(ret.getFullName());
292 public String getName() {
293 return className + "." + fieldName;
298 * This class represents read access to a Java (non-static) object field as a one-parameter {@link MethodRef}.
300 public static class FieldRef implements MethodRef {
307 public FieldRef(String className, String fieldName, TypeDesc ret) {
308 this.className = className;
309 this.fieldName = fieldName;
311 this.params = new TypeDesc[] {TypeDesc.forClass(className)};
315 public void invoke(MethodBuilder mb, StackItem[] stackItems, Val[] parameters) {
316 if(SCLCompilerConfiguration.DEBUG)
317 if(stackItems.length != 1)
318 throw new InternalCompilerError();
319 stackItems[0].push(mb, parameters);
320 mb.loadField(className, fieldName, ret);
324 public TypeDesc[] getParameterTypes() {
329 public TypeDesc getReturnType() {
334 public String toString() {
335 StringBuilder b = new StringBuilder();
337 b.append(ret.getFullName());
344 public String getName() {
345 return className + "." + fieldName;
350 * This class represents a method for setting a static Java field value as a one-parameter {@link MethodRef}
352 public static class SetStaticFieldRef implements MethodRef {
359 public SetStaticFieldRef(String className, String fieldName, TypeDesc ret) {
360 this.className = className;
361 this.fieldName = fieldName;
363 this.params = new TypeDesc[] {ret};
367 public void invoke(MethodBuilder mb, StackItem[] stackItems, Val[] parameters) {
368 if(SCLCompilerConfiguration.DEBUG)
369 if(stackItems.length != 1)
370 throw new InternalCompilerError();
371 stackItems[0].push(mb, parameters);
372 mb.storeStaticField(className, fieldName, ret);
376 public TypeDesc[] getParameterTypes() {
381 public TypeDesc getReturnType() {
382 return TypeDesc.VOID;
386 public String toString() {
387 StringBuilder b = new StringBuilder();
388 b.append("public static ");
389 b.append(ret.getFullName());
396 public String getName() {
397 return className + ".<set>" + fieldName;
402 * This class represents a method for setting the value of a Java (non-static) object field as a two-parameter
403 * {@link MethodRef}. The first parameter is the object reference and the second parameter is the field value.
405 public static class SetFieldRef implements MethodRef {
412 public SetFieldRef(String className, String fieldName, TypeDesc ret) {
413 this.className = className;
414 this.fieldName = fieldName;
416 this.params = new TypeDesc[] {TypeDesc.forClass(className), ret};
420 public void invoke(MethodBuilder mb, StackItem[] stackItems, Val[] parameters) {
421 if(SCLCompilerConfiguration.DEBUG)
422 if(stackItems.length != 2)
423 throw new InternalCompilerError();
424 stackItems[0].push(mb, parameters);
425 stackItems[1].push(mb, parameters);
426 mb.storeField(className, fieldName, ret);
430 public TypeDesc[] getParameterTypes() {
435 public TypeDesc getReturnType() {
436 return TypeDesc.VOID;
440 public String toString() {
441 StringBuilder b = new StringBuilder();
443 b.append(ret.getFullName());
450 public String getName() {
451 return className + ".<set>" + fieldName;
455 public abstract String getName();