Mercurial > hg > graal-compiler
comparison graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeParser.java @ 8245:703c09f8640c
Implemented support for @NodeClass annotation to support builtins.
author | Christian Humer <christian.humer@gmail.com> |
---|---|
date | Wed, 06 Mar 2013 18:32:33 +0100 |
parents | d81ff782fa1a |
children | c4c3f50fa9c2 |
comparison
equal
deleted
inserted
replaced
8244:10d37f893471 | 8245:703c09f8640c |
---|---|
42 public class NodeParser extends TemplateParser<NodeData> { | 42 public class NodeParser extends TemplateParser<NodeData> { |
43 | 43 |
44 public static final List<Class<? extends Annotation>> ANNOTATIONS = Arrays.asList(Generic.class, TypeSystemReference.class, ShortCircuit.class, Specialization.class, SpecializationListener.class); | 44 public static final List<Class<? extends Annotation>> ANNOTATIONS = Arrays.asList(Generic.class, TypeSystemReference.class, ShortCircuit.class, Specialization.class, SpecializationListener.class); |
45 | 45 |
46 private Map<String, NodeData> parsedNodes; | 46 private Map<String, NodeData> parsedNodes; |
47 private TypeElement originalType; | |
48 | 47 |
49 public NodeParser(ProcessorContext c) { | 48 public NodeParser(ProcessorContext c) { |
50 super(c); | 49 super(c); |
51 } | 50 } |
52 | 51 |
53 @Override | 52 @Override |
54 protected NodeData parse(Element element, AnnotationMirror mirror) { | 53 protected NodeData parse(Element element, AnnotationMirror mirror) { |
55 assert element instanceof TypeElement; | 54 assert element instanceof TypeElement; |
55 NodeData node = null; | |
56 try { | 56 try { |
57 parsedNodes = new HashMap<>(); | 57 parsedNodes = new HashMap<>(); |
58 originalType = (TypeElement) element; | 58 node = parseInnerClassHierarchy((TypeElement) element); |
59 | |
60 return parseInnerClassHierarchy((TypeElement) element); | |
61 } finally { | 59 } finally { |
62 if (Log.DEBUG) { | |
63 NodeData parsed = parsedNodes.get(Utils.getQualifiedName(originalType)); | |
64 if (parsed != null) { | |
65 String dump = parsed.dump(); | |
66 log.error("Node parsed: %s", dump); | |
67 System.out.println("Parsed: " + dump); | |
68 } | |
69 } | |
70 parsedNodes = null; | 60 parsedNodes = null; |
71 originalType = null; | 61 } |
72 } | 62 return node; |
73 } | 63 } |
74 | 64 |
75 @Override | 65 @Override |
76 public boolean isDelegateToRootDeclaredType() { | 66 public boolean isDelegateToRootDeclaredType() { |
77 return true; | 67 return true; |
86 children.add(childNode); | 76 children.add(childNode); |
87 } | 77 } |
88 } | 78 } |
89 NodeData rootNode = resolveNode(rootType); | 79 NodeData rootNode = resolveNode(rootType); |
90 if (rootNode == null && children.size() > 0) { | 80 if (rootNode == null && children.size() > 0) { |
91 rootNode = new NodeData(rootType, null); | 81 rootNode = new NodeData(rootType, null, rootType.getSimpleName().toString()); |
92 } | 82 } |
93 if (rootNode != null) { | 83 if (rootNode != null) { |
84 children.addAll(rootNode.getDeclaredChildren()); | |
94 rootNode.setDeclaredChildren(children); | 85 rootNode.setDeclaredChildren(children); |
95 } | 86 } |
96 | 87 |
97 return rootNode; | 88 return rootNode; |
98 } | 89 } |
102 if (!parsedNodes.containsKey(typeName)) { | 93 if (!parsedNodes.containsKey(typeName)) { |
103 NodeData node = parseNode(currentType); | 94 NodeData node = parseNode(currentType); |
104 if (node != null) { | 95 if (node != null) { |
105 parsedNodes.put(typeName, node); | 96 parsedNodes.put(typeName, node); |
106 } | 97 } |
98 | |
99 if (Log.DEBUG) { | |
100 NodeData parsed = parsedNodes.get(Utils.getQualifiedName(currentType)); | |
101 if (parsed != null) { | |
102 String dump = parsed.dump(); | |
103 String valid = node != null ? "" : " failed"; | |
104 String msg = String.format("Node parsing %s : %s", valid, dump); | |
105 log.error(msg); | |
106 System.out.println(msg); | |
107 } | |
108 } | |
109 | |
107 return node; | 110 return node; |
108 } | 111 } |
109 return parsedNodes.get(typeName); | 112 return parsedNodes.get(typeName); |
110 } | 113 } |
111 | 114 |
119 | 122 |
120 if (methodNodes == null && !Utils.isAssignable(type.asType(), context.getTruffleTypes().getNode())) { | 123 if (methodNodes == null && !Utils.isAssignable(type.asType(), context.getTruffleTypes().getNode())) { |
121 return null; // not a node | 124 return null; // not a node |
122 } | 125 } |
123 | 126 |
127 TypeElement nodeType; | |
128 boolean needsSplit; | |
129 if (methodNodes != null) { | |
130 needsSplit = methodNodes != null; | |
131 nodeType = Utils.fromTypeMirror(Utils.getAnnotationValueType(methodNodes, "value")); | |
132 } else { | |
133 needsSplit = false; | |
134 nodeType = type; | |
135 } | |
136 | |
124 if (type.getModifiers().contains(Modifier.PRIVATE)) { | 137 if (type.getModifiers().contains(Modifier.PRIVATE)) { |
125 return null; // not visible | 138 return null; // not visible |
126 } | 139 } |
127 | 140 |
128 final NodeData nodeData = parseNodeData(type); | 141 NodeData nodeData = parseNodeData(type, nodeType); |
129 if (nodeData == null) { | 142 if (nodeData == null) { |
130 // TODO error message for instanceBaseClass? | |
131 return null; | 143 return null; |
132 } | 144 } |
133 | 145 |
134 List<Element> elements = new ArrayList<>(context.getEnvironment().getElementUtils().getAllMembers(type)); | 146 List<Element> elements = new ArrayList<>(context.getEnvironment().getElementUtils().getAllMembers(type)); |
135 nodeData.setExtensionElements(getExtensionParser().parseAll(type, elements)); | 147 nodeData.setExtensionElements(getExtensionParser().parseAll(type, elements)); |
138 } | 150 } |
139 | 151 |
140 if (!parseMethods(nodeData, elements)) { | 152 if (!parseMethods(nodeData, elements)) { |
141 return null; | 153 return null; |
142 } | 154 } |
143 // TODO split | 155 |
144 | 156 List<NodeData> nodes; |
145 if (!finalizeSpecializations(nodeData)) { | 157 if (needsSplit) { |
158 nodes = splitNodeData(nodeData); | |
159 if (nodes == null) { | |
160 return null; | |
161 } | |
162 } else { | |
163 nodes = new ArrayList<>(); | |
164 nodes.add(nodeData); | |
165 } | |
166 | |
167 boolean valid = true; | |
168 for (NodeData splittedNode : nodes) { | |
169 if (!finalizeSpecializations(splittedNode)) { | |
170 valid = false; | |
171 } | |
172 if (!verifyNode(splittedNode)) { | |
173 valid = false; | |
174 } | |
175 } | |
176 if (!valid) { | |
146 return null; | 177 return null; |
147 } | 178 } |
148 | 179 |
149 if (!verifyNode(nodeData)) { | 180 if (needsSplit) { |
150 return null; | 181 nodeData.setDeclaredChildren(nodes); |
151 } | 182 nodeData.setSpecializationListeners(new ArrayList<SpecializationListenerData>()); |
152 | 183 nodeData.setSpecializations(new ArrayList<SpecializationData>()); |
153 return nodeData; | 184 return nodeData; |
185 } else { | |
186 return nodeData; | |
187 } | |
188 } | |
189 | |
190 private static List<NodeData> splitNodeData(NodeData node) { | |
191 SortedMap<String, List<SpecializationData>> groupedSpecializations = groupByNodeId(node.getSpecializations()); | |
192 SortedMap<String, List<SpecializationListenerData>> groupedListeners = groupByNodeId(node.getSpecializationListeners()); | |
193 | |
194 Set<String> ids = new TreeSet<>(); | |
195 ids.addAll(groupedSpecializations.keySet()); | |
196 ids.addAll(groupedListeners.keySet()); | |
197 | |
198 List<NodeData> splitted = new ArrayList<>(); | |
199 for (String id : ids) { | |
200 List<SpecializationData> specializations = groupedSpecializations.get(id); | |
201 List<SpecializationListenerData> listeners = groupedListeners.get(id); | |
202 | |
203 if (specializations == null) { | |
204 specializations = new ArrayList<>(); | |
205 } | |
206 | |
207 if (listeners == null) { | |
208 listeners = new ArrayList<>(); | |
209 } | |
210 | |
211 String nodeId = node.getNodeId(); | |
212 if (nodeId.endsWith("Node") && !nodeId.equals("Node")) { | |
213 nodeId = nodeId.substring(0, nodeId.length() - 4); | |
214 } | |
215 String newNodeId = nodeId + Utils.firstLetterUpperCase(id); | |
216 NodeData copy = new NodeData(node, newNodeId); | |
217 | |
218 copy.setSpecializations(specializations); | |
219 copy.setSpecializationListeners(listeners); | |
220 | |
221 splitted.add(copy); | |
222 } | |
223 | |
224 if (splitted.isEmpty()) { | |
225 splitted.add(node); | |
226 } | |
227 | |
228 node.setSpecializations(new ArrayList<SpecializationData>()); | |
229 node.setSpecializationListeners(new ArrayList<SpecializationListenerData>()); | |
230 | |
231 return splitted; | |
232 } | |
233 | |
234 private static <M extends TemplateMethod> SortedMap<String, List<M>> groupByNodeId(List<M> methods) { | |
235 SortedMap<String, List<M>> grouped = new TreeMap<>(); | |
236 for (M m : methods) { | |
237 List<M> list = grouped.get(m.getId()); | |
238 if (list == null) { | |
239 list = new ArrayList<>(); | |
240 grouped.put(m.getId(), list); | |
241 } | |
242 list.add(m); | |
243 } | |
244 return grouped; | |
154 } | 245 } |
155 | 246 |
156 private boolean parseMethods(final NodeData node, List<Element> elements) { | 247 private boolean parseMethods(final NodeData node, List<Element> elements) { |
157 node.setGuards(new GuardParser(context, node, node.getTypeSystem()).parse(elements)); | 248 node.setGuards(new GuardParser(context, node, node.getTypeSystem()).parse(elements)); |
158 node.setShortCircuits(new ShortCircuitParser(context, node).parse(elements)); | 249 node.setShortCircuits(new ShortCircuitParser(context, node).parse(elements)); |
174 } | 265 } |
175 | 266 |
176 private boolean finalizeSpecializations(final NodeData node) { | 267 private boolean finalizeSpecializations(final NodeData node) { |
177 List<SpecializationData> specializations = new ArrayList<>(node.getSpecializations()); | 268 List<SpecializationData> specializations = new ArrayList<>(node.getSpecializations()); |
178 | 269 |
270 if (specializations.isEmpty()) { | |
271 return true; | |
272 } | |
273 | |
179 List<SpecializationData> generics = new ArrayList<>(); | 274 List<SpecializationData> generics = new ArrayList<>(); |
180 for (SpecializationData spec : specializations) { | 275 for (SpecializationData spec : specializations) { |
181 if (spec.isGeneric()) { | 276 if (spec.isGeneric()) { |
182 generics.add(spec); | 277 generics.add(spec); |
183 } | 278 } |
189 log.error(generic.getMethod(), "Only one method with @%s is allowed per operation.", Generic.class.getSimpleName()); | 284 log.error(generic.getMethod(), "Only one method with @%s is allowed per operation.", Generic.class.getSimpleName()); |
190 } | 285 } |
191 return false; | 286 return false; |
192 } else if (generics.size() == 1) { | 287 } else if (generics.size() == 1) { |
193 genericSpecialization = generics.get(0); | 288 genericSpecialization = generics.get(0); |
289 } else { | |
290 // TODO support generation of generic if not ambiguous. | |
194 } | 291 } |
195 | 292 |
196 if (specializations.size() > 1 && genericSpecialization == null) { | 293 if (specializations.size() > 1 && genericSpecialization == null) { |
197 log.error(node.getTemplateType(), "Need a @%s method.", Generic.class.getSimpleName()); | 294 log.error(node.getTemplateType(), "Need a @%s method.", Generic.class.getSimpleName()); |
198 return false; | 295 return false; |
213 } | 310 } |
214 }); | 311 }); |
215 | 312 |
216 node.setSpecializations(specializations); | 313 node.setSpecializations(specializations); |
217 | 314 |
315 for (SpecializationData specialization : specializations) { | |
316 specialization.setId(findUniqueSpecializationId(specialization)); | |
317 } | |
318 | |
218 return true; | 319 return true; |
320 } | |
321 | |
322 private static String findUniqueSpecializationId(SpecializationData specialization) { | |
323 | |
324 String name; | |
325 if (specialization.isGeneric()) { | |
326 name = "Generic"; | |
327 } else if (specialization.isUninitialized()) { | |
328 name = "Uninitialized"; | |
329 } else { | |
330 List<SpecializationData> specializations = new ArrayList<>(specialization.getNode().getSpecializations()); | |
331 for (ListIterator<SpecializationData> iterator = specializations.listIterator(); iterator.hasNext();) { | |
332 SpecializationData data = iterator.next(); | |
333 if (data.isGeneric() || data.isUninitialized()) { | |
334 iterator.remove(); | |
335 } | |
336 } | |
337 | |
338 Map<ParameterSpec, Set<String>> usedIds = new HashMap<>(); | |
339 for (SpecializationData other : specializations) { | |
340 for (ActualParameter param : other.getReturnTypeAndParameters()) { | |
341 if (other.getNode().findField(param.getSpecification().getName()) == null) { | |
342 continue; | |
343 } | |
344 | |
345 Set<String> types = usedIds.get(param.getSpecification()); | |
346 if (types == null) { | |
347 types = new HashSet<>(); | |
348 usedIds.put(param.getSpecification(), types); | |
349 } | |
350 types.add(Utils.getTypeId(param.getActualType())); | |
351 } | |
352 } | |
353 | |
354 List<ParameterSpec> ambiguousSpecs = new ArrayList<>(); | |
355 for (ActualParameter param : specialization.getReturnTypeAndParameters()) { | |
356 Set<String> ids = usedIds.get(param.getSpecification()); | |
357 if (ids != null && ids.size() > 1) { | |
358 ambiguousSpecs.add(param.getSpecification()); | |
359 } | |
360 } | |
361 | |
362 String specializationId = findSpecializationId(specialization, ambiguousSpecs); | |
363 int specializationIndex = 0; | |
364 int totalIndex = 0; | |
365 | |
366 for (SpecializationData other : specializations) { | |
367 String id = findSpecializationId(other, ambiguousSpecs); | |
368 if (id.equals(specializationId)) { | |
369 totalIndex++; | |
370 if (specialization == other) { | |
371 specializationIndex = totalIndex; | |
372 } | |
373 } | |
374 } | |
375 | |
376 if (specializationIndex != totalIndex) { | |
377 name = specializationId + specializationIndex; | |
378 } else { | |
379 name = specializationId; | |
380 } | |
381 } | |
382 return name; | |
383 } | |
384 | |
385 private static String findSpecializationId(SpecializationData specialization, List<ParameterSpec> specs) { | |
386 boolean allSame = true; | |
387 ActualParameter prevParam = specialization.getReturnType(); | |
388 for (ParameterSpec spec : specs) { | |
389 ActualParameter param = specialization.findParameter(spec); | |
390 if (!Utils.typeEquals(prevParam.getActualType(), param.getActualType())) { | |
391 allSame = false; | |
392 break; | |
393 } | |
394 prevParam = param; | |
395 } | |
396 | |
397 if (allSame) { | |
398 return Utils.getTypeId(prevParam.getActualType()); | |
399 } else { | |
400 StringBuilder nameBuilder = new StringBuilder(); | |
401 nameBuilder.append(Utils.getTypeId(prevParam.getActualType())); | |
402 for (ParameterSpec spec : specs) { | |
403 ActualParameter param = specialization.findParameter(spec); | |
404 nameBuilder.append(Utils.getTypeId(param.getActualType())); | |
405 } | |
406 return nameBuilder.toString(); | |
407 } | |
219 } | 408 } |
220 | 409 |
221 private boolean verifyNode(NodeData nodeData) { | 410 private boolean verifyNode(NodeData nodeData) { |
222 // verify specialization parameter length | 411 // verify specialization parameter length |
223 if (!verifySpecializationParameters(nodeData)) { | 412 if (!verifySpecializationParameters(nodeData)) { |
258 } | 447 } |
259 | 448 |
260 return true; | 449 return true; |
261 } | 450 } |
262 | 451 |
263 private NodeData parseNodeData(TypeElement type) { | 452 private NodeData parseNodeData(TypeElement templateType, TypeElement nodeType) { |
264 List<Element> elements = new ArrayList<>(context.getEnvironment().getElementUtils().getAllMembers(type)); | 453 List<Element> elements = new ArrayList<>(context.getEnvironment().getElementUtils().getAllMembers(nodeType)); |
265 List<TypeElement> typeHierarchy = findSuperClasses(new ArrayList<TypeElement>(), type); | 454 List<TypeElement> typeHierarchy = findSuperClasses(new ArrayList<TypeElement>(), nodeType); |
266 Collections.reverse(typeHierarchy); | 455 Collections.reverse(typeHierarchy); |
267 | 456 |
268 AnnotationMirror typeSystemMirror = findFirstAnnotation(typeHierarchy, TypeSystemReference.class); | 457 AnnotationMirror typeSystemMirror = findFirstAnnotation(typeHierarchy, TypeSystemReference.class); |
269 if (typeSystemMirror == null) { | 458 if (typeSystemMirror == null) { |
270 log.error(type, "No @%s annotation found in type hierarchy of %s.", TypeSystemReference.class.getSimpleName(), type.getQualifiedName().toString()); | 459 log.error(templateType, "No @%s annotation found in type hierarchy of %s.", TypeSystemReference.class.getSimpleName(), nodeType.getQualifiedName().toString()); |
271 return null; | 460 return null; |
272 } | 461 } |
273 | 462 |
274 TypeMirror typeSytemType = Utils.getAnnotationValueType(typeSystemMirror, "value"); | 463 TypeMirror typeSytemType = Utils.getAnnotationValueType(typeSystemMirror, "value"); |
275 final TypeSystemData typeSystem = (TypeSystemData) context.getTemplate(typeSytemType, true); | 464 final TypeSystemData typeSystem = (TypeSystemData) context.getTemplate(typeSytemType, true); |
276 if (typeSystem == null) { | 465 if (typeSystem == null) { |
277 log.error(type, "The used type system '%s' is invalid.", Utils.getQualifiedName(typeSytemType)); | 466 log.error(templateType, "The used type system '%s' is invalid.", Utils.getQualifiedName(typeSytemType)); |
278 return null; | 467 return null; |
279 } | 468 } |
280 | 469 |
281 NodeData nodeData = new NodeData(type, typeSystem); | 470 String nodeId = templateType.getSimpleName().toString(); |
471 if (nodeId.endsWith("Node") && !nodeId.equals("Node")) { | |
472 nodeId = nodeId.substring(0, nodeId.length() - 4); | |
473 } | |
474 | |
475 NodeData nodeData = new NodeData(templateType, typeSystem, templateType.getSimpleName().toString()); | |
476 nodeData.setNodeType(nodeType.asType()); | |
282 | 477 |
283 List<ExecutableTypeData> executableTypes = filterExecutableTypes(new ExecutableTypeMethodParser(context, nodeData).parse(elements)); | 478 List<ExecutableTypeData> executableTypes = filterExecutableTypes(new ExecutableTypeMethodParser(context, nodeData).parse(elements)); |
284 | 479 |
285 nodeData.setExecutableTypes(executableTypes); | 480 nodeData.setExecutableTypes(executableTypes); |
286 | 481 |
287 parsedNodes.put(Utils.getQualifiedName(type), nodeData); | 482 parsedNodes.put(Utils.getQualifiedName(nodeType), nodeData); |
288 | 483 |
289 List<NodeFieldData> fields = parseFields(nodeData, elements, typeHierarchy); | 484 List<NodeFieldData> fields = parseFields(nodeData, elements, typeHierarchy); |
290 if (fields == null) { | 485 if (fields == null) { |
291 return null; | 486 return null; |
292 } | 487 } |
293 nodeData.setFields(fields); | 488 nodeData.setFields(fields); |
489 | |
490 if (!Utils.isAssignable(templateType.asType(), nodeType.asType())) { | |
491 // nodeData.setInstanceParameterSpec(new ParameterSpec("instance", templateType.asType(), false, | |
492 // true)); | |
493 } | |
494 | |
294 return nodeData; | 495 return nodeData; |
295 } | 496 } |
296 | 497 |
297 private boolean verifySpecializationParameters(NodeData nodeData) { | 498 private boolean verifySpecializationParameters(NodeData nodeData) { |
298 boolean valid = true; | 499 boolean valid = true; |
667 } | 868 } |
668 } | 869 } |
669 return valid; | 870 return valid; |
670 } | 871 } |
671 | 872 |
873 @SuppressWarnings("unused") | |
672 private boolean verifyNamesUnique(List<? extends TemplateMethod> methods) { | 874 private boolean verifyNamesUnique(List<? extends TemplateMethod> methods) { |
673 boolean valid = true; | 875 boolean valid = true; |
674 for (int i = 0; i < methods.size(); i++) { | 876 for (int i = 0; i < methods.size(); i++) { |
675 TemplateMethod m1 = methods.get(i); | 877 TemplateMethod m1 = methods.get(i); |
676 for (int j = i + 1; j < methods.size(); j++) { | 878 for (int j = i + 1; j < methods.size(); j++) { |
768 } | 970 } |
769 return true; | 971 return true; |
770 } | 972 } |
771 | 973 |
772 private boolean verifySpecializationThrows(NodeData node) { | 974 private boolean verifySpecializationThrows(NodeData node) { |
773 TypeSystemData typeSystem = node.getTypeSystem(); | |
774 | |
775 Map<String, SpecializationData> specializationMap = new HashMap<>(); | 975 Map<String, SpecializationData> specializationMap = new HashMap<>(); |
776 for (SpecializationData spec : node.getSpecializations()) { | 976 for (SpecializationData spec : node.getSpecializations()) { |
777 specializationMap.put(spec.getMethodName(), spec); | 977 specializationMap.put(spec.getMethodName(), spec); |
778 } | 978 } |
779 boolean valid = true; | 979 boolean valid = true; |