Search in sources :

Example 1 with NodeChildData

use of com.oracle.truffle.dsl.processor.model.NodeChildData in project graal by oracle.

the class FlatNodeGenFactory method createThrowUnsupported.

private CodeTree createThrowUnsupported(final CodeTreeBuilder parent, final FrameState frameState) {
    CodeTreeBuilder builder = parent.create();
    builder.startThrow().startNew(context.getType(UnsupportedSpecializationException.class));
    builder.string("this");
    builder.startNewArray(new ArrayCodeTypeMirror(context.getType(Node.class)), null);
    List<CodeTree> values = new ArrayList<>();
    for (NodeExecutionData execution : node.getChildExecutions()) {
        NodeChildData child = execution.getChild();
        LocalVariable var = frameState.getValue(execution);
        if (child != null) {
            builder.string(accessNodeField(execution));
        } else {
            builder.string("null");
        }
        if (var != null) {
            values.add(var.createReference());
        }
    }
    builder.end();
    builder.trees(values.toArray(new CodeTree[0]));
    builder.end().end();
    return builder.build();
}
Also used : NodeExecutionData(com.oracle.truffle.dsl.processor.model.NodeExecutionData) NodeChildData(com.oracle.truffle.dsl.processor.model.NodeChildData) CodeTree(com.oracle.truffle.dsl.processor.java.model.CodeTree) UnsupportedSpecializationException(com.oracle.truffle.api.dsl.UnsupportedSpecializationException) ArrayList(java.util.ArrayList) CodeTreeBuilder(com.oracle.truffle.dsl.processor.java.model.CodeTreeBuilder) ArrayCodeTypeMirror(com.oracle.truffle.dsl.processor.java.model.CodeTypeMirror.ArrayCodeTypeMirror)

Example 2 with NodeChildData

use of com.oracle.truffle.dsl.processor.model.NodeChildData in project graal by oracle.

the class NodeParser method verifyMissingAbstractMethods.

private static void verifyMissingAbstractMethods(NodeData nodeData, List<? extends Element> originalElements) {
    if (!nodeData.needsFactory()) {
        // if we need go generate factory for it.
        return;
    }
    List<Element> elements = newElementList(originalElements);
    Set<Element> unusedElements = new HashSet<>(elements);
    for (ExecutableElement method : nodeData.getAllTemplateMethods()) {
        unusedElements.remove(method);
    }
    for (NodeFieldData field : nodeData.getFields()) {
        if (field.getGetter() != null) {
            unusedElements.remove(field.getGetter());
        }
    }
    for (NodeChildData child : nodeData.getChildren()) {
        if (child.getAccessElement() != null) {
            unusedElements.remove(child.getAccessElement());
        }
    }
    Map<String, List<ExecutableElement>> methodsByName = null;
    outer: for (ExecutableElement unusedMethod : ElementFilter.methodsIn(unusedElements)) {
        if (unusedMethod.getModifiers().contains(Modifier.ABSTRACT)) {
            // group by method name to avoid N^2 worst case complexity.
            if (methodsByName == null) {
                methodsByName = new HashMap<>();
                for (ExecutableElement m : ElementFilter.methodsIn(unusedElements)) {
                    String name = m.getSimpleName().toString();
                    List<ExecutableElement> groupedElements = methodsByName.get(name);
                    if (groupedElements == null) {
                        groupedElements = new ArrayList<>();
                        methodsByName.put(name, groupedElements);
                    }
                    groupedElements.add(m);
                }
            }
            for (ExecutableElement otherMethod : methodsByName.get(unusedMethod.getSimpleName().toString())) {
                if (unusedMethod == otherMethod) {
                    continue;
                }
                if (ProcessorContext.getInstance().getEnvironment().getElementUtils().overrides(otherMethod, unusedMethod, nodeData.getTemplateType())) {
                    // -> the method does not need an implementation.
                    continue outer;
                }
            }
            nodeData.addError("The type %s must implement the inherited abstract method %s.", ElementUtils.getSimpleName(nodeData.getTemplateType()), ElementUtils.getReadableSignature(unusedMethod));
        }
    }
}
Also used : NodeFieldData(com.oracle.truffle.dsl.processor.model.NodeFieldData) NodeChildData(com.oracle.truffle.dsl.processor.model.NodeChildData) HashMap(java.util.HashMap) TypeElement(javax.lang.model.element.TypeElement) CodeVariableElement(com.oracle.truffle.dsl.processor.java.model.CodeVariableElement) CodeExecutableElement(com.oracle.truffle.dsl.processor.java.model.CodeExecutableElement) Element(javax.lang.model.element.Element) VariableElement(javax.lang.model.element.VariableElement) ExecutableElement(javax.lang.model.element.ExecutableElement) CodeExecutableElement(com.oracle.truffle.dsl.processor.java.model.CodeExecutableElement) ExecutableElement(javax.lang.model.element.ExecutableElement) ArrayList(java.util.ArrayList) List(java.util.List) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet)

