]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/constants/generic/MethodRef.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / constants / generic / MethodRef.java
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 (file)
index 0000000..ca4f1d1
--- /dev/null
@@ -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 <ul>
+ *     <li>{@link StaticMethodRef}</li> 
+ *     <li>{@link ObjectMethodRef}</li> 
+ *     <li>{@link ConstructorRef}</li> 
+ *     <li>{@link StaticFieldRef}</li> 
+ *     <li>{@link FieldRef}</li> 
+ *     <li>{@link SetStaticFieldRef}</li> 
+ *     <li>{@link SetFieldRef}</li>
+ * </ul>
+ * 
+ * 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<params.length;++i)
+                realParams[i+1] = params[i];
+        }
+        
+        @Override
+        public void invoke(MethodBuilder mb, StackItem[] stackItems, Val[] parameters) {
+            if(SCLCompilerConfiguration.DEBUG)
+                if(stackItems.length != realParams.length)
+                    throw new InternalCompilerError();            
+            for(StackItem stackItem : stackItems)
+                stackItem.push(mb, parameters);
+            if(isInterface)
+                mb.invokeInterface(className, methodName, ret, params);
+            else
+                mb.invokeVirtual(className, methodName, ret, params);                            
+        }
+        
+        @Override
+        public TypeDesc[] getParameterTypes() {
+            return realParams;
+        }
+        
+        @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(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 Java constructor. 
+     */
+    public static class ConstructorRef implements MethodRef {
+        
+        String className;
+        TypeDesc[] params;
+        TypeDesc ret;
+        
+        public ConstructorRef(String className, TypeDesc[] params) {
+            this.className = className;
+            this.params = params;
+            this.ret = TypeDesc.forClass(className);
+        }
+        
+        @Override
+        public void invoke(MethodBuilder mb, StackItem[] stackItems, Val[] parameters) {
+            if(SCLCompilerConfiguration.DEBUG)
+                if(stackItems.length != params.length)
+                    throw new InternalCompilerError();
+            mb.newObject(ret);
+            mb.dup();
+            for(StackItem stackItem : stackItems)
+                stackItem.push(mb, parameters);
+            mb.invokeConstructor(className, params);
+        }
+        
+        @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(className);
+            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 + ".<init>";
+        }
+    }
+    
+    /**
+     * 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 + ".<set>" + 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 + ".<set>" + fieldName;
+        }
+    }
+
+    public abstract String getName();
+}