Mercurial > hg > truffle
diff graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeCodeGenerator.java @ 18754:59bf50cc5a32
Truffle-DSL: implemented @GenerateNodeFactory to enable generation of factories. Factory generation is now disabled by default.
author | Christian Humer <christian.humer@gmail.com> |
---|---|
date | Mon, 29 Dec 2014 23:38:25 +0100 |
parents | f6b8787dc113 |
children | a665483c3881 |
line wrap: on
line diff
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeCodeGenerator.java Mon Dec 29 23:38:21 2014 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeCodeGenerator.java Mon Dec 29 23:38:25 2014 +0100 @@ -22,11 +22,18 @@ */ package com.oracle.truffle.dsl.processor.generator; +import static com.oracle.truffle.dsl.processor.java.ElementUtils.*; +import static javax.lang.model.element.Modifier.*; + import java.util.*; import javax.lang.model.element.*; +import javax.lang.model.type.*; +import javax.lang.model.util.*; +import com.oracle.truffle.api.dsl.*; import com.oracle.truffle.dsl.processor.*; +import com.oracle.truffle.dsl.processor.java.*; import com.oracle.truffle.dsl.processor.java.model.*; import com.oracle.truffle.dsl.processor.model.*; @@ -44,28 +51,82 @@ List<CodeTypeElement> generatedNodes = generateNodes(context, node); if (!generatedNodes.isEmpty() || !enclosedTypes.isEmpty()) { - CodeTypeElement type = wrapGeneratedNodes(context, node, generatedNodes); + + CodeTypeElement type; + if (generatedNodes.isEmpty()) { + type = createContainer(node); + } else { + type = wrapGeneratedNodes(context, node, generatedNodes); + } for (CodeTypeElement enclosedFactory : enclosedTypes) { - Set<Modifier> modifiers = enclosedFactory.getModifiers(); - if (!modifiers.contains(Modifier.STATIC)) { - modifiers.add(Modifier.STATIC); + type.add(makeInnerClass(enclosedFactory)); + } + + if (node.getDeclaringNode() == null && enclosedTypes.size() > 0) { + ExecutableElement getFactories = createGetFactories(context, node); + if (getFactories != null) { + type.add(getFactories); } - type.add(enclosedFactory); } + return type; } else { return null; } } + private static CodeTypeElement makeInnerClass(CodeTypeElement type) { + Set<Modifier> modifiers = type.getModifiers(); + if (!modifiers.contains(Modifier.STATIC)) { + modifiers.add(Modifier.STATIC); + } + return type; + } + private static CodeTypeElement wrapGeneratedNodes(ProcessorContext context, NodeData node, List<CodeTypeElement> generatedNodes) { - // wrap all types into a generated factory - CodeTypeElement factoryElement = new NodeFactoryFactory(context, node, generatedNodes.isEmpty() ? null : generatedNodes.get(0)).create(); - for (CodeTypeElement generatedNode : generatedNodes) { - factoryElement.add(generatedNode); + if (node.isGenerateFactory()) { + // wrap all types into a generated factory + CodeTypeElement factoryElement = new NodeFactoryFactory(context, node, generatedNodes.get(0)).create(); + for (CodeTypeElement generatedNode : generatedNodes) { + factoryElement.add(makeInnerClass(generatedNode)); + } + return factoryElement; + } else { + // wrap all types into the first node + CodeTypeElement first = generatedNodes.get(0); + CodeTypeElement last = generatedNodes.get(1); + + for (CodeTypeElement generatedNode : generatedNodes) { + if (first != generatedNode) { + first.add(makeInnerClass(generatedNode)); + } + } + ElementUtils.setVisibility(first.getModifiers(), ElementUtils.getVisibility(node.getTemplateType().getModifiers())); + for (ExecutableElement constructor : ElementFilter.constructorsIn(first.getEnclosedElements())) { + ElementUtils.setVisibility(((CodeExecutableElement) constructor).getModifiers(), Modifier.PRIVATE); + } + + NodeFactoryFactory.createFactoryMethods(context, node, first, last, ElementUtils.getVisibility(node.getTemplateType().getModifiers())); + return first; } - return factoryElement; + } + + private static CodeTypeElement createContainer(NodeData node) { + CodeTypeElement container; + Modifier visibility = ElementUtils.getVisibility(node.getTemplateType().getModifiers()); + String containerName = NodeFactoryFactory.factoryClassName(node); + container = GeneratorUtils.createClass(node, modifiers(), containerName, null, false); + if (visibility != null) { + container.getModifiers().add(visibility); + } + container.getModifiers().add(Modifier.FINAL); + + return container; + } + + private static String getAccessorClassName(NodeData node) { + return node.isGenerateFactory() ? NodeFactoryFactory.factoryClassName(node) : NodeBaseFactory.baseClassName(node); } private static List<CodeTypeElement> generateNodes(ProcessorContext context, NodeData node) { @@ -91,4 +152,64 @@ return nodeTypes; } + private static ExecutableElement createGetFactories(ProcessorContext context, NodeData node) { + List<NodeData> factoryList = node.getNodesWithFactories(); + if (node.needsFactory() && node.isGenerateFactory()) { + factoryList.add(node); + } + + if (factoryList.isEmpty()) { + return null; + } + + List<TypeMirror> nodeTypesList = new ArrayList<>(); + TypeMirror prev = null; + boolean allSame = true; + for (NodeData child : factoryList) { + nodeTypesList.add(child.getNodeType()); + if (prev != null && !ElementUtils.typeEquals(child.getNodeType(), prev)) { + allSame = false; + } + prev = child.getNodeType(); + } + TypeMirror commonNodeSuperType = ElementUtils.getCommonSuperType(context, nodeTypesList.toArray(new TypeMirror[nodeTypesList.size()])); + + Types types = context.getEnvironment().getTypeUtils(); + TypeMirror factoryType = context.getType(NodeFactory.class); + TypeMirror baseType; + if (allSame) { + baseType = ElementUtils.getDeclaredType(ElementUtils.fromTypeMirror(factoryType), commonNodeSuperType); + } else { + baseType = ElementUtils.getDeclaredType(ElementUtils.fromTypeMirror(factoryType), types.getWildcardType(commonNodeSuperType, null)); + } + TypeMirror listType = ElementUtils.getDeclaredType(ElementUtils.fromTypeMirror(context.getType(List.class)), baseType); + + CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, STATIC), listType, "getFactories"); + + CodeTreeBuilder builder = method.createBuilder(); + builder.startReturn(); + builder.startStaticCall(context.getType(Arrays.class), "asList"); + + for (NodeData child : factoryList) { + builder.startGroup(); + NodeData childNode = child; + List<NodeData> factories = new ArrayList<>(); + while (childNode.getDeclaringNode() != null) { + factories.add(childNode); + childNode = childNode.getDeclaringNode(); + } + Collections.reverse(factories); + for (NodeData nodeData : factories) { + + builder.string(getAccessorClassName(nodeData)).string("."); + } + builder.string("getInstance()"); + builder.end(); + } + builder.end(); + builder.end(); + + return method; + } + }