]> gerrit.simantics Code Review - simantics/platform.git/blob - 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
1 package org.simantics.scl.compiler.internal.codegen.types;\r
2 \r
3 import java.lang.reflect.Constructor;\r
4 import java.lang.reflect.Field;\r
5 import java.lang.reflect.Method;\r
6 import java.lang.reflect.Modifier;\r
7 import java.util.ArrayList;\r
8 \r
9 import org.cojen.classfile.TypeDesc;\r
10 import org.simantics.scl.compiler.constants.generic.ClassRef;\r
11 import org.simantics.scl.runtime.function.Function;\r
12 \r
13 public abstract class AbstractRuntimeJavaReferenceValidator \r
14 implements JavaReferenceValidator<Class<?>, Method, Field, Constructor<?>> {\r
15 \r
16     @Override\r
17     public abstract Class<?> findClass(TypeDesc name);\r
18     \r
19     @Override\r
20     public boolean isInterface(Class<?> clazz) {\r
21         return clazz.isInterface();\r
22     }\r
23     \r
24     @Override\r
25     public boolean isPublic(Class<?> clazz) {\r
26         return Modifier.isPublic(clazz.getModifiers());\r
27     }\r
28 \r
29     @Override\r
30     public Method[] findCompatibleMethods(Class<?> clazz, boolean isStatic, String name, TypeDesc[] parameterTypes, TypeDesc returnType) {\r
31         Class<?>[] parameterClasses = new Class[parameterTypes.length];\r
32         for(int i=0;i<parameterTypes.length;++i)\r
33             parameterClasses[i] = findClass(parameterTypes[i]);\r
34         Class<?> returnClass = findClass(returnType);\r
35         \r
36         ArrayList<Method> methods = new ArrayList<Method>(2);\r
37         \r
38         methodLoop: \r
39         for(Method method : clazz.getMethods()) {\r
40             if(!method.getName().equals(name))\r
41                 continue;\r
42             if(Modifier.isStatic(method.getModifiers()) != isStatic)\r
43                 continue;\r
44             \r
45             Class<?>[] parameters = method.getParameterTypes();\r
46             if(parameters.length != parameterClasses.length)\r
47                 continue;\r
48             for(int i=0;i<parameters.length;++i)\r
49                 if(!parameters[i].isAssignableFrom(parameterClasses[i]))\r
50                     continue methodLoop;\r
51 \r
52             if(!returnClass.isAssignableFrom(method.getReturnType()))\r
53                 continue;            \r
54             \r
55             methods.add(method);\r
56         }       \r
57         \r
58         return methods.toArray(new Method[methods.size()]);\r
59     }\r
60 \r
61     @Override\r
62     public TypeDesc getReturnType(Method method) {\r
63         return TypeDesc.forClass(method.getReturnType());\r
64     }\r
65 \r
66     @Override\r
67     public TypeDesc[] getParameterTypes(Method method) {\r
68         Class<?>[] parameters = method.getParameterTypes();\r
69         TypeDesc[] result = new TypeDesc[parameters.length];\r
70         for(int i=0;i<parameters.length;++i)\r
71             result[i] = TypeDesc.forClass(parameters[i]);\r
72         return result;\r
73     }\r
74 \r
75     @Override\r
76     public Constructor<?>[] findCompatibleConstructors(Class<?> clazz,\r
77             TypeDesc[] types) {\r
78         Class<?>[] classes = new Class[types.length];\r
79         for(int i=0;i<types.length;++i)\r
80             classes[i] = findClass(types[i]);\r
81         int maxArity = types.length-1;\r
82         \r
83         ArrayList<Constructor<?>> constructors = new ArrayList<Constructor<?>>(2);\r
84         \r
85         methodLoop: \r
86         for(Constructor<?> constructor : clazz.getConstructors()) {           \r
87             Class<?>[] parameters = constructor.getParameterTypes();\r
88             int arity = parameters.length;\r
89             if(arity > maxArity)\r
90                 continue;\r
91             for(int i=0;i<parameters.length;++i)\r
92                 if(!parameters[i].isAssignableFrom(classes[i]))\r
93                     continue methodLoop;\r
94             \r
95             if(arity == maxArity) {\r
96                 if(!classes[maxArity].isAssignableFrom(clazz))\r
97                     continue;\r
98             }\r
99             else {\r
100                 if(!Function.class.isAssignableFrom(clazz))\r
101                     continue;\r
102             }\r
103             \r
104             constructors.add(constructor);\r
105         }       \r
106         \r
107         return constructors.toArray(new Constructor[constructors.size()]);\r
108     }\r
109 \r
110     @Override\r
111     public TypeDesc[] getConstructorParameterTypes(Constructor<?> constructor) {\r
112         Class<?>[] parameters = constructor.getParameterTypes();\r
113         TypeDesc[] result = new TypeDesc[parameters.length];\r
114         for(int i=0;i<parameters.length;++i)\r
115             result[i] = TypeDesc.forClass(parameters[i]);\r
116         return result;\r
117     }\r
118 \r
119     @Override\r
120     public Field findField(Class<?> clazz, String name) {\r
121         try {\r
122             return clazz.getField(name);\r
123         } catch(NoSuchFieldException e) {\r
124             return null;\r
125         }\r
126     }\r
127 \r
128     @Override\r
129     public boolean isStaticField(Field field) {\r
130         return Modifier.isStatic(field.getModifiers());\r
131     }\r
132 \r
133     @Override\r
134     public TypeDesc getFieldType(Field field) {\r
135         return TypeDesc.forClass(field.getType());\r
136     }\r
137 \r
138     @Override\r
139     public boolean isAssignableFrom(TypeDesc to, TypeDesc from) {\r
140         if(to == from)\r
141             return true;\r
142         Class<?> toClass = findClass(to);\r
143         Class<?> fromClass = findClass(from);\r
144         if(toClass == null || fromClass == null)\r
145             // Note: I added this branch when I noticed that type can be\r
146             //       one from the module under compilation.\r
147             // Note2: A problem with this seems to be that also \r
148             //        some other type descs go to null, such as double[][]\r
149             return false; \r
150         else\r
151             return toClass.isAssignableFrom(fromClass);\r
152     }\r
153 \r
154     @Override\r
155     public Method[] chooseBest(Method[] methods) {\r
156         ArrayList<Method> newResult = new ArrayList<Method>();\r
157         for(Method method : methods)\r
158             if(!method.isSynthetic())\r
159                 newResult.add(method);\r
160         return newResult.toArray(new Method[newResult.size()]);\r
161     }\r
162     \r
163     @Override\r
164     public ClassRef getClassRef(String className) {\r
165         Class<?> clazz = findClass(TypeDesc.forClass(className));\r
166         if(clazz == null)\r
167             return null;\r
168         return new ClassRef(clazz);\r
169     }\r
170 \r
171 }\r