Mercurial > hg > graal-jvmci-8
comparison graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/TypeSystemCodeGenerator.java @ 16759:23415229349b
Truffle-DSL: new package structure.
author | Christian Humer <christian.humer@gmail.com> |
---|---|
date | Mon, 11 Aug 2014 15:57:14 +0200 |
parents | graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeSystemCodeGenerator.java@bd28da642eea |
children | 0370880ac9ce |
comparison
equal
deleted
inserted
replaced
16758:c5f8eeb3cbc8 | 16759:23415229349b |
---|---|
1 /* | |
2 * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. | |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
4 * | |
5 * This code is free software; you can redistribute it and/or modify it | |
6 * under the terms of the GNU General Public License version 2 only, as | |
7 * published by the Free Software Foundation. | |
8 * | |
9 * This code is distributed in the hope that it will be useful, but WITHOUT | |
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
12 * version 2 for more details (a copy is included in the LICENSE file that | |
13 * accompanied this code). | |
14 * | |
15 * You should have received a copy of the GNU General Public License version | |
16 * 2 along with this work; if not, write to the Free Software Foundation, | |
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
18 * | |
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
20 * or visit www.oracle.com if you need additional information or have any | |
21 * questions. | |
22 */ | |
23 package com.oracle.truffle.dsl.processor.generator; | |
24 | |
25 import static com.oracle.truffle.dsl.processor.java.ElementUtils.*; | |
26 import static javax.lang.model.element.Modifier.*; | |
27 | |
28 import java.util.*; | |
29 | |
30 import javax.lang.model.type.*; | |
31 | |
32 import com.oracle.truffle.dsl.processor.java.*; | |
33 import com.oracle.truffle.dsl.processor.java.model.*; | |
34 import com.oracle.truffle.dsl.processor.model.*; | |
35 | |
36 public class TypeSystemCodeGenerator extends AbstractCompilationUnitFactory<TypeSystemData> { | |
37 | |
38 public static String isTypeMethodName(TypeData type) { | |
39 return "is" + ElementUtils.getTypeId(type.getBoxedType()); | |
40 } | |
41 | |
42 public static String isImplicitTypeMethodName(TypeData type) { | |
43 return "isImplicit" + ElementUtils.getTypeId(type.getBoxedType()); | |
44 } | |
45 | |
46 public static String asTypeMethodName(TypeData type) { | |
47 return "as" + ElementUtils.getTypeId(type.getBoxedType()); | |
48 } | |
49 | |
50 public static String asImplicitTypeMethodName(TypeData type) { | |
51 return "asImplicit" + ElementUtils.getTypeId(type.getBoxedType()); | |
52 } | |
53 | |
54 public static String getImplicitClass(TypeData type) { | |
55 return "getImplicit" + ElementUtils.getTypeId(type.getBoxedType()) + "Class"; | |
56 } | |
57 | |
58 public static String expectTypeMethodName(TypeData type) { | |
59 return "expect" + ElementUtils.getTypeId(type.getBoxedType()); | |
60 } | |
61 | |
62 public static String typeName(TypeSystemData typeSystem) { | |
63 String name = getSimpleName(typeSystem.getTemplateType()); | |
64 return name + "Gen"; | |
65 } | |
66 | |
67 public static String singletonName(TypeSystemData type) { | |
68 return createConstantName(getSimpleName(type.getTemplateType().asType())); | |
69 } | |
70 | |
71 @Override | |
72 protected void createChildren(TypeSystemData m) { | |
73 add(new TypeClassFactory(), m); | |
74 } | |
75 | |
76 private static class TypeClassFactory extends AbstractClassElementFactory<TypeSystemData> { | |
77 | |
78 private static final String LOCAL_VALUE = "value"; | |
79 | |
80 @Override | |
81 public CodeTypeElement create(TypeSystemData typeSystem) { | |
82 String name = typeName(typeSystem); | |
83 CodeTypeElement clazz = createClass(typeSystem, modifiers(PUBLIC, FINAL), name, typeSystem.getTemplateType().asType(), false); | |
84 | |
85 clazz.add(createConstructorUsingFields(modifiers(PROTECTED), clazz)); | |
86 CodeVariableElement singleton = createSingleton(clazz); | |
87 clazz.add(singleton); | |
88 | |
89 for (TypeData type : typeSystem.getTypes()) { | |
90 if (!type.isGeneric()) { | |
91 clazz.addOptional(createIsTypeMethod(type)); | |
92 clazz.addOptional(createAsTypeMethod(type)); | |
93 | |
94 for (TypeData sourceType : collectExpectSourceTypes(type)) { | |
95 clazz.addOptional(createExpectTypeMethod(type, sourceType)); | |
96 } | |
97 | |
98 clazz.addOptional(createAsImplicitTypeMethod(type, true)); | |
99 clazz.addOptional(createAsImplicitTypeMethod(type, false)); | |
100 clazz.addOptional(createIsImplicitTypeMethod(type, true)); | |
101 clazz.addOptional(createIsImplicitTypeMethod(type, false)); | |
102 clazz.addOptional(createGetTypeIndex(type)); | |
103 } | |
104 } | |
105 | |
106 return clazz; | |
107 } | |
108 | |
109 private static List<TypeData> collectExpectSourceTypes(TypeData type) { | |
110 Set<TypeData> sourceTypes = new HashSet<>(); | |
111 sourceTypes.add(type.getTypeSystem().getGenericTypeData()); | |
112 for (TypeCastData cast : type.getTypeCasts()) { | |
113 sourceTypes.add(cast.getSourceType()); | |
114 } | |
115 for (TypeCheckData cast : type.getTypeChecks()) { | |
116 sourceTypes.add(cast.getCheckedType()); | |
117 } | |
118 return new ArrayList<>(sourceTypes); | |
119 } | |
120 | |
121 private CodeVariableElement createSingleton(CodeTypeElement clazz) { | |
122 CodeVariableElement field = new CodeVariableElement(modifiers(PUBLIC, STATIC, FINAL), clazz.asType(), singletonName(getModel())); | |
123 field.createInitBuilder().startNew(clazz.asType()).end(); | |
124 return field; | |
125 } | |
126 | |
127 private CodeExecutableElement createIsImplicitTypeMethod(TypeData type, boolean typed) { | |
128 TypeSystemData typeSystem = getModel(); | |
129 List<ImplicitCastData> casts = typeSystem.lookupByTargetType(type); | |
130 if (casts.isEmpty()) { | |
131 return null; | |
132 } | |
133 CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), getContext().getType(boolean.class), TypeSystemCodeGenerator.isImplicitTypeMethodName(type)); | |
134 method.addParameter(new CodeVariableElement(getContext().getType(Object.class), LOCAL_VALUE)); | |
135 if (typed) { | |
136 method.addParameter(new CodeVariableElement(getContext().getType(Class.class), "typeHint")); | |
137 } | |
138 CodeTreeBuilder builder = method.createBuilder(); | |
139 | |
140 List<TypeData> sourceTypes = typeSystem.lookupSourceTypes(type); | |
141 | |
142 builder.startReturn(); | |
143 String sep = ""; | |
144 for (TypeData sourceType : sourceTypes) { | |
145 builder.string(sep); | |
146 if (typed) { | |
147 builder.string("(typeHint == ").typeLiteral(sourceType.getPrimitiveType()).string(" && "); | |
148 } | |
149 builder.startCall(isTypeMethodName(sourceType)).string(LOCAL_VALUE).end(); | |
150 if (typed) { | |
151 builder.string(")"); | |
152 } | |
153 if (sourceTypes.lastIndexOf(sourceType) != sourceTypes.size() - 1) { | |
154 builder.newLine(); | |
155 } | |
156 if (sep.equals("")) { | |
157 builder.startIndention(); | |
158 } | |
159 sep = " || "; | |
160 } | |
161 builder.end(); | |
162 builder.end(); | |
163 return method; | |
164 } | |
165 | |
166 private CodeExecutableElement createAsImplicitTypeMethod(TypeData type, boolean typed) { | |
167 TypeSystemData typeSystem = getModel(); | |
168 List<ImplicitCastData> casts = typeSystem.lookupByTargetType(type); | |
169 if (casts.isEmpty()) { | |
170 return null; | |
171 } | |
172 CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), type.getPrimitiveType(), TypeSystemCodeGenerator.asImplicitTypeMethodName(type)); | |
173 method.addParameter(new CodeVariableElement(getContext().getType(Object.class), LOCAL_VALUE)); | |
174 if (typed) { | |
175 method.addParameter(new CodeVariableElement(getContext().getType(Class.class), "typeHint")); | |
176 } | |
177 | |
178 List<TypeData> sourceTypes = typeSystem.lookupSourceTypes(type); | |
179 | |
180 CodeTreeBuilder builder = method.createBuilder(); | |
181 boolean elseIf = false; | |
182 for (TypeData sourceType : sourceTypes) { | |
183 elseIf = builder.startIf(elseIf); | |
184 if (typed) { | |
185 builder.string("typeHint == ").typeLiteral(sourceType.getPrimitiveType()); | |
186 } else { | |
187 builder.startCall(isTypeMethodName(sourceType)).string(LOCAL_VALUE).end(); | |
188 } | |
189 | |
190 builder.end().startBlock(); | |
191 | |
192 builder.startReturn(); | |
193 ImplicitCastData cast = typeSystem.lookupCast(sourceType, type); | |
194 if (cast != null) { | |
195 builder.startCall(cast.getMethodName()); | |
196 } | |
197 builder.startCall(asTypeMethodName(sourceType)).string(LOCAL_VALUE).end(); | |
198 if (cast != null) { | |
199 builder.end(); | |
200 } | |
201 builder.end(); | |
202 builder.end(); | |
203 } | |
204 | |
205 builder.startElseBlock(); | |
206 builder.startStatement().startStaticCall(getContext().getTruffleTypes().getCompilerDirectives(), "transferToInterpreterAndInvalidate").end().end(); | |
207 builder.startThrow().startNew(getContext().getType(IllegalArgumentException.class)).doubleQuote("Illegal type ").end().end(); | |
208 builder.end(); | |
209 return method; | |
210 } | |
211 | |
212 private CodeExecutableElement createGetTypeIndex(TypeData type) { | |
213 TypeSystemData typeSystem = getModel(); | |
214 List<ImplicitCastData> casts = typeSystem.lookupByTargetType(type); | |
215 if (casts.isEmpty()) { | |
216 return null; | |
217 } | |
218 CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), getContext().getType(Class.class), TypeSystemCodeGenerator.getImplicitClass(type)); | |
219 method.addParameter(new CodeVariableElement(getContext().getType(Object.class), LOCAL_VALUE)); | |
220 | |
221 List<TypeData> sourceTypes = typeSystem.lookupSourceTypes(type); | |
222 CodeTreeBuilder builder = method.createBuilder(); | |
223 boolean elseIf = false; | |
224 for (TypeData sourceType : sourceTypes) { | |
225 elseIf = builder.startIf(elseIf); | |
226 builder.startCall(isTypeMethodName(sourceType)).string(LOCAL_VALUE).end(); | |
227 builder.end().startBlock(); | |
228 builder.startReturn().typeLiteral(sourceType.getPrimitiveType()).end(); | |
229 builder.end(); | |
230 } | |
231 | |
232 builder.startElseBlock(); | |
233 builder.startStatement().startStaticCall(getContext().getTruffleTypes().getCompilerDirectives(), "transferToInterpreterAndInvalidate").end().end(); | |
234 builder.startThrow().startNew(getContext().getType(IllegalArgumentException.class)).doubleQuote("Illegal type ").end().end(); | |
235 builder.end(); | |
236 | |
237 return method; | |
238 } | |
239 | |
240 private CodeExecutableElement createIsTypeMethod(TypeData type) { | |
241 if (!type.getTypeChecks().isEmpty()) { | |
242 return null; | |
243 } | |
244 | |
245 CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), getContext().getType(boolean.class), TypeSystemCodeGenerator.isTypeMethodName(type)); | |
246 method.addParameter(new CodeVariableElement(getContext().getType(Object.class), LOCAL_VALUE)); | |
247 | |
248 DeclaredType suppressWarnings = (DeclaredType) getContext().getType(SuppressWarnings.class); | |
249 CodeAnnotationMirror annotationMirror = new CodeAnnotationMirror(suppressWarnings); | |
250 annotationMirror.setElementValue(annotationMirror.findExecutableElement("value"), new CodeAnnotationValue("static-method")); | |
251 method.getAnnotationMirrors().add(annotationMirror); | |
252 | |
253 CodeTreeBuilder body = method.createBuilder(); | |
254 body.startReturn().instanceOf(LOCAL_VALUE, type.getBoxedType()).end(); | |
255 | |
256 return method; | |
257 } | |
258 | |
259 private CodeExecutableElement createAsTypeMethod(TypeData type) { | |
260 if (!type.getTypeCasts().isEmpty()) { | |
261 return null; | |
262 } | |
263 | |
264 CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), type.getPrimitiveType(), TypeSystemCodeGenerator.asTypeMethodName(type)); | |
265 method.addParameter(new CodeVariableElement(getContext().getType(Object.class), LOCAL_VALUE)); | |
266 | |
267 CodeTreeBuilder body = method.createBuilder(); | |
268 String assertMessage = typeName(getModel()) + "." + asTypeMethodName(type) + ": " + ElementUtils.getSimpleName(type.getBoxedType()) + " expected"; | |
269 body.startAssert().startCall(isTypeMethodName(type)).string(LOCAL_VALUE).end().string(" : ").doubleQuote(assertMessage).end(); | |
270 body.startReturn().cast(type.getPrimitiveType(), body.create().string(LOCAL_VALUE).getTree()).end(); | |
271 | |
272 return method; | |
273 } | |
274 | |
275 private CodeExecutableElement createExpectTypeMethod(TypeData expectedType, TypeData sourceType) { | |
276 CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), expectedType.getPrimitiveType(), TypeSystemCodeGenerator.expectTypeMethodName(expectedType)); | |
277 method.addParameter(new CodeVariableElement(sourceType.getPrimitiveType(), LOCAL_VALUE)); | |
278 method.addThrownType(getContext().getTruffleTypes().getUnexpectedValueException()); | |
279 | |
280 CodeTreeBuilder body = method.createBuilder(); | |
281 body.startIf().startCall(TypeSystemCodeGenerator.isTypeMethodName(expectedType)).string(LOCAL_VALUE).end().end().startBlock(); | |
282 body.startReturn().startCall(TypeSystemCodeGenerator.asTypeMethodName(expectedType)).string(LOCAL_VALUE).end().end(); | |
283 body.end(); // if-block | |
284 body.startThrow().startNew(getContext().getTruffleTypes().getUnexpectedValueException()).string(LOCAL_VALUE).end().end(); | |
285 | |
286 return method; | |
287 } | |
288 | |
289 } | |
290 } |