Search in sources :

Example 1 with Child

use of com.oracle.truffle.api.nodes.Node.Child 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 2 with Child

use of com.oracle.truffle.api.nodes.Node.Child in project graal by oracle.

the class FlatNodeGenFactory method create.

public CodeTypeElement create(CodeTypeElement clazz) {
    for (NodeChildData child : node.getChildren()) {
        clazz.addOptional(createAccessChildMethod(child));
    }
    for (NodeFieldData field : node.getFields()) {
        if (!field.isGenerated()) {
            continue;
        }
        clazz.add(new CodeVariableElement(modifiers(PRIVATE, FINAL), field.getType(), field.getName()));
        if (field.getGetter() != null && field.getGetter().getModifiers().contains(Modifier.ABSTRACT)) {
            CodeExecutableElement method = CodeExecutableElement.clone(context.getEnvironment(), field.getGetter());
            method.getModifiers().remove(Modifier.ABSTRACT);
            method.createBuilder().startReturn().string("this.").string(field.getName()).end();
            clazz.add(method);
        }
    }
    for (ExecutableElement superConstructor : GeneratorUtils.findUserConstructors(node.getTemplateType().asType())) {
        clazz.add(createNodeConstructor(clazz, superConstructor));
    }
    for (NodeExecutionData execution : node.getChildExecutions()) {
        if (execution.getChild() != null && execution.getChild().needsGeneratedField()) {
            clazz.add(createNodeField(PRIVATE, execution.getNodeType(), nodeFieldName(execution), Child.class));
        }
    }
    createFields(clazz);
    TypeMirror genericReturnType = node.getPolymorphicSpecialization().getReturnType().getType();
    List<ExecutableTypeData> executableTypes = filterExecutableTypes(node.getExecutableTypes(), reachableSpecializations);
    List<ExecutableTypeData> genericExecutableTypes = new ArrayList<>();
    List<ExecutableTypeData> specializedExecutableTypes = new ArrayList<>();
    List<ExecutableTypeData> voidExecutableTypes = new ArrayList<>();
    for (ExecutableTypeData type : executableTypes) {
        if (ElementUtils.isVoid(type.getReturnType())) {
            voidExecutableTypes.add(type);
        } else if (type.hasUnexpectedValue(context) && !ElementUtils.typeEquals(genericReturnType, type.getReturnType())) {
            specializedExecutableTypes.add(type);
        } else {
            genericExecutableTypes.add(type);
        }
    }
    if (genericExecutableTypes.size() > 1) {
        boolean hasGenericTypeMatch = false;
        for (ExecutableTypeData genericExecutable : genericExecutableTypes) {
            if (ElementUtils.typeEquals(genericExecutable.getReturnType(), genericReturnType)) {
                hasGenericTypeMatch = true;
                break;
            }
        }
        if (hasGenericTypeMatch) {
            for (ListIterator<ExecutableTypeData> iterator = genericExecutableTypes.listIterator(); iterator.hasNext(); ) {
                ExecutableTypeData executableTypeData = iterator.next();
                if (!ElementUtils.typeEquals(genericReturnType, executableTypeData.getReturnType())) {
                    iterator.remove();
                    specializedExecutableTypes.add(executableTypeData);
                }
            }
        }
    }
    SpecializationData fallback = node.getGenericSpecialization();
    if (fallback.getMethod() != null && fallback.isReachable()) {
        clazz.add(createFallbackGuard());
    }
    for (ExecutableTypeData type : genericExecutableTypes) {
        createExecute(clazz, type, Collections.<ExecutableTypeData>emptyList());
    }
    for (ExecutableTypeData type : specializedExecutableTypes) {
        createExecute(clazz, type, genericExecutableTypes);
    }
    for (ExecutableTypeData type : voidExecutableTypes) {
        List<ExecutableTypeData> genericAndSpecialized = new ArrayList<>();
        genericAndSpecialized.addAll(genericExecutableTypes);
        genericAndSpecialized.addAll(specializedExecutableTypes);
        createExecute(clazz, type, genericAndSpecialized);
    }
    clazz.addOptional(createExecuteAndSpecialize());
    if (shouldReportPolymorphism(node, reachableSpecializations)) {
        clazz.addOptional(createCheckForPolymorphicSpecialize());
        if (requiresCacheCheck()) {
            clazz.addOptional(createCountCaches());
        }
    }
    NodeInfo nodeInfo = node.getTemplateType().getAnnotation(NodeInfo.class);
    if (nodeInfo == null || nodeInfo.cost() == NodeCost.MONOMORPHIC) /* the default */
    {
        clazz.add(createGetCostMethod());
    }
    for (TypeMirror type : ElementUtils.uniqueSortedTypes(expectedTypes, false)) {
        if (!typeSystem.hasType(type)) {
            clazz.addOptional(TypeSystemCodeGenerator.createExpectMethod(PRIVATE, typeSystem, context.getType(Object.class), type));
        }
    }
    for (TypeMirror assumptionType : isValidSignatures.values()) {
        clazz.add(createIsValid(assumptionType));
    }
    clazz.getEnclosedElements().addAll(removeThisMethods.values());
    for (SpecializationData specialization : specializationClasses.keySet()) {
        CodeTypeElement type = specializationClasses.get(specialization);
        if (getInsertAccessorSet(true).contains(specialization)) {
            type.add(createInsertAccessor(true));
        } else if (getInsertAccessorSet(false).contains(specialization)) {
            type.add(createInsertAccessor(false));
        }
    }
    if (node.isReflectable()) {
        generateReflectionInfo(clazz);
    }
    return clazz;
}
Also used : ExecutableTypeData(com.oracle.truffle.dsl.processor.model.ExecutableTypeData) CodeExecutableElement(com.oracle.truffle.dsl.processor.java.model.CodeExecutableElement) NodeChildData(com.oracle.truffle.dsl.processor.model.NodeChildData) NodeExecutionData(com.oracle.truffle.dsl.processor.model.NodeExecutionData) CodeExecutableElement(com.oracle.truffle.dsl.processor.java.model.CodeExecutableElement) ExecutableElement(javax.lang.model.element.ExecutableElement) ArrayList(java.util.ArrayList) SpecializationData(com.oracle.truffle.dsl.processor.model.SpecializationData) NodeFieldData(com.oracle.truffle.dsl.processor.model.NodeFieldData) DeclaredCodeTypeMirror(com.oracle.truffle.dsl.processor.java.model.CodeTypeMirror.DeclaredCodeTypeMirror) ArrayCodeTypeMirror(com.oracle.truffle.dsl.processor.java.model.CodeTypeMirror.ArrayCodeTypeMirror) GeneratedTypeMirror(com.oracle.truffle.dsl.processor.java.model.GeneratedTypeMirror) TypeMirror(javax.lang.model.type.TypeMirror) CodeTypeElement(com.oracle.truffle.dsl.processor.java.model.CodeTypeElement) NodeInfo(com.oracle.truffle.api.nodes.NodeInfo) CodeVariableElement(com.oracle.truffle.dsl.processor.java.model.CodeVariableElement) Child(com.oracle.truffle.api.nodes.Node.Child)

