]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/types/AbstractRuntimeJavaReferenceValidator.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / internal / codegen / types / AbstractRuntimeJavaReferenceValidator.java
diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/types/AbstractRuntimeJavaReferenceValidator.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/types/AbstractRuntimeJavaReferenceValidator.java
new file mode 100644 (file)
index 0000000..5ea3064
--- /dev/null
@@ -0,0 +1,171 @@
+package org.simantics.scl.compiler.internal.codegen.types;\r
+\r
+import java.lang.reflect.Constructor;\r
+import java.lang.reflect.Field;\r
+import java.lang.reflect.Method;\r
+import java.lang.reflect.Modifier;\r
+import java.util.ArrayList;\r
+\r
+import org.cojen.classfile.TypeDesc;\r
+import org.simantics.scl.compiler.constants.generic.ClassRef;\r
+import org.simantics.scl.runtime.function.Function;\r
+\r
+public abstract class AbstractRuntimeJavaReferenceValidator \r
+implements JavaReferenceValidator<Class<?>, Method, Field, Constructor<?>> {\r
+\r
+    @Override\r
+    public abstract Class<?> findClass(TypeDesc name);\r
+    \r
+    @Override\r
+    public boolean isInterface(Class<?> clazz) {\r
+        return clazz.isInterface();\r
+    }\r
+    \r
+    @Override\r
+    public boolean isPublic(Class<?> clazz) {\r
+        return Modifier.isPublic(clazz.getModifiers());\r
+    }\r
+\r
+    @Override\r
+    public Method[] findCompatibleMethods(Class<?> clazz, boolean isStatic, String name, TypeDesc[] parameterTypes, TypeDesc returnType) {\r
+        Class<?>[] parameterClasses = new Class[parameterTypes.length];\r
+        for(int i=0;i<parameterTypes.length;++i)\r
+            parameterClasses[i] = findClass(parameterTypes[i]);\r
+        Class<?> returnClass = findClass(returnType);\r
+        \r
+        ArrayList<Method> methods = new ArrayList<Method>(2);\r
+        \r
+        methodLoop: \r
+        for(Method method : clazz.getMethods()) {\r
+            if(!method.getName().equals(name))\r
+                continue;\r
+            if(Modifier.isStatic(method.getModifiers()) != isStatic)\r
+                continue;\r
+            \r
+            Class<?>[] parameters = method.getParameterTypes();\r
+            if(parameters.length != parameterClasses.length)\r
+                continue;\r
+            for(int i=0;i<parameters.length;++i)\r
+                if(!parameters[i].isAssignableFrom(parameterClasses[i]))\r
+                    continue methodLoop;\r
+\r
+            if(!returnClass.isAssignableFrom(method.getReturnType()))\r
+                continue;            \r
+            \r
+            methods.add(method);\r
+        }       \r
+        \r
+        return methods.toArray(new Method[methods.size()]);\r
+    }\r
+\r
+    @Override\r
+    public TypeDesc getReturnType(Method method) {\r
+        return TypeDesc.forClass(method.getReturnType());\r
+    }\r
+\r
+    @Override\r
+    public TypeDesc[] getParameterTypes(Method method) {\r
+        Class<?>[] parameters = method.getParameterTypes();\r
+        TypeDesc[] result = new TypeDesc[parameters.length];\r
+        for(int i=0;i<parameters.length;++i)\r
+            result[i] = TypeDesc.forClass(parameters[i]);\r
+        return result;\r
+    }\r
+\r
+    @Override\r
+    public Constructor<?>[] findCompatibleConstructors(Class<?> clazz,\r
+            TypeDesc[] types) {\r
+        Class<?>[] classes = new Class[types.length];\r
+        for(int i=0;i<types.length;++i)\r
+            classes[i] = findClass(types[i]);\r
+        int maxArity = types.length-1;\r
+        \r
+        ArrayList<Constructor<?>> constructors = new ArrayList<Constructor<?>>(2);\r
+        \r
+        methodLoop: \r
+        for(Constructor<?> constructor : clazz.getConstructors()) {           \r
+            Class<?>[] parameters = constructor.getParameterTypes();\r
+            int arity = parameters.length;\r
+            if(arity > maxArity)\r
+                continue;\r
+            for(int i=0;i<parameters.length;++i)\r
+                if(!parameters[i].isAssignableFrom(classes[i]))\r
+                    continue methodLoop;\r
+            \r
+            if(arity == maxArity) {\r
+                if(!classes[maxArity].isAssignableFrom(clazz))\r
+                    continue;\r
+            }\r
+            else {\r
+                if(!Function.class.isAssignableFrom(clazz))\r
+                    continue;\r
+            }\r
+            \r
+            constructors.add(constructor);\r
+        }       \r
+        \r
+        return constructors.toArray(new Constructor[constructors.size()]);\r
+    }\r
+\r
+    @Override\r
+    public TypeDesc[] getConstructorParameterTypes(Constructor<?> constructor) {\r
+        Class<?>[] parameters = constructor.getParameterTypes();\r
+        TypeDesc[] result = new TypeDesc[parameters.length];\r
+        for(int i=0;i<parameters.length;++i)\r
+            result[i] = TypeDesc.forClass(parameters[i]);\r
+        return result;\r
+    }\r
+\r
+    @Override\r
+    public Field findField(Class<?> clazz, String name) {\r
+        try {\r
+            return clazz.getField(name);\r
+        } catch(NoSuchFieldException e) {\r
+            return null;\r
+        }\r
+    }\r
+\r
+    @Override\r
+    public boolean isStaticField(Field field) {\r
+        return Modifier.isStatic(field.getModifiers());\r
+    }\r
+\r
+    @Override\r
+    public TypeDesc getFieldType(Field field) {\r
+        return TypeDesc.forClass(field.getType());\r
+    }\r
+\r
+    @Override\r
+    public boolean isAssignableFrom(TypeDesc to, TypeDesc from) {\r
+        if(to == from)\r
+            return true;\r
+        Class<?> toClass = findClass(to);\r
+        Class<?> fromClass = findClass(from);\r
+        if(toClass == null || fromClass == null)\r
+            // Note: I added this branch when I noticed that type can be\r
+            //       one from the module under compilation.\r
+            // Note2: A problem with this seems to be that also \r
+            //        some other type descs go to null, such as double[][]\r
+            return false; \r
+        else\r
+            return toClass.isAssignableFrom(fromClass);\r
+    }\r
+\r
+    @Override\r
+    public Method[] chooseBest(Method[] methods) {\r
+        ArrayList<Method> newResult = new ArrayList<Method>();\r
+        for(Method method : methods)\r
+            if(!method.isSynthetic())\r
+                newResult.add(method);\r
+        return newResult.toArray(new Method[newResult.size()]);\r
+    }\r
+    \r
+    @Override\r
+    public ClassRef getClassRef(String className) {\r
+        Class<?> clazz = findClass(TypeDesc.forClass(className));\r
+        if(clazz == null)\r
+            return null;\r
+        return new ClassRef(clazz);\r
+    }\r
+\r
+}\r