diff truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeCodeGenerator.java @ 21951:9c8c0937da41

Moving all sources into truffle subdirectory
author Jaroslav Tulach <jaroslav.tulach@oracle.com>
date Wed, 17 Jun 2015 10:58:08 +0200
parents graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeCodeGenerator.java@37f65dc8c713
children dc83cc1f94f2
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeCodeGenerator.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,200 @@
+/*
+ * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+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.*;
+
+public class NodeCodeGenerator extends CodeTypeElementFactory<NodeData> {
+
+    @Override
+    public CodeTypeElement create(ProcessorContext context, NodeData node) {
+        List<CodeTypeElement> enclosedTypes = new ArrayList<>();
+        for (NodeData childNode : node.getEnclosingNodes()) {
+            CodeTypeElement type = create(context, childNode);
+            if (type != null) {
+                enclosedTypes.add(type);
+            }
+        }
+        List<CodeTypeElement> generatedNodes = generateNodes(context, node);
+
+        if (!generatedNodes.isEmpty() || !enclosedTypes.isEmpty()) {
+            CodeTypeElement type;
+            if (generatedNodes.isEmpty()) {
+                type = createContainer(node);
+            } else {
+                type = wrapGeneratedNodes(context, node, generatedNodes);
+            }
+
+            for (CodeTypeElement enclosedFactory : enclosedTypes) {
+                type.add(makeInnerClass(enclosedFactory));
+            }
+
+            if (node.getDeclaringNode() == null && enclosedTypes.size() > 0) {
+                ExecutableElement getFactories = createGetFactories(context, node);
+                if (getFactories != null) {
+                    type.add(getFactories);
+                }
+            }
+
+            return type;
+        } else {
+            return null;
+        }
+    }
+
+    private static CodeTypeElement makeInnerClass(CodeTypeElement type) {
+        Set<Modifier> modifiers = type.getModifiers();
+        modifiers.add(Modifier.STATIC);
+        return type;
+    }
+
+    private static CodeTypeElement wrapGeneratedNodes(ProcessorContext context, NodeData node, List<CodeTypeElement> generatedNodes) {
+        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 second = first;
+            if (generatedNodes.size() > 1) {
+                second = generatedNodes.get(1);
+                for (CodeTypeElement generatedNode : generatedNodes) {
+                    if (first != generatedNode) {
+                        first.add(makeInnerClass(generatedNode));
+                    }
+                }
+            }
+            new NodeFactoryFactory(context, node, second).createFactoryMethods(first);
+            ElementUtils.setVisibility(first.getModifiers(), ElementUtils.getVisibility(node.getTemplateType().getModifiers()));
+
+            return first;
+        }
+    }
+
+    private static CodeTypeElement createContainer(NodeData node) {
+        CodeTypeElement container;
+        Modifier visibility = ElementUtils.getVisibility(node.getTemplateType().getModifiers());
+        String containerName = NodeFactoryFactory.factoryClassName(node);
+        container = GeneratorUtils.createClass(node, null, modifiers(), containerName, null);
+        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) : NodeGenFactory.nodeTypeName(node);
+    }
+
+    private static List<CodeTypeElement> generateNodes(ProcessorContext context, NodeData node) {
+        if (!node.needsFactory()) {
+            return Collections.emptyList();
+        }
+        return Arrays.asList(new NodeGenFactory(context, node).create());
+    }
+
+    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);
+
+        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();
+
+        if (factoryList.size() > 1) {
+            builder.startStaticCall(context.getType(Arrays.class), "asList");
+        } else {
+            builder.startStaticCall(context.getType(Collections.class), "singletonList");
+        }
+
+        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;
+    }
+
+}