X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;f=bundles%2Forg.simantics.scl.compiler%2Fsrc%2Forg%2Fsimantics%2Fscl%2Fcompiler%2Fconstants%2Fgeneric%2FMethodRef.java;fp=bundles%2Forg.simantics.scl.compiler%2Fsrc%2Forg%2Fsimantics%2Fscl%2Fcompiler%2Fconstants%2Fgeneric%2FMethodRef.java;h=ca4f1d18f2df08b033536348a3ef4230b632f085;hb=969bd23cab98a79ca9101af33334000879fb60c5;hp=0000000000000000000000000000000000000000;hpb=866dba5cd5a3929bbeae85991796acb212338a08;p=simantics%2Fplatform.git diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/constants/generic/MethodRef.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/constants/generic/MethodRef.java new file mode 100644 index 000000000..ca4f1d18f --- /dev/null +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/constants/generic/MethodRef.java @@ -0,0 +1,456 @@ +package org.simantics.scl.compiler.constants.generic; + +import org.cojen.classfile.TypeDesc; +import org.simantics.scl.compiler.common.exceptions.InternalCompilerError; +import org.simantics.scl.compiler.internal.codegen.references.Val; +import org.simantics.scl.compiler.internal.codegen.utils.ClassBuilder; +import org.simantics.scl.compiler.internal.codegen.utils.MethodBuilder; +import org.simantics.scl.compiler.top.SCLCompilerConfiguration; + +/** + * This interface represents a method for accessing the members of Java classes. + * This interface is implemented by + * + * It provides the method {@link #invoke(MethodBuilder, StackItem[], Val[])} for creating the Java byte code + * for calling the method or manipulating the field value. + * + * Parameter and return value type can be accessed using {@link #getParameterTypes()} and {@link #getReturnType()}. + */ +public interface MethodRef { + + /** + * Build code for invoking the referenced function using a given MethodBuilder. + * @param mb a method builder + * @param stackItems a set of StackItem objects into which the call parameters are pushed + * @param parameters the method call parameters + */ + void invoke(MethodBuilder mb, StackItem[] stackItems, Val[] parameters); + + /** + * Get the parameter types for a method. For (non-static) object methods and field accessors, the first + * parameter represents the object itself, as passed in the {@code this} variable. + */ + public TypeDesc[] getParameterTypes(); + + /** + * Get the return type of the method. + */ + public TypeDesc getReturnType(); + + /** + * This class represents a static Java class method. + */ + public static class StaticMethodRef implements MethodRef { + + String className; + String methodName; + TypeDesc ret; + TypeDesc[] params; + + public StaticMethodRef(String className, String methodName, + TypeDesc ret, TypeDesc[] params) { + this.className = className; + this.methodName = methodName; + this.ret = ret; + this.params = params; + } + + @Override + public void invoke(MethodBuilder mb, StackItem[] stackItems, Val[] parameters) { + if(SCLCompilerConfiguration.DEBUG) + if(stackItems.length != params.length) + throw new InternalCompilerError(); + for(StackItem stackItem : stackItems) + stackItem.push(mb, parameters); + mb.invokeStatic(className, methodName, ret, params); + } + + @Override + public TypeDesc[] getParameterTypes() { + return params; + } + + @Override + public TypeDesc getReturnType() { + return ret; + } + + @Override + public String toString() { + StringBuilder b = new StringBuilder(); + b.append("public static "); + b.append(ret.getFullName()); + b.append(" "); + b.append(methodName); + b.append("("); + boolean first = true; + for(TypeDesc param : params) { + if(first) + first = false; + else + b.append(", "); + b.append(param.getFullName()); + } + b.append(")"); + return b.toString(); + } + + @Override + public String getName() { + return className + "." + methodName; + } + } + + /** + * This class represents a (non-static) java object method. + */ + public static class ObjectMethodRef implements MethodRef { + + boolean isInterface; + String className; + String methodName; + TypeDesc ret; + TypeDesc[] params; + TypeDesc[] realParams; + + public ObjectMethodRef(boolean isInterface, String className, String methodName, + TypeDesc ret, TypeDesc[] params) { + this.isInterface = isInterface; + ClassBuilder.checkClassName(className); + this.className = className; + this.methodName = methodName; + this.ret = ret; + this.params = params; + this.realParams = new TypeDesc[params.length+1]; + realParams[0] = TypeDesc.forClass(className); + for(int i=0;i"; + } + } + + /** + * This class represents a read access to a static Java field, represented as a zero-arity {@link MethodRef}. + */ + public static class StaticFieldRef implements MethodRef { + + String className; + String fieldName; + TypeDesc ret; + + public StaticFieldRef(String className, String fieldName, TypeDesc ret) { + this.className = className; + this.fieldName = fieldName; + this.ret = ret; + } + + @Override + public void invoke(MethodBuilder mb, StackItem[] stackItems, Val[] parameters) { + if(SCLCompilerConfiguration.DEBUG) + if(stackItems.length != 0) + throw new InternalCompilerError(); + mb.loadStaticField(className, fieldName, ret); + } + + @Override + public TypeDesc[] getParameterTypes() { + return ClassRef.NO_PARAMS; + } + + @Override + public TypeDesc getReturnType() { + return ret; + } + + @Override + public String toString() { + StringBuilder b = new StringBuilder(); + b.append("public static "); + b.append(ret.getFullName()); + b.append(" "); + b.append(fieldName); + return b.toString(); + } + + @Override + public String getName() { + return className + "." + fieldName; + } + } + + /** + * This class represents read access to a Java (non-static) object field as a one-parameter {@link MethodRef}. + */ + public static class FieldRef implements MethodRef { + + String className; + String fieldName; + TypeDesc[] params; + TypeDesc ret; + + public FieldRef(String className, String fieldName, TypeDesc ret) { + this.className = className; + this.fieldName = fieldName; + this.ret = ret; + this.params = new TypeDesc[] {TypeDesc.forClass(className)}; + } + + @Override + public void invoke(MethodBuilder mb, StackItem[] stackItems, Val[] parameters) { + if(SCLCompilerConfiguration.DEBUG) + if(stackItems.length != 1) + throw new InternalCompilerError(); + stackItems[0].push(mb, parameters); + mb.loadField(className, fieldName, ret); + } + + @Override + public TypeDesc[] getParameterTypes() { + return params; + } + + @Override + public TypeDesc getReturnType() { + return ret; + } + + @Override + public String toString() { + StringBuilder b = new StringBuilder(); + b.append("public "); + b.append(ret.getFullName()); + b.append(" "); + b.append(fieldName); + return b.toString(); + } + + @Override + public String getName() { + return className + "." + fieldName; + } + } + + /** + * This class represents a method for setting a static Java field value as a one-parameter {@link MethodRef} + */ + public static class SetStaticFieldRef implements MethodRef { + + String className; + String fieldName; + TypeDesc ret; + TypeDesc[] params; + + public SetStaticFieldRef(String className, String fieldName, TypeDesc ret) { + this.className = className; + this.fieldName = fieldName; + this.ret = ret; + this.params = new TypeDesc[] {ret}; + } + + @Override + public void invoke(MethodBuilder mb, StackItem[] stackItems, Val[] parameters) { + if(SCLCompilerConfiguration.DEBUG) + if(stackItems.length != 1) + throw new InternalCompilerError(); + stackItems[0].push(mb, parameters); + mb.storeStaticField(className, fieldName, ret); + } + + @Override + public TypeDesc[] getParameterTypes() { + return params; + } + + @Override + public TypeDesc getReturnType() { + return TypeDesc.VOID; + } + + @Override + public String toString() { + StringBuilder b = new StringBuilder(); + b.append("public static "); + b.append(ret.getFullName()); + b.append(" "); + b.append(fieldName); + return b.toString(); + } + + @Override + public String getName() { + return className + "." + fieldName; + } + } + + /** + * This class represents a method for setting the value of a Java (non-static) object field as a two-parameter + * {@link MethodRef}. The first parameter is the object reference and the second parameter is the field value. + */ + public static class SetFieldRef implements MethodRef { + + String className; + String fieldName; + TypeDesc ret; + TypeDesc[] params; + + public SetFieldRef(String className, String fieldName, TypeDesc ret) { + this.className = className; + this.fieldName = fieldName; + this.ret = ret; + this.params = new TypeDesc[] {TypeDesc.forClass(className), ret}; + } + + @Override + public void invoke(MethodBuilder mb, StackItem[] stackItems, Val[] parameters) { + if(SCLCompilerConfiguration.DEBUG) + if(stackItems.length != 2) + throw new InternalCompilerError(); + stackItems[0].push(mb, parameters); + stackItems[1].push(mb, parameters); + mb.storeField(className, fieldName, ret); + } + + @Override + public TypeDesc[] getParameterTypes() { + return params; + } + + @Override + public TypeDesc getReturnType() { + return TypeDesc.VOID; + } + + @Override + public String toString() { + StringBuilder b = new StringBuilder(); + b.append("public "); + b.append(ret.getFullName()); + b.append(" "); + b.append(fieldName); + return b.toString(); + } + + @Override + public String getName() { + return className + "." + fieldName; + } + } + + public abstract String getName(); +}