private static List<ExecutableTypeData> buildExecutableHierarchy(NodeData node) { List<ExecutableTypeData> executes = node.getExecutableTypes(); if (executes.isEmpty()) { return Collections.emptyList(); } List<ExecutableTypeData> hierarchyExecutes = new ArrayList<>(executes); Collections.sort(hierarchyExecutes); ExecutableTypeData parent = hierarchyExecutes.get(0); ListIterator<ExecutableTypeData> executesIterator = hierarchyExecutes.listIterator(1); buildExecutableHierarchy(node, parent, executesIterator); return hierarchyExecutes; }
private void resolveContains(NodeData node) { // flatten transitive includes for (SpecializationData specialization : node.getSpecializations()) { if (specialization.getContains().isEmpty()) { continue; } Set<SpecializationData> foundSpecializations = new HashSet<>(); collectIncludes(specialization, foundSpecializations, new HashSet<SpecializationData>()); specialization.getContains().addAll(foundSpecializations); } }
private static List<TypeElement> collectSuperClasses(List<TypeElement> collection, TypeElement element) { if (element != null) { collection.add(element); if (element.getSuperclass() != null) { collectSuperClasses(collection, ElementUtils.fromTypeMirror(element.getSuperclass())); } } return collection; }
List<TypeElement> lookupTypes = collectSuperClasses(new ArrayList<TypeElement>(), templateType); List<Element> members = loadMembers(templateType); if (!containsSpecializations(members)) { return null; NodeData node = parseNodeData(templateType, lookupTypes); if (node.hasErrors()) { return node; AnnotationMirror reflectable = findFirstAnnotation(lookupTypes, Introspectable.class); if (reflectable != null) { node.setReflectable(true); AnnotationMirror reportPolymorphism = findFirstAnnotation(lookupTypes, ReportPolymorphism.class); AnnotationMirror excludePolymorphism = findFirstAnnotation(lookupTypes, ReportPolymorphism.Exclude.class); if (reportPolymorphism != null && excludePolymorphism == null) { node.setReportPolymorphism(true); node.getFields().addAll(parseFields(lookupTypes, members)); node.getChildren().addAll(parseChildren(node, lookupTypes, members)); node.getChildExecutions().addAll(parseExecutions(node.getFields(), node.getChildren(), members)); node.getExecutableTypes().addAll(parseExecutableTypeData(node, members, node.getSignatureSize(), context.getFrameTypes(), false)); initializeExecutableTypes(node); initializeImportGuards(node, lookupTypes, members); initializeChildren(node); initializeSpecializations(members, node);
private void initializeExpressions(List<? extends Element> elements, NodeData node) { List<Element> members = filterNotAccessibleElements(node.getTemplateType(), elements); List<VariableElement> fields = new ArrayList<>(); for (NodeFieldData field : node.getFields()) { fields.add(field.getVariable()); } for (SpecializationData specialization : node.getSpecializations()) { if (specialization.getMethod() == null) { continue; } List<Element> specializationMembers = new ArrayList<>(members.size() + specialization.getParameters().size() + fields.size()); for (Parameter p : specialization.getParameters()) { specializationMembers.add(p.getVariableElement()); } specializationMembers.addAll(fields); specializationMembers.addAll(members); DSLExpressionResolver resolver = new DSLExpressionResolver(context, specializationMembers); initializeCaches(specialization, resolver); initializeGuards(specialization, resolver); if (specialization.hasErrors()) { continue; } initializeLimit(specialization, resolver); initializeAssumptions(specialization, resolver); } }
private NodeData parseChildNodeData(NodeData parentNode, NodeChildData child, TypeElement originalTemplateType) { TypeElement templateType = ElementUtils.fromTypeMirror(context.reloadTypeElement(originalTemplateType)); if (ElementUtils.findAnnotationMirror(processingEnv, originalTemplateType, GeneratedBy.class) != null) { // generated nodes should not get called again. return null; } if (!ElementUtils.isAssignable(templateType.asType(), context.getTruffleTypes().getNode())) { return null; } List<TypeElement> lookupTypes = collectSuperClasses(new ArrayList<TypeElement>(), templateType); // Declaration order is not required for child nodes. List<? extends Element> members = processingEnv.getElementUtils().getAllMembers(templateType); NodeData node = parseNodeData(templateType, lookupTypes); if (node.hasErrors()) { return node; } List<TypeMirror> frameTypes = Collections.emptyList(); if (parentNode.getFrameType() != null) { frameTypes = Arrays.asList(parentNode.getFrameType()); } node.getExecutableTypes().addAll(parseExecutableTypeData(node, members, child.getExecuteWith().size(), frameTypes, true)); node.setFrameType(parentNode.getFrameType()); return node; }
private void initializeChildren(NodeData node) { initializeExecuteWith(node); for (NodeChildData child : node.getChildren()) { TypeMirror nodeType = child.getNodeType(); NodeData fieldNodeData = parseChildNodeData(node, child, ElementUtils.fromTypeMirror(nodeType)); child.setNode(fieldNodeData); if (fieldNodeData == null || fieldNodeData.hasErrors()) { child.addError("Node type '%s' is invalid or not a subclass of Node.", ElementUtils.getQualifiedName(nodeType)); } else { List<ExecutableTypeData> types = child.findGenericExecutableTypes(context); if (types.isEmpty()) { AnnotationValue executeWithValue = ElementUtils.getAnnotationValue(child.getMessageAnnotation(), "executeWith"); child.addError(executeWithValue, "No generic execute method found with %s evaluated arguments for node type %s and frame types %s.", child.getExecuteWith().size(), ElementUtils.getSimpleName(nodeType), ElementUtils.getUniqueIdentifiers(createAllowedChildFrameTypes(node))); } } } }
List<ExecutableTypeData> rootTypes = buildExecutableHierarchy(node); List<ExecutableTypeData> additionalAbstractRootTypes = new ArrayList<>(); for (int i = 1; i < rootTypes.size(); i++) { namesUnique(node.getExecutableTypes());
NodeData fieldNodeData = parseChildNodeData(node, child, ElementUtils.fromTypeMirror(nodeType)); AnnotationValue executeWithValue = child.getExecuteWithValue(); child.addError(executeWithValue, "No generic execute method found with %s evaluated arguments for node type %s and frame types %s.", child.getExecuteWith().size(), ElementUtils.getSimpleName(nodeType), ElementUtils.getUniqueIdentifiers(createAllowedChildFrameTypes(node)));
private List<AnnotationProcessor<?>> getGenerators() { if (generators == null && processingEnv != null) { generators = new ArrayList<>(); generators.add(new AnnotationProcessor<>(new TypeSystemParser(), new TypeSystemCodeGenerator())); generators.add(new AnnotationProcessor<>(new NodeParser(), new NodeCodeGenerator())); } return generators; }
@Override protected NodeData filterErrorElements(NodeData model) { for (Iterator<NodeData> iterator = model.getEnclosingNodes().iterator(); iterator.hasNext();) { NodeData node = filterErrorElements(iterator.next()); if (node == null) { iterator.remove(); } } if (model.hasErrors()) { return null; } return model; }
private SpecializationData createGenericSpecialization(final NodeData node) { FallbackParser parser = new FallbackParser(context, node); MethodSpec specification = parser.createDefaultMethodSpec(node.getSpecializations().iterator().next().getMethod(), null, true, null); List<VariableElement> parameterTypes = new ArrayList<>(); int signatureIndex = 1; for (ParameterSpec spec : specification.getRequired()) { parameterTypes.add(new CodeVariableElement(createGenericType(node, spec), "arg" + signatureIndex)); if (spec.isSignature()) { signatureIndex++; } } TypeMirror returnType = createGenericType(node, specification.getReturnType()); SpecializationData generic = parser.create("Generic", TemplateMethod.NO_NATURAL_ORDER, null, null, returnType, parameterTypes); if (generic == null) { throw new RuntimeException("Unable to create generic signature for node " + node.getNodeId() + " with " + parameterTypes + ". Specification " + specification + "."); } return generic; }
private void initializeGeneric(final NodeData node) { List<SpecializationData> generics = new ArrayList<>(); for (SpecializationData spec : node.getSpecializations()) { if (spec.isFallback()) { generics.add(spec); } } if (generics.size() == 1 && node.getSpecializations().size() == 1) { // TODO this limitation should be lifted for (SpecializationData generic : generics) { generic.addError("@%s defined but no @%s.", Fallback.class.getSimpleName(), Specialization.class.getSimpleName()); } } if (generics.isEmpty()) { node.getSpecializations().add(createGenericSpecialization(node)); } else { if (generics.size() > 1) { for (SpecializationData generic : generics) { generic.addError("Only one @%s is allowed per operation.", Fallback.class.getSimpleName()); } } } }
List<TypeElement> lookupTypes = collectSuperClasses(new ArrayList<TypeElement>(), templateType); List<Element> members = loadMembers(templateType); if (!containsSpecializations(members)) { return null; NodeData node = parseNodeData(templateType, lookupTypes); if (node.hasErrors()) { return node; node.getFields().addAll(parseFields(lookupTypes, members)); node.getChildren().addAll(parseChildren(lookupTypes, members)); node.getChildExecutions().addAll(parseExecutions(node.getFields(), node.getChildren(), members)); node.getExecutableTypes().addAll(parseExecutableTypeData(node, members, node.getSignatureSize(), context.getFrameTypes(), false)); initializeExecutableTypes(node); initializeImportGuards(node, lookupTypes, members); initializeChildren(node); initializeSpecializations(members, node); initializeExecutableTypeHierarchy(node); verifySpecializationSameLength(node); initializeShortCircuits(node); // requires specializations and polymorphic specializations verifyVisibilities(node); verifyMissingAbstractMethods(node, members); verifyConstructors(node); verifyNamingConvention(node.getShortCircuits(), "needs");
private void initializeExpressions(List<? extends Element> elements, NodeData node) { List<Element> members = filterNotAccessibleElements(node.getTemplateType(), elements); List<VariableElement> fields = new ArrayList<>(); for (NodeFieldData field : node.getFields()) { fields.add(field.getVariable()); } for (SpecializationData specialization : node.getSpecializations()) { if (specialization.getMethod() == null) { continue; } List<Element> specializationMembers = new ArrayList<>(members.size() + specialization.getParameters().size() + fields.size()); for (Parameter p : specialization.getParameters()) { specializationMembers.add(p.getVariableElement()); } specializationMembers.addAll(fields); specializationMembers.addAll(members); DSLExpressionResolver resolver = new DSLExpressionResolver(context, specializationMembers); initializeCaches(specialization, resolver); initializeGuards(specialization, resolver); if (specialization.hasErrors()) { continue; } initializeLimit(specialization, resolver); initializeAssumptions(specialization, resolver); } }
private NodeData parseChildNodeData(NodeData parentNode, NodeChildData child, TypeElement originalTemplateType) { TypeElement templateType = ElementUtils.fromTypeMirror(context.reloadTypeElement(originalTemplateType)); if (ElementUtils.findAnnotationMirror(processingEnv, originalTemplateType, GeneratedBy.class) != null) { // generated nodes should not get called again. return null; } if (!ElementUtils.isAssignable(templateType.asType(), context.getTruffleTypes().getNode())) { return null; } List<TypeElement> lookupTypes = collectSuperClasses(new ArrayList<TypeElement>(), templateType); // Declaration order is not required for child nodes. List<? extends Element> members = processingEnv.getElementUtils().getAllMembers(templateType); NodeData node = parseNodeData(templateType, lookupTypes); if (node.hasErrors()) { return node; } List<TypeMirror> frameTypes = Collections.emptyList(); if (parentNode.getFrameType() != null) { frameTypes = Arrays.asList(parentNode.getFrameType()); } node.getExecutableTypes().addAll(parseExecutableTypeData(node, members, child.getExecuteWith().size(), frameTypes, true)); node.setFrameType(parentNode.getFrameType()); return node; }
List<ExecutableTypeData> rootTypes = buildExecutableHierarchy(node); List<ExecutableTypeData> additionalAbstractRootTypes = new ArrayList<>(); for (int i = 1; i < rootTypes.size(); i++) { namesUnique(node.getExecutableTypes());
private List<AnnotationProcessor<?>> getGenerators() { if (generators == null && processingEnv != null) { generators = new ArrayList<>(); generators.add(new AnnotationProcessor<>(new TypeSystemParser(), new TypeSystemCodeGenerator())); generators.add(new AnnotationProcessor<>(new NodeParser(), new NodeCodeGenerator())); } return generators; }
@Override protected NodeData filterErrorElements(NodeData model) { for (Iterator<NodeData> iterator = model.getEnclosingNodes().iterator(); iterator.hasNext();) { NodeData node = filterErrorElements(iterator.next()); if (node == null) { iterator.remove(); } } if (model.hasErrors()) { return null; } return model; }
private SpecializationData createGenericSpecialization(final NodeData node) { FallbackParser parser = new FallbackParser(context, node); MethodSpec specification = parser.createDefaultMethodSpec(node.getSpecializations().iterator().next().getMethod(), null, true, null); List<VariableElement> parameterTypes = new ArrayList<>(); int signatureIndex = 1; for (ParameterSpec spec : specification.getRequired()) { parameterTypes.add(new CodeVariableElement(createGenericType(node, spec), "arg" + signatureIndex)); if (spec.isSignature()) { signatureIndex++; } } TypeMirror returnType = createGenericType(node, specification.getReturnType()); SpecializationData generic = parser.create("Generic", TemplateMethod.NO_NATURAL_ORDER, null, null, returnType, parameterTypes); if (generic == null) { throw new RuntimeException("Unable to create generic signature for node " + node.getNodeId() + " with " + parameterTypes + ". Specification " + specification + "."); } return generic; }