Mercurial > hg > graal-compiler
comparison graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/TypeSystemCodeGenerator.java @ 18758:3912400fc33a
Truffle-DSL: remove type system singleton
author | Christian Humer <christian.humer@gmail.com> |
---|---|
date | Mon, 29 Dec 2014 23:38:42 +0100 |
parents | f6b8787dc113 |
children | a665483c3881 |
comparison
equal
deleted
inserted
replaced
18757:0ec5f5a2e720 | 18758:3912400fc33a |
---|---|
34 import com.oracle.truffle.dsl.processor.java.model.*; | 34 import com.oracle.truffle.dsl.processor.java.model.*; |
35 import com.oracle.truffle.dsl.processor.model.*; | 35 import com.oracle.truffle.dsl.processor.model.*; |
36 | 36 |
37 public class TypeSystemCodeGenerator extends CodeTypeElementFactory<TypeSystemData> { | 37 public class TypeSystemCodeGenerator extends CodeTypeElementFactory<TypeSystemData> { |
38 | 38 |
39 public static CodeTree cast(TypeData type, String content) { | |
40 return cast(type, CodeTreeBuilder.singleString(content)); | |
41 } | |
42 | |
43 public static CodeTree implicitType(TypeData type, String valueName) { | |
44 if (type.isGeneric()) { | |
45 return CodeTreeBuilder.singleString(valueName); | |
46 } | |
47 CodeTreeBuilder builder = CodeTreeBuilder.createBuilder(); | |
48 TypeSystemData typeSystem = type.getTypeSystem(); | |
49 builder.startStaticCall(createTypeSystemGen(typeSystem), getImplicitClass(type)).string(valueName); | |
50 builder.end(); | |
51 return builder.getRoot(); | |
52 } | |
53 | |
54 public static CodeTree invokeImplicitCast(ImplicitCastData cast, CodeTree expression) { | |
55 CodeTreeBuilder builder = CodeTreeBuilder.createBuilder(); | |
56 TypeSystemData typeSystem = cast.getTargetType().getTypeSystem(); | |
57 builder.startStaticCall(createTypeSystemGen(typeSystem), cast.getMethodName()).tree(expression); | |
58 builder.end(); | |
59 return builder.getRoot(); | |
60 } | |
61 | |
62 public static CodeTree implicitCheck(TypeData type, String valueName, String typeHint) { | |
63 if (type.isGeneric()) { | |
64 return CodeTreeBuilder.singleString(valueName); | |
65 } | |
66 CodeTreeBuilder builder = CodeTreeBuilder.createBuilder(); | |
67 TypeSystemData typeSystem = type.getTypeSystem(); | |
68 builder.startStaticCall(createTypeSystemGen(typeSystem), isImplicitTypeMethodName(type)).string(valueName); | |
69 if (typeHint != null) { | |
70 builder.string(typeHint); | |
71 } | |
72 builder.end(); | |
73 return builder.getRoot(); | |
74 } | |
75 | |
76 public static CodeTree implicitCast(TypeData type, String valueName, String typeHint) { | |
77 if (type.isGeneric()) { | |
78 return CodeTreeBuilder.singleString(valueName); | |
79 } | |
80 CodeTreeBuilder builder = CodeTreeBuilder.createBuilder(); | |
81 TypeSystemData typeSystem = type.getTypeSystem(); | |
82 builder.startStaticCall(createTypeSystemGen(typeSystem), asImplicitTypeMethodName(type)).string(valueName); | |
83 if (typeHint != null) { | |
84 builder.string(typeHint); | |
85 } | |
86 builder.end(); | |
87 return builder.getRoot(); | |
88 } | |
89 | |
90 public static CodeTree cast(TypeData type, CodeTree content) { | |
91 if (type.isGeneric()) { | |
92 return content; | |
93 } | |
94 CodeTreeBuilder builder = CodeTreeBuilder.createBuilder(); | |
95 TypeSystemData typeSystem = type.getTypeSystem(); | |
96 | |
97 if (type.isDefaultCast()) { | |
98 builder.cast(type.getPrimitiveType(), content); | |
99 } else { | |
100 builder.startStaticCall(typeSystem.getTemplateType().asType(), type.getTypeCasts().get(0).getMethodName()).tree(content).end(); | |
101 } | |
102 return builder.getRoot(); | |
103 } | |
104 | |
105 public static CodeTree expect(TypeData type, CodeTree content) { | |
106 if (type.isGeneric()) { | |
107 return content; | |
108 } | |
109 CodeTreeBuilder builder = CodeTreeBuilder.createBuilder(); | |
110 TypeSystemData typeSystem = type.getTypeSystem(); | |
111 builder.startStaticCall(createTypeSystemGen(typeSystem), expectTypeMethodName(type)).tree(content).end(); | |
112 return builder.getRoot(); | |
113 } | |
114 | |
115 private static CodeTypeMirror createTypeSystemGen(TypeSystemData typeSystem) { | |
116 return new GeneratedTypeMirror(ElementUtils.getPackageName(typeSystem.getTemplateType()), typeName(typeSystem)); | |
117 } | |
118 | |
119 public static CodeTree check(TypeData type, String content) { | |
120 return check(type, CodeTreeBuilder.singleString(content)); | |
121 } | |
122 | |
123 public static CodeTree check(TypeData type, CodeTree content) { | |
124 if (type.isGeneric()) { | |
125 return content; | |
126 } | |
127 CodeTreeBuilder builder = CodeTreeBuilder.createBuilder(); | |
128 TypeSystemData typeSystem = type.getTypeSystem(); | |
129 | |
130 if (type.isDefaultCheck()) { | |
131 builder.instanceOf(content, type.getBoxedType()); | |
132 } else { | |
133 builder.startStaticCall(typeSystem.getTemplateType().asType(), type.getTypeChecks().get(0).getMethodName()).tree(content).end(); | |
134 } | |
135 return builder.getRoot(); | |
136 } | |
137 | |
39 public static String isTypeMethodName(TypeData type) { | 138 public static String isTypeMethodName(TypeData type) { |
40 return "is" + ElementUtils.getTypeId(type.getBoxedType()); | 139 return "is" + ElementUtils.getTypeId(type.getBoxedType()); |
41 } | 140 } |
42 | 141 |
43 static String isImplicitTypeMethodName(TypeData type) { | 142 static String isImplicitTypeMethodName(TypeData type) { |
122 sourceTypes.add(cast.getSourceType()); | 221 sourceTypes.add(cast.getSourceType()); |
123 } | 222 } |
124 for (TypeCheckData cast : type.getTypeChecks()) { | 223 for (TypeCheckData cast : type.getTypeChecks()) { |
125 sourceTypes.add(cast.getCheckedType()); | 224 sourceTypes.add(cast.getCheckedType()); |
126 } | 225 } |
226 sourceTypes.remove(type); | |
127 return new ArrayList<>(sourceTypes); | 227 return new ArrayList<>(sourceTypes); |
128 } | 228 } |
129 | 229 |
130 private CodeVariableElement createSingleton(CodeTypeElement clazz) { | 230 private CodeVariableElement createSingleton(CodeTypeElement clazz) { |
131 CodeVariableElement field = new CodeVariableElement(modifiers(PUBLIC, STATIC, FINAL), clazz.asType(), singletonName(typeSystem)); | 231 CodeVariableElement field = new CodeVariableElement(modifiers(PUBLIC, STATIC, FINAL), clazz.asType(), singletonName(typeSystem)); |
132 field.createInitBuilder().startNew(clazz.asType()).end(); | 232 field.createInitBuilder().startNew(clazz.asType()).end(); |
233 | |
234 CodeAnnotationMirror annotationMirror = new CodeAnnotationMirror((DeclaredType) context.getType(Deprecated.class)); | |
235 field.getAnnotationMirrors().add(annotationMirror); | |
236 | |
133 return field; | 237 return field; |
134 } | 238 } |
135 | 239 |
136 private CodeExecutableElement createIsImplicitTypeMethod(TypeData type, boolean typed) { | 240 private CodeExecutableElement createIsImplicitTypeMethod(TypeData type, boolean typed) { |
137 List<ImplicitCastData> casts = typeSystem.lookupByTargetType(type); | 241 List<ImplicitCastData> casts = typeSystem.lookupByTargetType(type); |
138 if (casts.isEmpty()) { | 242 if (casts.isEmpty()) { |
139 return null; | 243 return null; |
140 } | 244 } |
141 CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), context.getType(boolean.class), TypeSystemCodeGenerator.isImplicitTypeMethodName(type)); | 245 CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, STATIC), context.getType(boolean.class), TypeSystemCodeGenerator.isImplicitTypeMethodName(type)); |
142 method.addParameter(new CodeVariableElement(context.getType(Object.class), LOCAL_VALUE)); | 246 method.addParameter(new CodeVariableElement(context.getType(Object.class), LOCAL_VALUE)); |
143 if (typed) { | 247 if (typed) { |
144 method.addParameter(new CodeVariableElement(context.getType(Class.class), "typeHint")); | 248 method.addParameter(new CodeVariableElement(context.getType(Class.class), "typeHint")); |
145 } | 249 } |
146 CodeTreeBuilder builder = method.createBuilder(); | 250 CodeTreeBuilder builder = method.createBuilder(); |
152 for (TypeData sourceType : sourceTypes) { | 256 for (TypeData sourceType : sourceTypes) { |
153 builder.string(sep); | 257 builder.string(sep); |
154 if (typed) { | 258 if (typed) { |
155 builder.string("(typeHint == ").typeLiteral(sourceType.getPrimitiveType()).string(" && "); | 259 builder.string("(typeHint == ").typeLiteral(sourceType.getPrimitiveType()).string(" && "); |
156 } | 260 } |
157 builder.startCall(isTypeMethodName(sourceType)).string(LOCAL_VALUE).end(); | 261 builder.tree(check(sourceType, LOCAL_VALUE)); |
158 if (typed) { | 262 if (typed) { |
159 builder.string(")"); | 263 builder.string(")"); |
160 } | 264 } |
161 if (sourceTypes.lastIndexOf(sourceType) != sourceTypes.size() - 1) { | 265 if (sourceTypes.lastIndexOf(sourceType) != sourceTypes.size() - 1) { |
162 builder.newLine(); | 266 builder.newLine(); |
174 private CodeExecutableElement createAsImplicitTypeMethod(TypeData type, boolean typed) { | 278 private CodeExecutableElement createAsImplicitTypeMethod(TypeData type, boolean typed) { |
175 List<ImplicitCastData> casts = typeSystem.lookupByTargetType(type); | 279 List<ImplicitCastData> casts = typeSystem.lookupByTargetType(type); |
176 if (casts.isEmpty()) { | 280 if (casts.isEmpty()) { |
177 return null; | 281 return null; |
178 } | 282 } |
179 CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), type.getPrimitiveType(), TypeSystemCodeGenerator.asImplicitTypeMethodName(type)); | 283 CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, STATIC), type.getPrimitiveType(), TypeSystemCodeGenerator.asImplicitTypeMethodName(type)); |
180 method.addParameter(new CodeVariableElement(context.getType(Object.class), LOCAL_VALUE)); | 284 method.addParameter(new CodeVariableElement(context.getType(Object.class), LOCAL_VALUE)); |
181 if (typed) { | 285 if (typed) { |
182 method.addParameter(new CodeVariableElement(context.getType(Class.class), "typeHint")); | 286 method.addParameter(new CodeVariableElement(context.getType(Class.class), "typeHint")); |
183 } | 287 } |
184 | 288 |
189 for (TypeData sourceType : sourceTypes) { | 293 for (TypeData sourceType : sourceTypes) { |
190 elseIf = builder.startIf(elseIf); | 294 elseIf = builder.startIf(elseIf); |
191 if (typed) { | 295 if (typed) { |
192 builder.string("typeHint == ").typeLiteral(sourceType.getPrimitiveType()); | 296 builder.string("typeHint == ").typeLiteral(sourceType.getPrimitiveType()); |
193 } else { | 297 } else { |
194 builder.startCall(isTypeMethodName(sourceType)).string(LOCAL_VALUE).end(); | 298 builder.tree(check(sourceType, LOCAL_VALUE)); |
195 } | 299 } |
196 | 300 |
197 builder.end().startBlock(); | 301 builder.end().startBlock(); |
198 | 302 |
199 builder.startReturn(); | 303 builder.startReturn(); |
200 ImplicitCastData cast = typeSystem.lookupCast(sourceType, type); | 304 ImplicitCastData cast = typeSystem.lookupCast(sourceType, type); |
201 if (cast != null) { | 305 if (cast != null) { |
202 builder.startCall(cast.getMethodName()); | 306 builder.startCall(cast.getMethodName()); |
203 } | 307 } |
204 builder.startCall(asTypeMethodName(sourceType)).string(LOCAL_VALUE).end(); | 308 builder.tree(cast(sourceType, LOCAL_VALUE)).end(); |
205 if (cast != null) { | 309 if (cast != null) { |
206 builder.end(); | 310 builder.end(); |
207 } | 311 } |
208 builder.end(); | 312 builder.end(); |
209 builder.end(); | 313 builder.end(); |
219 private CodeExecutableElement createGetTypeIndex(TypeData type) { | 323 private CodeExecutableElement createGetTypeIndex(TypeData type) { |
220 List<ImplicitCastData> casts = typeSystem.lookupByTargetType(type); | 324 List<ImplicitCastData> casts = typeSystem.lookupByTargetType(type); |
221 if (casts.isEmpty()) { | 325 if (casts.isEmpty()) { |
222 return null; | 326 return null; |
223 } | 327 } |
224 CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), context.getType(Class.class), TypeSystemCodeGenerator.getImplicitClass(type)); | 328 CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, STATIC), context.getType(Class.class), TypeSystemCodeGenerator.getImplicitClass(type)); |
225 method.addParameter(new CodeVariableElement(context.getType(Object.class), LOCAL_VALUE)); | 329 method.addParameter(new CodeVariableElement(context.getType(Object.class), LOCAL_VALUE)); |
226 | 330 |
227 List<TypeData> sourceTypes = typeSystem.lookupSourceTypes(type); | 331 List<TypeData> sourceTypes = typeSystem.lookupSourceTypes(type); |
228 CodeTreeBuilder builder = method.createBuilder(); | 332 CodeTreeBuilder builder = method.createBuilder(); |
229 boolean elseIf = false; | 333 boolean elseIf = false; |
230 for (TypeData sourceType : sourceTypes) { | 334 for (TypeData sourceType : sourceTypes) { |
231 elseIf = builder.startIf(elseIf); | 335 elseIf = builder.startIf(elseIf); |
232 builder.startCall(isTypeMethodName(sourceType)).string(LOCAL_VALUE).end(); | 336 builder.tree(check(sourceType, LOCAL_VALUE)).end(); |
233 builder.end().startBlock(); | 337 builder.end().startBlock(); |
234 builder.startReturn().typeLiteral(sourceType.getPrimitiveType()).end(); | 338 builder.startReturn().typeLiteral(sourceType.getPrimitiveType()).end(); |
235 builder.end(); | 339 builder.end(); |
236 } | 340 } |
237 | 341 |
246 private CodeExecutableElement createIsTypeMethod(TypeData type) { | 350 private CodeExecutableElement createIsTypeMethod(TypeData type) { |
247 if (!type.getTypeChecks().isEmpty()) { | 351 if (!type.getTypeChecks().isEmpty()) { |
248 return null; | 352 return null; |
249 } | 353 } |
250 | 354 |
251 CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), context.getType(boolean.class), TypeSystemCodeGenerator.isTypeMethodName(type)); | 355 CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, STATIC), context.getType(boolean.class), TypeSystemCodeGenerator.isTypeMethodName(type)); |
252 method.addParameter(new CodeVariableElement(context.getType(Object.class), LOCAL_VALUE)); | 356 method.addParameter(new CodeVariableElement(context.getType(Object.class), LOCAL_VALUE)); |
253 | |
254 DeclaredType suppressWarnings = (DeclaredType) context.getType(SuppressWarnings.class); | |
255 CodeAnnotationMirror annotationMirror = new CodeAnnotationMirror(suppressWarnings); | |
256 annotationMirror.setElementValue(annotationMirror.findExecutableElement("value"), new CodeAnnotationValue("static-method")); | |
257 method.getAnnotationMirrors().add(annotationMirror); | |
258 | 357 |
259 CodeTreeBuilder body = method.createBuilder(); | 358 CodeTreeBuilder body = method.createBuilder(); |
260 body.startReturn().instanceOf(LOCAL_VALUE, type.getBoxedType()).end(); | 359 body.startReturn().tree(check(type, LOCAL_VALUE)).end(); |
261 | 360 |
262 return method; | 361 return method; |
263 } | 362 } |
264 | 363 |
265 private CodeExecutableElement createAsTypeMethod(TypeData type) { | 364 private CodeExecutableElement createAsTypeMethod(TypeData type) { |
266 if (!type.getTypeCasts().isEmpty()) { | 365 if (!type.getTypeCasts().isEmpty()) { |
267 return null; | 366 return null; |
268 } | 367 } |
269 | 368 |
270 CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), type.getPrimitiveType(), TypeSystemCodeGenerator.asTypeMethodName(type)); | 369 CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, STATIC), type.getPrimitiveType(), TypeSystemCodeGenerator.asTypeMethodName(type)); |
271 method.addParameter(new CodeVariableElement(context.getType(Object.class), LOCAL_VALUE)); | 370 method.addParameter(new CodeVariableElement(context.getType(Object.class), LOCAL_VALUE)); |
272 | 371 |
273 CodeTreeBuilder body = method.createBuilder(); | 372 CodeTreeBuilder body = method.createBuilder(); |
274 String assertMessage = typeName(typeSystem) + "." + asTypeMethodName(type) + ": " + ElementUtils.getSimpleName(type.getBoxedType()) + " expected"; | 373 String assertMessage = typeName(typeSystem) + "." + asTypeMethodName(type) + ": " + ElementUtils.getSimpleName(type.getBoxedType()) + " expected"; |
275 body.startAssert().startCall(isTypeMethodName(type)).string(LOCAL_VALUE).end().string(" : ").doubleQuote(assertMessage).end(); | 374 body.startAssert().tree(check(type, LOCAL_VALUE)).string(" : ").doubleQuote(assertMessage).end(); |
276 body.startReturn().cast(type.getPrimitiveType(), body.create().string(LOCAL_VALUE).getTree()).end(); | 375 body.startReturn().tree(cast(type, LOCAL_VALUE)).end(); |
277 | 376 |
278 return method; | 377 return method; |
279 } | 378 } |
280 | 379 |
281 private CodeExecutableElement createExpectTypeMethod(TypeData expectedType, TypeData sourceType) { | 380 private CodeExecutableElement createExpectTypeMethod(TypeData expectedType, TypeData sourceType) { |
282 CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), expectedType.getPrimitiveType(), TypeSystemCodeGenerator.expectTypeMethodName(expectedType)); | 381 CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, STATIC), expectedType.getPrimitiveType(), TypeSystemCodeGenerator.expectTypeMethodName(expectedType)); |
283 method.addParameter(new CodeVariableElement(sourceType.getPrimitiveType(), LOCAL_VALUE)); | 382 method.addParameter(new CodeVariableElement(sourceType.getPrimitiveType(), LOCAL_VALUE)); |
284 method.addThrownType(context.getTruffleTypes().getUnexpectedValueException()); | 383 method.addThrownType(context.getTruffleTypes().getUnexpectedValueException()); |
285 | 384 |
286 CodeTreeBuilder body = method.createBuilder(); | 385 CodeTreeBuilder body = method.createBuilder(); |
287 body.startIf().startCall(TypeSystemCodeGenerator.isTypeMethodName(expectedType)).string(LOCAL_VALUE).end().end().startBlock(); | 386 body.startIf().tree(check(expectedType, LOCAL_VALUE)).end().startBlock(); |
288 body.startReturn().startCall(TypeSystemCodeGenerator.asTypeMethodName(expectedType)).string(LOCAL_VALUE).end().end(); | 387 body.startReturn().tree(cast(expectedType, LOCAL_VALUE)).end().end(); |
289 body.end(); // if-block | 388 body.end(); // if-block |
290 body.startThrow().startNew(context.getTruffleTypes().getUnexpectedValueException()).string(LOCAL_VALUE).end().end(); | 389 body.startThrow().startNew(context.getTruffleTypes().getUnexpectedValueException()).string(LOCAL_VALUE).end().end(); |
291 | 390 |
292 return method; | 391 return method; |
293 } | 392 } |
294 | 393 |
295 } | 394 } |
395 | |
296 } | 396 } |