Example 3 with NodeChildData

use of com.oracle.truffle.dsl.processor.model.NodeChildData in project graal by oracle.

the class NodeParser method parseChildren.

private List<NodeChildData> parseChildren(NodeData node, final List<TypeElement> typeHierarchy, List<? extends Element> elements) {
    Map<String, TypeMirror> castNodeTypes = new HashMap<>();
    for (ExecutableElement method : ElementFilter.methodsIn(elements)) {
        AnnotationMirror mirror = ElementUtils.findAnnotationMirror(processingEnv, method, CreateCast.class);
        if (mirror != null) {
            List<String> children = (ElementUtils.getAnnotationValueList(String.class, mirror, "value"));
            if (children != null) {
                for (String child : children) {
                    castNodeTypes.put(child, method.getReturnType());
                }
            }
        }
    }
    List<NodeChildData> executedFieldChildren = new ArrayList<>();
    for (VariableElement field : ElementFilter.fieldsIn(elements)) {
        if (field.getModifiers().contains(Modifier.STATIC)) {
            continue;
        }
        AnnotationMirror executed = ElementUtils.findAnnotationMirror(field.getAnnotationMirrors(), context.getDeclaredType(Executed.class));
        if (executed != null) {
            TypeMirror type = field.asType();
            String name = field.getSimpleName().toString();
            Cardinality cardinality = Cardinality.ONE;
            if (type.getKind() == TypeKind.ARRAY) {
                cardinality = Cardinality.MANY;
            }
            AnnotationValue executedWith = ElementUtils.getAnnotationValue(executed, "with");
            NodeChildData child = new NodeChildData(field, executed, name, type, type, field, cardinality, executedWith);
            executedFieldChildren.add(child);
            if (field.getModifiers().contains(Modifier.PRIVATE)) {
                child.addError("Field annotated with @%s must be visible for the generated subclass to execute.", Executed.class.getSimpleName());
            }
            if (cardinality == Cardinality.ONE) {
                if (field.getAnnotation(Child.class) == null) {
                    child.addError("Field annotated with @%s must also be annotated with @%s.", Executed.class.getSimpleName(), Child.class.getSimpleName());
                }
            } else {
                assert cardinality == Cardinality.MANY;
                if (field.getAnnotation(Children.class) == null) {
                    child.addError("Field annotated with @%s must also be annotated with @%s.", Executed.class.getSimpleName(), Children.class.getSimpleName());
                }
            }
        }
    }
    NodeChildData many = null;
    Set<String> names = new HashSet<>();
    for (NodeChildData child : executedFieldChildren) {
        if (child.needsGeneratedField()) {
            throw new AssertionError("Should not need generated field.");
        }
        if (names.contains(child.getName())) {
            child.addError("Field annotated with @%s has duplicate name '%s'. " + "Executed children must have unique names.", Executed.class.getSimpleName(), child.getName());
        } else if (many != null) {
            child.addError("Field annotated with @%s is hidden by executed field '%s'. " + "Executed child fields with multiple children hide all following executed child declarations. " + "Reorder or remove this executed child declaration.", Executed.class.getSimpleName(), many.getName());
        } else if (child.getCardinality().isMany()) {
            many = child;
        }
        names.add(child.getName());
    }
    List<NodeChildData> nodeChildren = new ArrayList<>();
    List<TypeElement> typeHierarchyReversed = new ArrayList<>(typeHierarchy);
    Collections.reverse(typeHierarchyReversed);
    for (TypeElement type : typeHierarchyReversed) {
        AnnotationMirror nodeChildrenMirror = ElementUtils.findAnnotationMirror(processingEnv, type, NodeChildren.class);
        TypeMirror nodeClassType = type.getSuperclass();
        if (!ElementUtils.isAssignable(nodeClassType, context.getTruffleTypes().getNode())) {
            nodeClassType = null;
        }
        List<AnnotationMirror> children = ElementUtils.collectAnnotations(context, nodeChildrenMirror, "value", type, NodeChild.class);
        int index = 0;
        for (AnnotationMirror childMirror : children) {
            String name = ElementUtils.getAnnotationValue(String.class, childMirror, "value");
            if (name.equals("")) {
                name = "child" + index;
            }
            Cardinality cardinality = Cardinality.ONE;
            TypeMirror childNodeType = inheritType(childMirror, "type", nodeClassType);
            if (childNodeType.getKind() == TypeKind.ARRAY) {
                cardinality = Cardinality.MANY;
            }
            TypeMirror originalChildType = childNodeType;
            TypeMirror castNodeType = castNodeTypes.get(name);
            if (castNodeType != null) {
                childNodeType = castNodeType;
            }
            Element getter = findGetter(elements, name, childNodeType);
            AnnotationValue executeWith = ElementUtils.getAnnotationValue(childMirror, "executeWith");
            NodeChildData nodeChild = new NodeChildData(type, childMirror, name, childNodeType, originalChildType, getter, cardinality, executeWith);
            nodeChildren.add(nodeChild);
            if (nodeChild.getNodeType() == null) {
                nodeChild.addError("No valid node type could be resoleved.");
            }
            if (nodeChild.hasErrors()) {
                continue;
            }
            index++;
        }
    }
    if (!nodeChildren.isEmpty() && !executedFieldChildren.isEmpty()) {
        node.addError("The use of @%s and @%s at the same time is not supported.", NodeChild.class.getSimpleName(), Executed.class.getSimpleName());
        return executedFieldChildren;
    } else if (!executedFieldChildren.isEmpty()) {
        return executedFieldChildren;
    } else {
        List<NodeChildData> filteredChildren = new ArrayList<>();
        Set<String> encounteredNames = new HashSet<>();
        for (int i = nodeChildren.size() - 1; i >= 0; i--) {
            NodeChildData child = nodeChildren.get(i);
            if (!encounteredNames.contains(child.getName())) {
                filteredChildren.add(0, child);
                encounteredNames.add(child.getName());
            }
        }
        return filteredChildren;
    }
}
Also used : Set(java.util.Set) HashSet(java.util.HashSet) HashMap(java.util.HashMap) CodeExecutableElement(com.oracle.truffle.dsl.processor.java.model.CodeExecutableElement) ExecutableElement(javax.lang.model.element.ExecutableElement) TypeElement(javax.lang.model.element.TypeElement) CodeVariableElement(com.oracle.truffle.dsl.processor.java.model.CodeVariableElement) CodeExecutableElement(com.oracle.truffle.dsl.processor.java.model.CodeExecutableElement) Element(javax.lang.model.element.Element) VariableElement(javax.lang.model.element.VariableElement) ExecutableElement(javax.lang.model.element.ExecutableElement) ArrayList(java.util.ArrayList) CodeVariableElement(com.oracle.truffle.dsl.processor.java.model.CodeVariableElement) VariableElement(javax.lang.model.element.VariableElement) Executed(com.oracle.truffle.api.dsl.Executed) ArrayCodeTypeMirror(com.oracle.truffle.dsl.processor.java.model.CodeTypeMirror.ArrayCodeTypeMirror) TypeMirror(javax.lang.model.type.TypeMirror) List(java.util.List) ArrayList(java.util.ArrayList) Children(com.oracle.truffle.api.nodes.Node.Children) NodeChildren(com.oracle.truffle.api.dsl.NodeChildren) Child(com.oracle.truffle.api.nodes.Node.Child) NodeChild(com.oracle.truffle.api.dsl.NodeChild) HashSet(java.util.HashSet) NodeChildData(com.oracle.truffle.dsl.processor.model.NodeChildData) Cardinality(com.oracle.truffle.dsl.processor.model.NodeChildData.Cardinality) TypeElement(javax.lang.model.element.TypeElement) AnnotationMirror(javax.lang.model.element.AnnotationMirror) AnnotationValue(javax.lang.model.element.AnnotationValue) NodeChild(com.oracle.truffle.api.dsl.NodeChild)

