comparison 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
comparison
equal deleted inserted replaced
21950:2a5011c7e641 21951:9c8c0937da41
1 /*
2 * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23 package com.oracle.truffle.dsl.processor.generator;
24
25 import static com.oracle.truffle.dsl.processor.java.ElementUtils.*;
26 import static javax.lang.model.element.Modifier.*;
27
28 import java.util.*;
29
30 import javax.lang.model.element.*;
31 import javax.lang.model.type.*;
32 import javax.lang.model.util.*;
33
34 import com.oracle.truffle.api.dsl.*;
35 import com.oracle.truffle.dsl.processor.*;
36 import com.oracle.truffle.dsl.processor.java.*;
37 import com.oracle.truffle.dsl.processor.java.model.*;
38 import com.oracle.truffle.dsl.processor.model.*;
39
40 public class NodeCodeGenerator extends CodeTypeElementFactory<NodeData> {
41
42 @Override
43 public CodeTypeElement create(ProcessorContext context, NodeData node) {
44 List<CodeTypeElement> enclosedTypes = new ArrayList<>();
45 for (NodeData childNode : node.getEnclosingNodes()) {
46 CodeTypeElement type = create(context, childNode);
47 if (type != null) {
48 enclosedTypes.add(type);
49 }
50 }
51 List<CodeTypeElement> generatedNodes = generateNodes(context, node);
52
53 if (!generatedNodes.isEmpty() || !enclosedTypes.isEmpty()) {
54 CodeTypeElement type;
55 if (generatedNodes.isEmpty()) {
56 type = createContainer(node);
57 } else {
58 type = wrapGeneratedNodes(context, node, generatedNodes);
59 }
60
61 for (CodeTypeElement enclosedFactory : enclosedTypes) {
62 type.add(makeInnerClass(enclosedFactory));
63 }
64
65 if (node.getDeclaringNode() == null && enclosedTypes.size() > 0) {
66 ExecutableElement getFactories = createGetFactories(context, node);
67 if (getFactories != null) {
68 type.add(getFactories);
69 }
70 }
71
72 return type;
73 } else {
74 return null;
75 }
76 }
77
78 private static CodeTypeElement makeInnerClass(CodeTypeElement type) {
79 Set<Modifier> modifiers = type.getModifiers();
80 modifiers.add(Modifier.STATIC);
81 return type;
82 }
83
84 private static CodeTypeElement wrapGeneratedNodes(ProcessorContext context, NodeData node, List<CodeTypeElement> generatedNodes) {
85 if (node.isGenerateFactory()) {
86 // wrap all types into a generated factory
87 CodeTypeElement factoryElement = new NodeFactoryFactory(context, node, generatedNodes.get(0)).create();
88 for (CodeTypeElement generatedNode : generatedNodes) {
89 factoryElement.add(makeInnerClass(generatedNode));
90 }
91 return factoryElement;
92 } else {
93 // wrap all types into the first node
94 CodeTypeElement first = generatedNodes.get(0);
95 CodeTypeElement second = first;
96 if (generatedNodes.size() > 1) {
97 second = generatedNodes.get(1);
98 for (CodeTypeElement generatedNode : generatedNodes) {
99 if (first != generatedNode) {
100 first.add(makeInnerClass(generatedNode));
101 }
102 }
103 }
104 new NodeFactoryFactory(context, node, second).createFactoryMethods(first);
105 ElementUtils.setVisibility(first.getModifiers(), ElementUtils.getVisibility(node.getTemplateType().getModifiers()));
106
107 return first;
108 }
109 }
110
111 private static CodeTypeElement createContainer(NodeData node) {
112 CodeTypeElement container;
113 Modifier visibility = ElementUtils.getVisibility(node.getTemplateType().getModifiers());
114 String containerName = NodeFactoryFactory.factoryClassName(node);
115 container = GeneratorUtils.createClass(node, null, modifiers(), containerName, null);
116 if (visibility != null) {
117 container.getModifiers().add(visibility);
118 }
119 container.getModifiers().add(Modifier.FINAL);
120
121 return container;
122 }
123
124 private static String getAccessorClassName(NodeData node) {
125 return node.isGenerateFactory() ? NodeFactoryFactory.factoryClassName(node) : NodeGenFactory.nodeTypeName(node);
126 }
127
128 private static List<CodeTypeElement> generateNodes(ProcessorContext context, NodeData node) {
129 if (!node.needsFactory()) {
130 return Collections.emptyList();
131 }
132 return Arrays.asList(new NodeGenFactory(context, node).create());
133 }
134
135 private static ExecutableElement createGetFactories(ProcessorContext context, NodeData node) {
136 List<NodeData> factoryList = node.getNodesWithFactories();
137 if (node.needsFactory() && node.isGenerateFactory()) {
138 factoryList.add(node);
139 }
140
141 if (factoryList.isEmpty()) {
142 return null;
143 }
144
145 List<TypeMirror> nodeTypesList = new ArrayList<>();
146 TypeMirror prev = null;
147 boolean allSame = true;
148 for (NodeData child : factoryList) {
149 nodeTypesList.add(child.getNodeType());
150 if (prev != null && !ElementUtils.typeEquals(child.getNodeType(), prev)) {
151 allSame = false;
152 }
153 prev = child.getNodeType();
154 }
155 TypeMirror commonNodeSuperType = ElementUtils.getCommonSuperType(context, nodeTypesList);
156
157 Types types = context.getEnvironment().getTypeUtils();
158 TypeMirror factoryType = context.getType(NodeFactory.class);
159 TypeMirror baseType;
160 if (allSame) {
161 baseType = ElementUtils.getDeclaredType(ElementUtils.fromTypeMirror(factoryType), commonNodeSuperType);
162 } else {
163 baseType = ElementUtils.getDeclaredType(ElementUtils.fromTypeMirror(factoryType), types.getWildcardType(commonNodeSuperType, null));
164 }
165 TypeMirror listType = ElementUtils.getDeclaredType(ElementUtils.fromTypeMirror(context.getType(List.class)), baseType);
166
167 CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, STATIC), listType, "getFactories");
168
169 CodeTreeBuilder builder = method.createBuilder();
170 builder.startReturn();
171
172 if (factoryList.size() > 1) {
173 builder.startStaticCall(context.getType(Arrays.class), "asList");
174 } else {
175 builder.startStaticCall(context.getType(Collections.class), "singletonList");
176 }
177
178 for (NodeData child : factoryList) {
179 builder.startGroup();
180 NodeData childNode = child;
181 List<NodeData> factories = new ArrayList<>();
182 while (childNode.getDeclaringNode() != null) {
183 factories.add(childNode);
184 childNode = childNode.getDeclaringNode();
185 }
186 Collections.reverse(factories);
187 for (NodeData nodeData : factories) {
188
189 builder.string(getAccessorClassName(nodeData)).string(".");
190 }
191 builder.string("getInstance()");
192 builder.end();
193 }
194 builder.end();
195 builder.end();
196
197 return method;
198 }
199
200 }