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
+ * - {@link StaticMethodRef}
+ * - {@link ObjectMethodRef}
+ * - {@link ConstructorRef}
+ * - {@link StaticFieldRef}
+ * - {@link FieldRef}
+ * - {@link SetStaticFieldRef}
+ * - {@link SetFieldRef}
+ *
+ *
+ * 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();
+}