Search in sources :

Example 81 with AnnotationMirror

use of javax.lang.model.element.AnnotationMirror 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 82 with AnnotationMirror

use of javax.lang.model.element.AnnotationMirror in project graal by oracle.

the class NodeParser method initializeCaches.

private void initializeCaches(SpecializationData specialization, DSLExpressionResolver resolver) {
    TypeMirror cacheMirror = context.getType(Cached.class);
    List<CacheExpression> expressions = new ArrayList<>();
    for (Parameter parameter : specialization.getParameters()) {
        AnnotationMirror annotationMirror = ElementUtils.findAnnotationMirror(parameter.getVariableElement().getAnnotationMirrors(), cacheMirror);
        if (annotationMirror != null) {
            String initializer = ElementUtils.getAnnotationValue(String.class, annotationMirror, "value");
            TypeMirror parameterType = parameter.getType();
            DSLExpressionResolver localResolver = resolver;
            if (parameterType.getKind() == TypeKind.DECLARED) {
                localResolver = localResolver.copy(importPublicStaticMembers(ElementUtils.fromTypeMirror(parameterType), true));
            }
            CacheExpression cacheExpression;
            DSLExpression expression = null;
            try {
                expression = DSLExpression.parse(initializer);
                expression.accept(localResolver);
                cacheExpression = new CacheExpression(parameter, annotationMirror, expression);
                if (!ElementUtils.typeEquals(expression.getResolvedType(), parameter.getType())) {
                    cacheExpression.addError("Incompatible return type %s. The expression type must be equal to the parameter type %s.", ElementUtils.getSimpleName(expression.getResolvedType()), ElementUtils.getSimpleName(parameter.getType()));
                }
            } catch (InvalidExpressionException e) {
                cacheExpression = new CacheExpression(parameter, annotationMirror, null);
                cacheExpression.addError("Error parsing expression '%s': %s", initializer, e.getMessage());
            }
            if (!cacheExpression.hasErrors()) {
                Cached cached = cacheExpression.getParameter().getVariableElement().getAnnotation(Cached.class);
                cacheExpression.setDimensions(cached.dimensions());
                if (parameterType.getKind() == TypeKind.ARRAY && !ElementUtils.isSubtype(((ArrayType) parameterType).getComponentType(), context.getType(NodeInterface.class))) {
                    if (cacheExpression.getDimensions() == -1) {
                        cacheExpression.addWarning("The cached dimensions attribute must be specified for array types.");
                    }
                } else {
                    if (cacheExpression.getDimensions() != -1) {
                        cacheExpression.addError("The dimensions attribute has no affect for the type %s.", ElementUtils.getSimpleName(parameterType));
                    }
                }
            }
            expressions.add(cacheExpression);
        }
    }
    specialization.setCaches(expressions);
    if (specialization.hasErrors()) {
        return;
    }
    // verify that cache expressions are bound in the correct order.
    for (int i = 0; i < expressions.size(); i++) {
        CacheExpression currentExpression = expressions.get(i);
        Set<VariableElement> boundVariables = currentExpression.getExpression().findBoundVariableElements();
        for (int j = i + 1; j < expressions.size(); j++) {
            CacheExpression boundExpression = expressions.get(j);
            if (boundVariables.contains(boundExpression.getParameter().getVariableElement())) {
                currentExpression.addError("The initializer expression of parameter '%s' binds unitialized parameter '%s. Reorder the parameters to resolve the problem.", currentExpression.getParameter().getLocalName(), boundExpression.getParameter().getLocalName());
                break;
            }
        }
    }
}
Also used : ArrayList(java.util.ArrayList) CodeVariableElement(com.oracle.truffle.dsl.processor.java.model.CodeVariableElement) VariableElement(javax.lang.model.element.VariableElement) DSLExpression(com.oracle.truffle.dsl.processor.expression.DSLExpression) CacheExpression(com.oracle.truffle.dsl.processor.model.CacheExpression) AnnotationMirror(javax.lang.model.element.AnnotationMirror) ArrayCodeTypeMirror(com.oracle.truffle.dsl.processor.java.model.CodeTypeMirror.ArrayCodeTypeMirror) TypeMirror(javax.lang.model.type.TypeMirror) InvalidExpressionException(com.oracle.truffle.dsl.processor.expression.InvalidExpressionException) Cached(com.oracle.truffle.api.dsl.Cached) Parameter(com.oracle.truffle.dsl.processor.model.Parameter) DSLExpressionResolver(com.oracle.truffle.dsl.processor.expression.DSLExpressionResolver) NodeInterface(com.oracle.truffle.api.nodes.NodeInterface)

Example 83 with AnnotationMirror

use of javax.lang.model.element.AnnotationMirror 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 84 with AnnotationMirror

use of javax.lang.model.element.AnnotationMirror in project graal by oracle.

the class AbstractParser method parse.

public final M parse(Element element) {
    M model = null;
    try {
        AnnotationMirror mirror = null;
        if (getAnnotationType() != null) {
            mirror = ElementUtils.findAnnotationMirror(processingEnv, element.getAnnotationMirrors(), getAnnotationType());
        }
        if (!context.getTruffleTypes().verify(context, element, mirror)) {
            return null;
        }
        model = parse(element, mirror);
        if (model == null) {
            return null;
        }
        redirectMessages(new HashSet<MessageContainer>(), model, model);
        model.emitMessages(context, log);
        if (model instanceof NodeData) {
            return model;
        } else {
            return filterErrorElements(model);
        }
    } catch (CompileErrorException e) {
        log.message(Kind.WARNING, element, null, null, "The truffle processor could not parse class due to error: %s", e.getMessage());
        return null;
    }
}
Also used : AnnotationMirror(javax.lang.model.element.AnnotationMirror) MessageContainer(com.oracle.truffle.dsl.processor.model.MessageContainer) NodeData(com.oracle.truffle.dsl.processor.model.NodeData) CompileErrorException(com.oracle.truffle.dsl.processor.CompileErrorException)

Example 85 with AnnotationMirror

use of javax.lang.model.element.AnnotationMirror 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

AnnotationMirror (javax.lang.model.element.AnnotationMirror)665 TypeElement (javax.lang.model.element.TypeElement)159 ExecutableElement (javax.lang.model.element.ExecutableElement)112 TypeMirror (javax.lang.model.type.TypeMirror)99 ArrayList (java.util.ArrayList)92 AnnotatedTypeMirror (org.checkerframework.framework.type.AnnotatedTypeMirror)90 Element (javax.lang.model.element.Element)87 VariableElement (javax.lang.model.element.VariableElement)79 AnnotationValue (javax.lang.model.element.AnnotationValue)73 DeclaredType (javax.lang.model.type.DeclaredType)58 List (java.util.List)52 CFValue (org.checkerframework.framework.flow.CFValue)52 Map (java.util.Map)46 HashSet (java.util.HashSet)40 JavaExpression (org.checkerframework.dataflow.expression.JavaExpression)39 CFStore (org.checkerframework.framework.flow.CFStore)39 HashMap (java.util.HashMap)37 QualifierHierarchy (org.checkerframework.framework.type.QualifierHierarchy)36 ExpressionTree (com.sun.source.tree.ExpressionTree)30 MethodTree (com.sun.source.tree.MethodTree)29