comparison graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeParser.java @ 13527:25ecb47a6d0e

Truffle-DSL: Added support for references to child arrays in @ShortCircuit; Introduced new layer NodeExecutionData to the implementation model which is in between NodeChildData and the actual parameters..
author Christian Humer <christian.humer@gmail.com>
date Tue, 07 Jan 2014 12:22:47 +0100
parents 2b9fcffd6f36
children 5a0c694ef735
comparison
equal deleted inserted replaced
13483:37ec2cabf397 13527:25ecb47a6d0e
32 32
33 import com.oracle.truffle.api.dsl.*; 33 import com.oracle.truffle.api.dsl.*;
34 import com.oracle.truffle.api.nodes.*; 34 import com.oracle.truffle.api.nodes.*;
35 import com.oracle.truffle.dsl.processor.*; 35 import com.oracle.truffle.dsl.processor.*;
36 import com.oracle.truffle.dsl.processor.node.NodeChildData.Cardinality; 36 import com.oracle.truffle.dsl.processor.node.NodeChildData.Cardinality;
37 import com.oracle.truffle.dsl.processor.node.NodeChildData.ExecutionKind;
38 import com.oracle.truffle.dsl.processor.template.*; 37 import com.oracle.truffle.dsl.processor.template.*;
39 import com.oracle.truffle.dsl.processor.template.TemplateMethod.Signature; 38 import com.oracle.truffle.dsl.processor.template.TemplateMethod.TypeSignature;
40 import com.oracle.truffle.dsl.processor.typesystem.*; 39 import com.oracle.truffle.dsl.processor.typesystem.*;
41 40
42 public class NodeParser extends TemplateParser<NodeData> { 41 public class NodeParser extends TemplateParser<NodeData> {
43 42
44 public static final List<Class<? extends Annotation>> ANNOTATIONS = Arrays.asList(Generic.class, TypeSystemReference.class, ShortCircuit.class, Specialization.class, SpecializationListener.class, 43 public static final List<Class<? extends Annotation>> ANNOTATIONS = Arrays.asList(Generic.class, TypeSystemReference.class, ShortCircuit.class, Specialization.class, SpecializationListener.class,
203 splittedNode.addError("Classes containing a @%s annotation must not be private.", Specialization.class.getSimpleName()); 202 splittedNode.addError("Classes containing a @%s annotation must not be private.", Specialization.class.getSimpleName());
204 } 203 }
205 204
206 finalizeSpecializations(elements, splittedNode); 205 finalizeSpecializations(elements, splittedNode);
207 verifyNode(splittedNode, elements); 206 verifyNode(splittedNode, elements);
208 expandExecutableTypeVarArgs(splittedNode);
209 createPolymorphicSpecializations(splittedNode); 207 createPolymorphicSpecializations(splittedNode);
210 assignShortCircuitsToSpecializations(splittedNode); 208 assignShortCircuitsToSpecializations(splittedNode);
211 } 209 }
212 210
213 if (node.isNodeContainer()) { 211 if (node.isNodeContainer()) {
214 node.setDeclaredNodes(nodes); 212 node.setDeclaredNodes(nodes);
215 node.setSpecializationListeners(new ArrayList<SpecializationListenerData>()); 213 node.setSpecializationListeners(new ArrayList<SpecializationListenerData>());
216 node.setSpecializations(new ArrayList<SpecializationData>()); 214 node.setSpecializations(new ArrayList<SpecializationData>());
217 } 215 }
218 return node; 216 return node;
219 }
220
221 private static void expandExecutableTypeVarArgs(NodeData node) {
222 for (ExecutableTypeData executableMethod : node.getExecutableTypes()) {
223 if (!(executableMethod.getMethod().isVarArgs() && executableMethod.getSpecification().isVariableRequiredArguments())) {
224 continue;
225 }
226 int expandArguments = node.getSignatureSize() - executableMethod.getSignatureSize();
227 if (expandArguments > 0) {
228 int signatureSize = executableMethod.getSignatureSize();
229 ActualParameter parameter = executableMethod.getSignatureParameter(signatureSize - 1);
230 for (int i = 0; i < expandArguments; i++) {
231 int newVarArgsIndex = parameter.getVarArgsIndex() + i + 1;
232 int newSpecificationIndex = parameter.getSpecificationIndex() + i + 1;
233 executableMethod.getParameters().add(
234 new ActualParameter(parameter.getSpecification(), parameter.getTypeSystemType(), newSpecificationIndex, newVarArgsIndex, parameter.isImplicit()));
235 }
236
237 }
238 }
239 } 217 }
240 218
241 private void createPolymorphicSpecializations(NodeData node) { 219 private void createPolymorphicSpecializations(NodeData node) {
242 if (!node.needsRewrites(context) || !node.isPolymorphic()) { 220 if (!node.needsRewrites(context) || !node.isPolymorphic()) {
243 node.setPolymorphicSpecializations(Collections.<SpecializationData> emptyList()); 221 node.setPolymorphicSpecializations(Collections.<SpecializationData> emptyList());
275 } 253 }
276 polymorphicSignature.add(polymorphicType); 254 polymorphicSignature.add(polymorphicType);
277 } 255 }
278 256
279 SpecializationData specialization = new SpecializationData(generic, false, false, true); 257 SpecializationData specialization = new SpecializationData(generic, false, false, true);
280 specialization.updateSignature(new Signature(polymorphicSignature)); 258 specialization.updateSignature(new TypeSignature(polymorphicSignature));
281 specialization.setNode(node); 259 specialization.setNode(node);
282 node.setGenericPolymorphicSpecialization(specialization); 260 node.setGenericPolymorphicSpecialization(specialization);
283 // TODO remove polymoprhic specializations 261 // TODO remove polymoprhic specializations
284 node.setPolymorphicSpecializations(Collections.<SpecializationData> emptyList()); 262 node.setPolymorphicSpecializations(Collections.<SpecializationData> emptyList());
285 } 263 }
334 AnnotationMirror nodeContainer = findFirstAnnotation(typeHierarchy, NodeContainer.class); 312 AnnotationMirror nodeContainer = findFirstAnnotation(typeHierarchy, NodeContainer.class);
335 nodeData.setNodeContainer(nodeContainer != null); 313 nodeData.setNodeContainer(nodeContainer != null);
336 nodeData.setTypeSystem(typeSystem); 314 nodeData.setTypeSystem(typeSystem);
337 nodeData.setFields(parseFields(typeHierarchy, elements)); 315 nodeData.setFields(parseFields(typeHierarchy, elements));
338 nodeData.setChildren(parseChildren(nodeData, elements, typeHierarchy)); 316 nodeData.setChildren(parseChildren(nodeData, elements, typeHierarchy));
317 nodeData.setChildExecutions(parseDefaultSignature(nodeData, elements));
339 nodeData.setExecutableTypes(groupExecutableTypes(new ExecutableTypeMethodParser(context, nodeData).parse(elements))); 318 nodeData.setExecutableTypes(groupExecutableTypes(new ExecutableTypeMethodParser(context, nodeData).parse(elements)));
340 319
341 // resolveChildren invokes cyclic parsing. 320 // resolveChildren invokes cyclic parsing.
342 parsedNodes.put(Utils.getQualifiedName(templateType), nodeData); 321 parsedNodes.put(Utils.getQualifiedName(templateType), nodeData);
343 resolveChildren(nodeData); 322 resolveChildren(nodeData);
344 323
345 return nodeData; 324 return nodeData;
325 }
326
327 private List<NodeExecutionData> parseDefaultSignature(NodeData node, List<? extends Element> elements) {
328 if (node.getChildren() == null) {
329 return null;
330 }
331
332 // pre-parse short circuits
333 Set<String> shortCircuits = new HashSet<>();
334 List<ExecutableElement> methods = ElementFilter.methodsIn(elements);
335 for (ExecutableElement method : methods) {
336 AnnotationMirror mirror = Utils.findAnnotationMirror(processingEnv, method, ShortCircuit.class);
337 if (mirror != null) {
338 shortCircuits.add(Utils.getAnnotationValue(String.class, mirror, "value"));
339 }
340 }
341
342 boolean hasVarArgs = false;
343 int maxSignatureSize = 0;
344 if (!node.getChildren().isEmpty()) {
345 int lastIndex = node.getChildren().size() - 1;
346 hasVarArgs = node.getChildren().get(lastIndex).getCardinality() == Cardinality.MANY;
347 if (hasVarArgs) {
348 maxSignatureSize = lastIndex;
349 } else {
350 maxSignatureSize = node.getChildren().size();
351 }
352 }
353
354 // pre-parse specializations
355 for (ExecutableElement method : methods) {
356 AnnotationMirror mirror = Utils.findAnnotationMirror(processingEnv, method, Specialization.class);
357 if (mirror == null) {
358 continue;
359 }
360
361 int currentArgumentCount = 0;
362 boolean skipShortCircuit = false;
363 for (VariableElement var : method.getParameters()) {
364 TypeMirror type = var.asType();
365 if (currentArgumentCount == 0) {
366 // skip optionals
367 if (Utils.typeEquals(type, context.getTruffleTypes().getFrame())) {
368 continue;
369 }
370 // TODO skip optional fields?
371 }
372 int childIndex = currentArgumentCount < node.getChildren().size() ? currentArgumentCount : node.getChildren().size() - 1;
373 if (childIndex == -1) {
374 continue;
375 }
376 if (!skipShortCircuit) {
377 NodeChildData child = node.getChildren().get(childIndex);
378 if (shortCircuits.contains(NodeExecutionData.createShortCircuitId(child, currentArgumentCount - childIndex))) {
379 skipShortCircuit = true;
380 continue;
381 }
382 } else {
383 skipShortCircuit = false;
384 }
385
386 currentArgumentCount++;
387 }
388 maxSignatureSize = Math.max(maxSignatureSize, currentArgumentCount);
389 }
390
391 List<NodeExecutionData> executions = new ArrayList<>();
392 for (int i = 0; i < maxSignatureSize; i++) {
393 int childIndex = i;
394 boolean varArg = false;
395 if (childIndex >= node.getChildren().size() - 1) {
396 if (hasVarArgs) {
397 childIndex = node.getChildren().size() - 1;
398 varArg = hasVarArgs;
399 } else if (childIndex >= node.getChildren().size()) {
400 break;
401 }
402 }
403 int varArgsIndex = varArg ? Math.abs(childIndex - i) : -1;
404 NodeChildData child = node.getChildren().get(childIndex);
405 boolean shortCircuit = shortCircuits.contains(NodeExecutionData.createShortCircuitId(child, varArgsIndex));
406 executions.add(new NodeExecutionData(child, varArgsIndex, shortCircuit));
407 }
408 return executions;
346 } 409 }
347 410
348 private List<NodeFieldData> parseFields(List<TypeElement> typeHierarchy, List<? extends Element> elements) { 411 private List<NodeFieldData> parseFields(List<TypeElement> typeHierarchy, List<? extends Element> elements) {
349 Set<String> names = new HashSet<>(); 412 Set<String> names = new HashSet<>();
350 413
468 childType = castNodeType; 531 childType = castNodeType;
469 } 532 }
470 533
471 Element getter = findGetter(elements, name, childType); 534 Element getter = findGetter(elements, name, childType);
472 535
473 ExecutionKind kind = ExecutionKind.DEFAULT; 536 NodeChildData nodeChild = new NodeChildData(parent, type, childMirror, name, childType, originalChildType, getter, cardinality);
474 if (shortCircuits.contains(name)) {
475 kind = ExecutionKind.SHORT_CIRCUIT;
476 }
477
478 NodeChildData nodeChild = new NodeChildData(parent, type, childMirror, name, childType, originalChildType, getter, cardinality, kind);
479 537
480 parsedChildren.add(nodeChild); 538 parsedChildren.add(nodeChild);
481 539
482 verifyNodeChild(nodeChild); 540 verifyNodeChild(nodeChild);
483 if (nodeChild.hasErrors()) { 541 if (nodeChild.hasErrors()) {
725 node.setPolymorphicDepth(1); 783 node.setPolymorphicDepth(1);
726 } 784 }
727 } 785 }
728 786
729 private SpecializationData createGenericSpecialization(final NodeData node, List<SpecializationData> specializations) { 787 private SpecializationData createGenericSpecialization(final NodeData node, List<SpecializationData> specializations) {
730 SpecializationData genericSpecialization;
731 SpecializationData specialization = specializations.get(0); 788 SpecializationData specialization = specializations.get(0);
732 GenericParser parser = new GenericParser(context, node); 789 GenericParser parser = new GenericParser(context, node);
733 MethodSpec specification = parser.createDefaultMethodSpec(specialization.getMethod(), null, true, null); 790 MethodSpec specification = parser.createDefaultMethodSpec(specialization.getMethod(), null, true, null);
734 791 specification.getImplicitRequiredTypes().clear();
735 List<ActualParameter> parameters = new ArrayList<>(); 792
736 for (ActualParameter parameter : specialization.getReturnTypeAndParameters()) { 793 List<TypeMirror> parameterTypes = new ArrayList<>();
737 if (!parameter.getSpecification().isSignature()) { 794 int signatureIndex = 1;
738 parameters.add(new ActualParameter(parameter)); 795 for (ParameterSpec spec : specification.getRequired()) {
739 continue; 796 parameterTypes.add(createGenericType(spec, specializations, signatureIndex));
740 } 797 if (spec.isSignature()) {
741 NodeData childNode = node; 798 signatureIndex++;
742 NodeChildData child = node.findChild(parameter.getSpecification().getName()); 799 }
743 if (child != null) { 800 }
744 childNode = child.getNodeData(); 801 TypeMirror returnType = createGenericType(specification.getReturnType(), specializations, 0);
745 } 802 return parser.create("Generic", null, null, returnType, parameterTypes);
803 }
804
805 private TypeMirror createGenericType(ParameterSpec spec, List<SpecializationData> specializations, int signatureIndex) {
806 NodeExecutionData execution = spec.getExecution();
807 if (execution == null) {
808 if (spec.getAllowedTypes().size() == 1) {
809 return spec.getAllowedTypes().get(0);
810 } else {
811 return Utils.getCommonSuperType(context, spec.getAllowedTypes().toArray(new TypeMirror[0]));
812 }
813 } else {
814 Set<TypeData> types = new HashSet<>();
815 for (SpecializationData specialization : specializations) {
816 types.add(specialization.getTypeSignature().get(signatureIndex));
817 }
818
819 NodeChildData child = execution.getChild();
746 820
747 TypeData genericType = null; 821 TypeData genericType = null;
748
749 Set<TypeData> types = new HashSet<>();
750 for (SpecializationData otherSpecialization : specializations) {
751 ActualParameter otherParameter = otherSpecialization.findParameter(parameter.getLocalName());
752 if (otherParameter != null) {
753 types.add(otherParameter.getTypeSystemType());
754 }
755 }
756
757 assert !types.isEmpty();
758
759 if (types.size() == 1) { 822 if (types.size() == 1) {
760 ExecutableTypeData executable = childNode.findExecutableType(types.iterator().next(), 0); 823 ExecutableTypeData executable = child.findExecutableType(context, types.iterator().next());
761 if (executable != null && !executable.hasUnexpectedValue(context)) { 824 if (executable != null && !executable.hasUnexpectedValue(context)) {
762 genericType = types.iterator().next(); 825 genericType = types.iterator().next();
763 } else { 826 }
764 genericType = childNode.findAnyGenericExecutableType(context, 0).getType(); 827 }
765 } 828 if (genericType == null) {
766 } else { 829 genericType = child.findAnyGenericExecutableType(context).getType();
767 genericType = childNode.findAnyGenericExecutableType(context, 0).getType(); 830 }
768 } 831 return genericType.getPrimitiveType();
769 832 }
770 parameters.add(new ActualParameter(parameter, genericType));
771 }
772 ActualParameter returnType = parameters.get(0);
773 parameters = parameters.subList(1, parameters.size());
774
775 TemplateMethod genericMethod = new TemplateMethod("Generic", node, specification, null, null, returnType, parameters);
776 genericSpecialization = new SpecializationData(genericMethod, true, false, false);
777 return genericSpecialization;
778 } 833 }
779 834
780 private void assignShortCircuitsToSpecializations(NodeData node) { 835 private void assignShortCircuitsToSpecializations(NodeData node) {
781 Map<String, List<ShortCircuitData>> groupedShortCircuits = groupShortCircuits(node.getShortCircuits()); 836 Map<String, List<ShortCircuitData>> groupedShortCircuits = groupShortCircuits(node.getShortCircuits());
782 837
783 boolean valid = true; 838 boolean valid = true;
784 for (NodeChildData field : node.filterFields(ExecutionKind.SHORT_CIRCUIT)) { 839 List<NodeExecutionData> shortCircuitExecutions = new ArrayList<>();
785 String valueName = field.getName(); 840 for (NodeExecutionData execution : node.getChildExecutions()) {
841 if (!execution.isShortCircuit()) {
842 continue;
843 }
844 shortCircuitExecutions.add(execution);
845 String valueName = execution.getShortCircuitId();
786 List<ShortCircuitData> availableCircuits = groupedShortCircuits.get(valueName); 846 List<ShortCircuitData> availableCircuits = groupedShortCircuits.get(valueName);
787 847
788 if (availableCircuits == null || availableCircuits.isEmpty()) { 848 if (availableCircuits == null || availableCircuits.isEmpty()) {
789 node.addError("@%s method for short cut value '%s' required.", ShortCircuit.class.getSimpleName(), valueName); 849 node.addError("@%s method for short cut value '%s' required.", ShortCircuit.class.getSimpleName(), valueName);
790 valid = false; 850 valid = false;
807 continue; 867 continue;
808 } 868 }
809 869
810 ShortCircuitData genericCircuit = null; 870 ShortCircuitData genericCircuit = null;
811 for (ShortCircuitData circuit : availableCircuits) { 871 for (ShortCircuitData circuit : availableCircuits) {
812 if (isGenericShortCutMethod(node, circuit)) { 872 if (isGenericShortCutMethod(circuit)) {
813 genericCircuit = circuit; 873 genericCircuit = circuit;
814 break; 874 break;
815 } 875 }
816 } 876 }
817 877
830 890
831 if (!valid) { 891 if (!valid) {
832 return; 892 return;
833 } 893 }
834 894
835 NodeChildData[] fields = node.filterFields(ExecutionKind.SHORT_CIRCUIT);
836 List<SpecializationData> specializations = new ArrayList<>(); 895 List<SpecializationData> specializations = new ArrayList<>();
837 specializations.addAll(node.getSpecializations()); 896 specializations.addAll(node.getSpecializations());
838 specializations.addAll(node.getPolymorphicSpecializations()); 897 specializations.addAll(node.getPolymorphicSpecializations());
839 898
840 for (SpecializationData specialization : specializations) { 899 for (SpecializationData specialization : specializations) {
841 List<ShortCircuitData> assignedShortCuts = new ArrayList<>(fields.length); 900 List<ShortCircuitData> assignedShortCuts = new ArrayList<>(shortCircuitExecutions.size());
842 901
843 for (int i = 0; i < fields.length; i++) { 902 for (NodeExecutionData shortCircuit : shortCircuitExecutions) {
844 List<ShortCircuitData> availableShortCuts = groupedShortCircuits.get(fields[i].getName()); 903 List<ShortCircuitData> availableShortCuts = groupedShortCircuits.get(shortCircuit.getShortCircuitId());
845 904
846 ShortCircuitData genericShortCircuit = null; 905 ShortCircuitData genericShortCircuit = null;
847 ShortCircuitData compatibleShortCircuit = null; 906 ShortCircuitData compatibleShortCircuit = null;
848 for (ShortCircuitData circuit : availableShortCuts) { 907 for (ShortCircuitData circuit : availableShortCuts) {
849 if (circuit.isGeneric()) { 908 if (circuit.isGeneric()) {
895 continue; 954 continue;
896 } 955 }
897 List<String> paramIds = new LinkedList<>(); 956 List<String> paramIds = new LinkedList<>();
898 paramIds.add(Utils.getTypeId(other.getReturnType().getType())); 957 paramIds.add(Utils.getTypeId(other.getReturnType().getType()));
899 for (ActualParameter param : other.getParameters()) { 958 for (ActualParameter param : other.getParameters()) {
900 if (other.getNode().findChild(param.getSpecification().getName()) == null) { 959 if (param.getSpecification().getExecution() == null) {
901 continue; 960 continue;
902 } 961 }
903 paramIds.add(Utils.getTypeId(param.getType())); 962 paramIds.add(Utils.getTypeId(param.getType()));
904 } 963 }
905 assert lastSize == -1 || lastSize == paramIds.size(); 964 assert lastSize == -1 || lastSize == paramIds.size();
1228 } 1287 }
1229 } 1288 }
1230 return null; 1289 return null;
1231 } 1290 }
1232 1291
1233 private boolean isGenericShortCutMethod(NodeData node, TemplateMethod method) { 1292 private boolean isGenericShortCutMethod(ShortCircuitData method) {
1234 for (ActualParameter parameter : method.getParameters()) { 1293 for (ActualParameter parameter : method.getParameters()) {
1235 NodeChildData field = node.findChild(parameter.getSpecification().getName()); 1294 NodeExecutionData execution = parameter.getSpecification().getExecution();
1236 if (field == null) { 1295 if (execution == null) {
1237 continue; 1296 continue;
1238 } 1297 }
1239 ExecutableTypeData found = null; 1298 ExecutableTypeData found = null;
1240 List<ExecutableTypeData> executableElements = field.findGenericExecutableTypes(context); 1299 List<ExecutableTypeData> executableElements = execution.getChild().findGenericExecutableTypes(context);
1241 for (ExecutableTypeData executable : executableElements) { 1300 for (ExecutableTypeData executable : executableElements) {
1242 if (executable.getType().equalsType(parameter.getTypeSystemType())) { 1301 if (executable.getType().equalsType(parameter.getTypeSystemType())) {
1243 found = executable; 1302 found = executable;
1244 break; 1303 break;
1245 } 1304 }