Aggregations

Child (com.oracle.truffle.api.nodes.Node.Child)2 CodeExecutableElement (com.oracle.truffle.dsl.processor.java.model.CodeExecutableElement)2 ArrayCodeTypeMirror (com.oracle.truffle.dsl.processor.java.model.CodeTypeMirror.ArrayCodeTypeMirror)2 CodeVariableElement (com.oracle.truffle.dsl.processor.java.model.CodeVariableElement)2 NodeChildData (com.oracle.truffle.dsl.processor.model.NodeChildData)2 ArrayList (java.util.ArrayList)2 ExecutableElement (javax.lang.model.element.ExecutableElement)2 TypeMirror (javax.lang.model.type.TypeMirror)2 Executed (com.oracle.truffle.api.dsl.Executed)1 NodeChild (com.oracle.truffle.api.dsl.NodeChild)1 NodeChildren (com.oracle.truffle.api.dsl.NodeChildren)1 Children (com.oracle.truffle.api.nodes.Node.Children)1 NodeInfo (com.oracle.truffle.api.nodes.NodeInfo)1 CodeTypeElement (com.oracle.truffle.dsl.processor.java.model.CodeTypeElement)1 DeclaredCodeTypeMirror (com.oracle.truffle.dsl.processor.java.model.CodeTypeMirror.DeclaredCodeTypeMirror)1 GeneratedTypeMirror (com.oracle.truffle.dsl.processor.java.model.GeneratedTypeMirror)1 ExecutableTypeData (com.oracle.truffle.dsl.processor.model.ExecutableTypeData)1 Cardinality (com.oracle.truffle.dsl.processor.model.NodeChildData.Cardinality)1 NodeExecutionData (com.oracle.truffle.dsl.processor.model.NodeExecutionData)1 NodeFieldData (com.oracle.truffle.dsl.processor.model.NodeFieldData)1