Example 4 with NodeChildData

use of com.oracle.truffle.dsl.processor.model.NodeChildData in project graal by oracle.

the class NodeParser method parseExecutions.

private List<NodeExecutionData> parseExecutions(List<NodeFieldData> fields, List<NodeChildData> children, List<? extends Element> elements) {
    List<ExecutableElement> methods = ElementFilter.methodsIn(elements);
    boolean hasVarArgs = false;
    int maxSignatureSize = 0;
    if (!children.isEmpty()) {
        int lastIndex = children.size() - 1;
        hasVarArgs = children.get(lastIndex).getCardinality() == Cardinality.MANY;
        if (hasVarArgs) {
            maxSignatureSize = lastIndex;
        } else {
            maxSignatureSize = children.size();
        }
    }
    List<NodeFieldData> nonGetterFields = new ArrayList<>();
    for (NodeFieldData field : fields) {
        if (field.getGetter() == null && field.isGenerated()) {
            nonGetterFields.add(field);
        }
    }
    TypeMirror cacheAnnotation = context.getType(Cached.class);
    List<TypeMirror> frameTypes = context.getFrameTypes();
    // pre-parse specializations to find signature size
    for (ExecutableElement method : methods) {
        AnnotationMirror mirror = ElementUtils.findAnnotationMirror(processingEnv, method, Specialization.class);
        if (mirror == null) {
            continue;
        }
        int currentArgumentIndex = 0;
        parameter: for (VariableElement var : method.getParameters()) {
            TypeMirror type = var.asType();
            if (currentArgumentIndex == 0) {
                // skip optionals
                for (TypeMirror frameType : frameTypes) {
                    if (ElementUtils.typeEquals(type, frameType)) {
                        continue parameter;
                    }
                }
            }
            if (currentArgumentIndex < nonGetterFields.size()) {
                for (NodeFieldData field : nonGetterFields) {
                    if (ElementUtils.typeEquals(var.asType(), field.getType())) {
                        continue parameter;
                    }
                }
            }
            if (ElementUtils.findAnnotationMirror(var.getAnnotationMirrors(), cacheAnnotation) != null) {
                continue parameter;
            }
            currentArgumentIndex++;
        }
        maxSignatureSize = Math.max(maxSignatureSize, currentArgumentIndex);
    }
    List<NodeExecutionData> executions = new ArrayList<>();
    for (int i = 0; i < maxSignatureSize; i++) {
        boolean varArgParameter = false;
        int childIndex = i;
        if (i >= children.size() - 1) {
            if (hasVarArgs) {
                varArgParameter = hasVarArgs;
                childIndex = Math.min(i, children.size() - 1);
            } else if (i >= children.size()) {
                childIndex = -1;
            }
        }
        int varArgsIndex = -1;
        NodeChildData child = null;
        if (childIndex != -1) {
            varArgsIndex = varArgParameter ? Math.abs(childIndex - i) : -1;
            child = children.get(childIndex);
        }
        executions.add(new NodeExecutionData(child, i, varArgsIndex));
    }
    return executions;
}
Also used : NodeExecutionData(com.oracle.truffle.dsl.processor.model.NodeExecutionData) NodeChildData(com.oracle.truffle.dsl.processor.model.NodeChildData) CodeExecutableElement(com.oracle.truffle.dsl.processor.java.model.CodeExecutableElement) ExecutableElement(javax.lang.model.element.ExecutableElement) ArrayList(java.util.ArrayList) CodeVariableElement(com.oracle.truffle.dsl.processor.java.model.CodeVariableElement) VariableElement(javax.lang.model.element.VariableElement) AnnotationMirror(javax.lang.model.element.AnnotationMirror) NodeFieldData(com.oracle.truffle.dsl.processor.model.NodeFieldData) ArrayCodeTypeMirror(com.oracle.truffle.dsl.processor.java.model.CodeTypeMirror.ArrayCodeTypeMirror) TypeMirror(javax.lang.model.type.TypeMirror)

