--- /dev/null
+package org.simantics.scl.compiler.constants.generic;\r
+\r
+import org.cojen.classfile.TypeDesc;\r
+import org.simantics.scl.compiler.constants.FunctionValue;\r
+import org.simantics.scl.compiler.internal.codegen.references.Val;\r
+import org.simantics.scl.compiler.internal.codegen.types.JavaReferenceValidator;\r
+import org.simantics.scl.compiler.internal.codegen.utils.MethodBuilder;\r
+import org.simantics.scl.compiler.types.TVar;\r
+import org.simantics.scl.compiler.types.Type;\r
+\r
+/**\r
+ * This class represents a call to a Java method as an SCL function value.\r
+ * It is instantiated by the {@link org.simantics.scl.compiler.compilation.Elaboration.matchType(MethodRef, Type)} method. \r
+ */\r
+public class CallJava extends FunctionValue {\r
+ StackItem[] stackItems;\r
+ MethodRef methodRef;\r
+ OutputFilter filter;\r
+ \r
+ public CallJava(TVar[] typeParameters, Type effect, Type returnType,\r
+ Type[] parameterTypes, StackItem[] stackItems, MethodRef methodRef,\r
+ OutputFilter filter) {\r
+ super(typeParameters, effect, returnType, parameterTypes);\r
+ this.stackItems = stackItems;\r
+ this.methodRef = methodRef;\r
+ this.filter = filter;\r
+ }\r
+\r
+ @Override\r
+ public Type applyExact(MethodBuilder mb, Val[] parameters) {\r
+ methodRef.invoke(mb, stackItems, parameters);\r
+ if(filter != null)\r
+ filter.filter(mb);\r
+ return getReturnType();\r
+ }\r
+ \r
+ public MethodRef getMethodRef() {\r
+ return methodRef;\r
+ }\r
+ \r
+ @Override\r
+ public String toString() {\r
+ return methodRef.getName();\r
+ }\r
+\r
+ public final static int INCOMPARABLE = -2;\r
+ public final static int LESS = -1;\r
+ public final static int EQUAL = 0;\r
+ public final static int GREATER = 1;\r
+ \r
+ public int compareTo(JavaReferenceValidator validator, CallJava other) {\r
+ MethodRef m1 = methodRef;\r
+ MethodRef m2 = other.methodRef;\r
+ TypeDesc[] ps1 = m1.getParameterTypes();\r
+ TypeDesc[] ps2 = m2.getParameterTypes();\r
+ if(ps1.length != ps2.length)\r
+ return INCOMPARABLE;\r
+\r
+ boolean lessOrEqual = true;\r
+ boolean greaterOrEqual = true;\r
+ for(int i=0;i<ps1.length;++i) {\r
+ if(ps1[i].equals(ps2[i]))\r
+ continue;\r
+ if(!validator.isAssignableFrom(ps1[i], ps2[i])) {\r
+ lessOrEqual = false;\r
+ }\r
+ if(!validator.isAssignableFrom(ps2[i], ps1[i])) {\r
+ greaterOrEqual = false;\r
+ }\r
+ }\r
+ if(lessOrEqual) {\r
+ if(greaterOrEqual)\r
+ return EQUAL;\r
+ else\r
+ return LESS;\r
+ }\r
+ else {\r
+ if(greaterOrEqual)\r
+ return GREATER;\r
+ else\r
+ return INCOMPARABLE;\r
+ }\r
+ }\r
+ \r
+ @Override\r
+ public void prepare(MethodBuilder mb) {\r
+ for(StackItem item : stackItems)\r
+ item.prepare(mb);\r
+ }\r
+}\r