|
1 |
| package edu.rice.cs.dynamicjava.symbol; |
|
2 |
| |
|
3 |
| import java.lang.reflect.Array; |
|
4 |
| import edu.rice.cs.plt.lambda.Lambda; |
|
5 |
| import edu.rice.cs.plt.lambda.Thunk; |
|
6 |
| import edu.rice.cs.plt.iter.IterUtil; |
|
7 |
| import edu.rice.cs.plt.reflect.JavaVersion; |
|
8 |
| import edu.rice.cs.plt.reflect.ReflectUtil; |
|
9 |
| import edu.rice.cs.plt.reflect.ReflectException; |
|
10 |
| |
|
11 |
| import edu.rice.cs.dynamicjava.symbol.type.*; |
|
12 |
| |
|
13 |
| import static edu.rice.cs.plt.debug.DebugUtil.debug; |
|
14 |
| |
|
15 |
| public class SymbolUtil { |
|
16 |
| |
|
17 |
| |
|
18 |
| |
|
19 |
| |
|
20 |
| |
|
21 |
| |
|
22 |
| |
|
23 |
9025
| public static Iterable<DJClass> outerClassChain(DJClass c) {
|
|
24 |
9025
| Iterable<DJClass> result = IterUtil.singleton(c);
|
|
25 |
9025
| DJClass outer = c.declaringClass();
|
|
26 |
0
| while (outer != null) { result = IterUtil.compose(outer, result); outer = outer.declaringClass(); }
|
|
27 |
9025
| return result;
|
|
28 |
| } |
|
29 |
| |
|
30 |
| |
|
31 |
0
| public static DJClass outermostClass(DJClass c) {
|
|
32 |
0
| DJClass result = c;
|
|
33 |
0
| DJClass outer = c.declaringClass();
|
|
34 |
0
| while (outer != null) { result = outer; outer = outer.declaringClass(); }
|
|
35 |
0
| return result;
|
|
36 |
| } |
|
37 |
| |
|
38 |
| |
|
39 |
| |
|
40 |
| |
|
41 |
| |
|
42 |
| |
|
43 |
22
| public static boolean dynamicallyEncloses(DJClass outer, DJClass inner) {
|
|
44 |
22
| DJClass c = inner;
|
|
45 |
22
| boolean nextIsStatic = false;
|
|
46 |
22
| while (c != null) {
|
|
47 |
22
| if (c.equals(outer)) { return !nextIsStatic; }
|
|
48 |
0
| nextIsStatic = c.isStatic();
|
|
49 |
0
| c = c.declaringClass();
|
|
50 |
| } |
|
51 |
0
| return false;
|
|
52 |
| } |
|
53 |
| |
|
54 |
| |
|
55 |
| |
|
56 |
| |
|
57 |
| |
|
58 |
| |
|
59 |
| |
|
60 |
| |
|
61 |
1972
| public static DJClass dynamicOuterClass(DJClass c) {
|
|
62 |
1972
| DJClass inner = c;
|
|
63 |
0
| while (inner != null && inner.isStatic()) { inner = inner.declaringClass(); }
|
|
64 |
1972
| return (inner == null) ? null : inner.declaringClass();
|
|
65 |
| } |
|
66 |
| |
|
67 |
| |
|
68 |
| |
|
69 |
| |
|
70 |
| |
|
71 |
| |
|
72 |
700
| public static ClassType dynamicOuterClassType(ClassType t) {
|
|
73 |
700
| final DJClass outer = dynamicOuterClass(t.ofClass());
|
|
74 |
700
| if (outer == null) { return null; }
|
|
75 |
| else { |
|
76 |
0
| return t.apply(new TypeAbstractVisitor<ClassType>() {
|
|
77 |
0
| public ClassType defaultCase(Type t) { throw new RuntimeException(); }
|
|
78 |
0
| @Override public ClassType forSimpleClassType(SimpleClassType t) {
|
|
79 |
0
| return new SimpleClassType(outer);
|
|
80 |
| } |
|
81 |
0
| @Override public ClassType forRawClassType(RawClassType t) {
|
|
82 |
0
| Iterable<VariableType> outerParams = allTypeParameters(outer);
|
|
83 |
0
| if (IterUtil.isEmpty(outerParams)) { return new SimpleClassType(outer); }
|
|
84 |
0
| else { return new RawClassType(outer); }
|
|
85 |
| } |
|
86 |
0
| @Override public ClassType forParameterizedClassType(ParameterizedClassType t) {
|
|
87 |
0
| Iterable<VariableType> outerParams = allTypeParameters(outer);
|
|
88 |
0
| if (IterUtil.isEmpty(outerParams)) { return new SimpleClassType(outer); }
|
|
89 |
| else { |
|
90 |
0
| Iterable<Type> targs = IterUtil.truncate(t.typeArguments(), IterUtil.sizeOf(outerParams));
|
|
91 |
0
| return new ParameterizedClassType(outer, targs);
|
|
92 |
| } |
|
93 |
| } |
|
94 |
| }); |
|
95 |
| } |
|
96 |
| } |
|
97 |
| |
|
98 |
| |
|
99 |
| |
|
100 |
| |
|
101 |
| |
|
102 |
8506
| public static Iterable<VariableType> allTypeParameters(DJClass c) {
|
|
103 |
8506
| Iterable<VariableType> result = IterUtil.empty();
|
|
104 |
8506
| Iterable<VariableType> enclosing = IterUtil.empty();
|
|
105 |
8506
| for (DJClass cl : outerClassChain(c)) {
|
|
106 |
8506
| if (!cl.isStatic()) { result = IterUtil.compose(result, enclosing); }
|
|
107 |
| |
|
108 |
8506
| enclosing = cl.declaredTypeParameters();
|
|
109 |
| } |
|
110 |
8506
| result = IterUtil.compose(result, enclosing);
|
|
111 |
8506
| return result;
|
|
112 |
| } |
|
113 |
| |
|
114 |
| |
|
115 |
| |
|
116 |
| |
|
117 |
| |
|
118 |
| |
|
119 |
142
| public static String shortName(DJClass c) {
|
|
120 |
142
| StringBuilder result = new StringBuilder();
|
|
121 |
142
| boolean first = true;
|
|
122 |
142
| for (DJClass outer : outerClassChain(c)) {
|
|
123 |
0
| if (!first) { result.append('.'); }
|
|
124 |
142
| first = false;
|
|
125 |
142
| if (outer.isAnonymous()) {
|
|
126 |
0
| result.append("(anonymous ");
|
|
127 |
0
| Iterable<Type> supers = outer.declaredSupertypes();
|
|
128 |
0
| try {
|
|
129 |
0
| ClassType superClassT = (ClassType) IterUtil.first(supers);
|
|
130 |
0
| result.append(shortName(superClassT.ofClass()));
|
|
131 |
| } |
|
132 |
0
| catch (RuntimeException e) { result.append("Object"); }
|
|
133 |
0
| result.append(')');
|
|
134 |
| } |
|
135 |
142
| else { result.append(outer.declaredName()); }
|
|
136 |
| } |
|
137 |
142
| return result.toString();
|
|
138 |
| } |
|
139 |
| |
|
140 |
| |
|
141 |
| |
|
142 |
1483
| public static ClassType thisType(DJClass c) {
|
|
143 |
1483
| Iterable<VariableType> vars = allTypeParameters(c);
|
|
144 |
1056
| if (IterUtil.isEmpty(vars)) { return new SimpleClassType(c); }
|
|
145 |
427
| else { return new ParameterizedClassType(c, vars); }
|
|
146 |
| } |
|
147 |
| |
|
148 |
| |
|
149 |
| |
|
150 |
| |
|
151 |
| |
|
152 |
112
| public static DJClass wrapClass(Class<?> c) {
|
|
153 |
112
| if (JavaVersion.CURRENT.supports(JavaVersion.JAVA_5)) {
|
|
154 |
112
| try {
|
|
155 |
112
| return (DJClass) ReflectUtil.loadObject(DJClass.class.getClassLoader(),
|
|
156 |
| "edu.rice.cs.dynamicjava.symbol.Java5Class", c); |
|
157 |
| } |
|
158 |
0
| catch (ReflectException e) { throw new RuntimeException("Unable to create a Java5Class"); }
|
|
159 |
| } |
|
160 |
0
| else { return new JavaClass(c); }
|
|
161 |
| } |
|
162 |
| |
|
163 |
| |
|
164 |
| |
|
165 |
| |
|
166 |
| |
|
167 |
183
| public static Library classLibrary(ClassLoader loader) {
|
|
168 |
183
| if (JavaVersion.CURRENT.supports(JavaVersion.JAVA_5)) {
|
|
169 |
183
| try {
|
|
170 |
183
| return (Library) ReflectUtil.loadObject(Library.class.getClassLoader(), Java5Library.class.getName(),
|
|
171 |
| new Class<?>[]{ ClassLoader.class }, loader); |
|
172 |
| } |
|
173 |
| catch (ReflectException e) { |
|
174 |
0
| debug.log(e);
|
|
175 |
0
| throw new RuntimeException("Unable to create a Java5Library");
|
|
176 |
| } |
|
177 |
| } |
|
178 |
0
| else { return new JavaLibrary(loader); }
|
|
179 |
| } |
|
180 |
| |
|
181 |
| |
|
182 |
| |
|
183 |
| |
|
184 |
| |
|
185 |
| |
|
186 |
970
| public static Type typeOfPrimitiveClass(Class<?> c) {
|
|
187 |
181
| if (c.equals(boolean.class)) { return TypeSystem.BOOLEAN; }
|
|
188 |
549
| else if (c.equals(int.class)) { return TypeSystem.INT; }
|
|
189 |
84
| else if (c.equals(double.class)) { return TypeSystem.DOUBLE; }
|
|
190 |
13
| else if (c.equals(char.class)) { return TypeSystem.CHAR; }
|
|
191 |
76
| else if (c.equals(void.class)) { return TypeSystem.VOID; }
|
|
192 |
10
| else if (c.equals(long.class)) { return TypeSystem.LONG; }
|
|
193 |
5
| else if (c.equals(byte.class)) { return TypeSystem.BYTE; }
|
|
194 |
5
| else if (c.equals(short.class)) { return TypeSystem.SHORT; }
|
|
195 |
47
| else if (c.equals(float.class)) { return TypeSystem.FLOAT; }
|
|
196 |
0
| else { throw new IllegalArgumentException("Unrecognized primitive: " + c); }
|
|
197 |
| } |
|
198 |
| |
|
199 |
| |
|
200 |
| |
|
201 |
| |
|
202 |
| |
|
203 |
| |
|
204 |
0
| public static Type typeOfGeneralClass(Class<?> c, TypeSystem ts) {
|
|
205 |
0
| if (c.isPrimitive()) { return typeOfPrimitiveClass(c); }
|
|
206 |
0
| else if (c.isArray()) { return new SimpleArrayType(typeOfGeneralClass(c.getComponentType(), ts)); }
|
|
207 |
0
| else { return ts.makeClassType(wrapClass(c)); }
|
|
208 |
| } |
|
209 |
| |
|
210 |
| |
|
211 |
77
| public static Thunk<Class<?>> arrayClassThunk(final Thunk<Class<?>> element) {
|
|
212 |
77
| return new Thunk<Class<?>>() {
|
|
213 |
67
| public Class<?> value() { return Array.newInstance(element.value(), 0).getClass(); }
|
|
214 |
| }; |
|
215 |
| } |
|
216 |
| |
|
217 |
| |
|
218 |
| |
|
219 |
| |
|
220 |
| |
|
221 |
469
| public static Object initialValue(Class<?> c) {
|
|
222 |
469
| if (c.isPrimitive()) {
|
|
223 |
49
| if (c.equals(boolean.class)) { return Boolean.FALSE; }
|
|
224 |
72
| else if (c.equals(int.class)) { return Integer.valueOf(0); }
|
|
225 |
7
| else if (c.equals(double.class)) { return Double.valueOf(0.0); }
|
|
226 |
5
| else if (c.equals(char.class)) { return Character.valueOf('\u0000'); }
|
|
227 |
143
| else if (c.equals(void.class)) { return null; }
|
|
228 |
3
| else if (c.equals(long.class)) { return Long.valueOf(0l); }
|
|
229 |
3
| else if (c.equals(byte.class)) { return Byte.valueOf((byte) 0); }
|
|
230 |
3
| else if (c.equals(short.class)) { return Short.valueOf((short) 0); }
|
|
231 |
15
| else if (c.equals(float.class)) { return Float.valueOf(0.0f); }
|
|
232 |
0
| else { throw new IllegalArgumentException("Unrecognized primitive: " + c); }
|
|
233 |
| } |
|
234 |
169
| else { return null; }
|
|
235 |
| } |
|
236 |
| |
|
237 |
2348
| public static Iterable<Type> parameterTypes(Function f) {
|
|
238 |
2348
| return IterUtil.map(f.parameters(), TYPE_OF_VARIABLE);
|
|
239 |
| } |
|
240 |
| |
|
241 |
| private static final Lambda<Variable, Type> TYPE_OF_VARIABLE = new Lambda<Variable, Type>() { |
|
242 |
2094
| public Type value(Variable v) { return v.type(); }
|
|
243 |
| }; |
|
244 |
| |
|
245 |
| |
|
246 |
10
| public static boolean isVararg(Function f) {
|
|
247 |
10
| Iterable<LocalVariable> params = f.parameters();
|
|
248 |
10
| return !IterUtil.isEmpty(params) && (IterUtil.last(params).type() instanceof VarargArrayType);
|
|
249 |
| } |
|
250 |
| |
|
251 |
| } |