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 }