Example 5 with NodeChildData

use of com.oracle.truffle.dsl.processor.model.NodeChildData in project graal by oracle.

the class CreateCastParser method create.

@Override
public CreateCastData create(TemplateMethod method, boolean invalid) {
    AnnotationMirror mirror = method.getMarkerAnnotation();
    List<String> childNames = ElementUtils.getAnnotationValueList(String.class, mirror, "value");
    CreateCastData cast = new CreateCastData(method, childNames);
    AnnotationValue value = ElementUtils.getAnnotationValue(mirror, "value");
    TypeMirror type = null;
    if (childNames == null || childNames.isEmpty()) {
        cast.addError(value, "No value specified but required.");
        return cast;
    }
    for (String childName : childNames) {
        NodeChildData child = getNode().findChild(childName);
        if (child == null) {
            // error
            cast.addError(value, "Specified child '%s' not found.", childName);
            continue;
        }
        if (type == null) {
            type = child.getNodeType();
        } else if (!ElementUtils.typeEquals(type, child.getNodeType())) {
            cast.addError(value, "All child nodes for a cast must have the same node type.");
            continue;
        }
    }
    return cast;
}
Also used : CreateCastData(com.oracle.truffle.dsl.processor.model.CreateCastData) AnnotationMirror(javax.lang.model.element.AnnotationMirror) NodeChildData(com.oracle.truffle.dsl.processor.model.NodeChildData) TypeMirror(javax.lang.model.type.TypeMirror) AnnotationValue(javax.lang.model.element.AnnotationValue)

