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;
}
}
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;
}
Aggregations