Aggregations

NodeChildData (com.oracle.truffle.dsl.processor.model.NodeChildData)13 ArrayList (java.util.ArrayList)10 TypeMirror (javax.lang.model.type.TypeMirror)8 ArrayCodeTypeMirror (com.oracle.truffle.dsl.processor.java.model.CodeTypeMirror.ArrayCodeTypeMirror)7 CodeExecutableElement (com.oracle.truffle.dsl.processor.java.model.CodeExecutableElement)6 CodeVariableElement (com.oracle.truffle.dsl.processor.java.model.CodeVariableElement)6 NodeExecutionData (com.oracle.truffle.dsl.processor.model.NodeExecutionData)6 ExecutableElement (javax.lang.model.element.ExecutableElement)5 ExecutableTypeData (com.oracle.truffle.dsl.processor.model.ExecutableTypeData)4 HashSet (java.util.HashSet)4 NodeFieldData (com.oracle.truffle.dsl.processor.model.NodeFieldData)3 List (java.util.List)3 AnnotationMirror (javax.lang.model.element.AnnotationMirror)3 AnnotationValue (javax.lang.model.element.AnnotationValue)3 VariableElement (javax.lang.model.element.VariableElement)3 Child (com.oracle.truffle.api.nodes.Node.Child)2 CodeTree (com.oracle.truffle.dsl.processor.java.model.CodeTree)2 CodeTreeBuilder (com.oracle.truffle.dsl.processor.java.model.CodeTreeBuilder)2 DeclaredCodeTypeMirror (com.oracle.truffle.dsl.processor.java.model.CodeTypeMirror.DeclaredCodeTypeMirror)2 GeneratedTypeMirror (com.oracle.truffle.dsl.processor.java.model.GeneratedTypeMirror)2