comparison 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
comparison
equal deleted inserted replaced
18753:f6b8787dc113 18754:59bf50cc5a32
20 * or visit www.oracle.com if you need additional information or have any 20 * or visit www.oracle.com if you need additional information or have any
21 * questions. 21 * questions.
22 */ 22 */
23 package com.oracle.truffle.dsl.processor.generator; 23 package com.oracle.truffle.dsl.processor.generator;
24 24
25 import static com.oracle.truffle.dsl.processor.java.ElementUtils.*;
26 import static javax.lang.model.element.Modifier.*;
27
25 import java.util.*; 28 import java.util.*;
26 29
27 import javax.lang.model.element.*; 30 import javax.lang.model.element.*;
28 31 import javax.lang.model.type.*;
32 import javax.lang.model.util.*;
33
34 import com.oracle.truffle.api.dsl.*;
29 import com.oracle.truffle.dsl.processor.*; 35 import com.oracle.truffle.dsl.processor.*;
36 import com.oracle.truffle.dsl.processor.java.*;
30 import com.oracle.truffle.dsl.processor.java.model.*; 37 import com.oracle.truffle.dsl.processor.java.model.*;
31 import com.oracle.truffle.dsl.processor.model.*; 38 import com.oracle.truffle.dsl.processor.model.*;
32 39
33 public class NodeCodeGenerator extends CodeTypeElementFactory<NodeData> { 40 public class NodeCodeGenerator extends CodeTypeElementFactory<NodeData> {
34 41
42 } 49 }
43 } 50 }
44 List<CodeTypeElement> generatedNodes = generateNodes(context, node); 51 List<CodeTypeElement> generatedNodes = generateNodes(context, node);
45 52
46 if (!generatedNodes.isEmpty() || !enclosedTypes.isEmpty()) { 53 if (!generatedNodes.isEmpty() || !enclosedTypes.isEmpty()) {
47 CodeTypeElement type = wrapGeneratedNodes(context, node, generatedNodes); 54
55 CodeTypeElement type;
56 if (generatedNodes.isEmpty()) {
57 type = createContainer(node);
58 } else {
59 type = wrapGeneratedNodes(context, node, generatedNodes);
60 }
48 61
49 for (CodeTypeElement enclosedFactory : enclosedTypes) { 62 for (CodeTypeElement enclosedFactory : enclosedTypes) {
50 Set<Modifier> modifiers = enclosedFactory.getModifiers(); 63 type.add(makeInnerClass(enclosedFactory));
51 if (!modifiers.contains(Modifier.STATIC)) { 64 }
52 modifiers.add(Modifier.STATIC); 65
66 if (node.getDeclaringNode() == null && enclosedTypes.size() > 0) {
67 ExecutableElement getFactories = createGetFactories(context, node);
68 if (getFactories != null) {
69 type.add(getFactories);
53 } 70 }
54 type.add(enclosedFactory); 71 }
55 } 72
56 return type; 73 return type;
57 } else { 74 } else {
58 return null; 75 return null;
59 } 76 }
60 } 77 }
61 78
79 private static CodeTypeElement makeInnerClass(CodeTypeElement type) {
80 Set<Modifier> modifiers = type.getModifiers();
81 if (!modifiers.contains(Modifier.STATIC)) {
82 modifiers.add(Modifier.STATIC);
83 }
84 return type;
85 }
86
62 private static CodeTypeElement wrapGeneratedNodes(ProcessorContext context, NodeData node, List<CodeTypeElement> generatedNodes) { 87 private static CodeTypeElement wrapGeneratedNodes(ProcessorContext context, NodeData node, List<CodeTypeElement> generatedNodes) {
63 // wrap all types into a generated factory 88 if (node.isGenerateFactory()) {
64 CodeTypeElement factoryElement = new NodeFactoryFactory(context, node, generatedNodes.isEmpty() ? null : generatedNodes.get(0)).create(); 89 // wrap all types into a generated factory
65 for (CodeTypeElement generatedNode : generatedNodes) { 90 CodeTypeElement factoryElement = new NodeFactoryFactory(context, node, generatedNodes.get(0)).create();
66 factoryElement.add(generatedNode); 91 for (CodeTypeElement generatedNode : generatedNodes) {
67 } 92 factoryElement.add(makeInnerClass(generatedNode));
68 return factoryElement; 93 }
94 return factoryElement;
95 } else {
96 // wrap all types into the first node
97 CodeTypeElement first = generatedNodes.get(0);
98 CodeTypeElement last = generatedNodes.get(1);
99
100 for (CodeTypeElement generatedNode : generatedNodes) {
101 if (first != generatedNode) {
102 first.add(makeInnerClass(generatedNode));
103 }
104 }
105 ElementUtils.setVisibility(first.getModifiers(), ElementUtils.getVisibility(node.getTemplateType().getModifiers()));
106 for (ExecutableElement constructor : ElementFilter.constructorsIn(first.getEnclosedElements())) {
107 ElementUtils.setVisibility(((CodeExecutableElement) constructor).getModifiers(), Modifier.PRIVATE);
108 }
109
110 NodeFactoryFactory.createFactoryMethods(context, node, first, last, ElementUtils.getVisibility(node.getTemplateType().getModifiers()));
111 return first;
112 }
113 }
114
115 private static CodeTypeElement createContainer(NodeData node) {
116 CodeTypeElement container;
117 Modifier visibility = ElementUtils.getVisibility(node.getTemplateType().getModifiers());
118 String containerName = NodeFactoryFactory.factoryClassName(node);
119 container = GeneratorUtils.createClass(node, modifiers(), containerName, null, false);
120 if (visibility != null) {
121 container.getModifiers().add(visibility);
122 }
123 container.getModifiers().add(Modifier.FINAL);
124
125 return container;
126 }
127
128 private static String getAccessorClassName(NodeData node) {
129 return node.isGenerateFactory() ? NodeFactoryFactory.factoryClassName(node) : NodeBaseFactory.baseClassName(node);
69 } 130 }
70 131
71 private static List<CodeTypeElement> generateNodes(ProcessorContext context, NodeData node) { 132 private static List<CodeTypeElement> generateNodes(ProcessorContext context, NodeData node) {
72 if (!node.needsFactory()) { 133 if (!node.needsFactory()) {
73 return Collections.emptyList(); 134 return Collections.emptyList();
89 nodeTypes.add(new SpecializedNodeFactory(context, node, specialization, baseNode).create()); 150 nodeTypes.add(new SpecializedNodeFactory(context, node, specialization, baseNode).create());
90 } 151 }
91 return nodeTypes; 152 return nodeTypes;
92 } 153 }
93 154
155 private static ExecutableElement createGetFactories(ProcessorContext context, NodeData node) {
156 List<NodeData> factoryList = node.getNodesWithFactories();
157 if (node.needsFactory() && node.isGenerateFactory()) {
158 factoryList.add(node);
159 }
160
161 if (factoryList.isEmpty()) {
162 return null;
163 }
164
165 List<TypeMirror> nodeTypesList = new ArrayList<>();
166 TypeMirror prev = null;
167 boolean allSame = true;
168 for (NodeData child : factoryList) {
169 nodeTypesList.add(child.getNodeType());
170 if (prev != null && !ElementUtils.typeEquals(child.getNodeType(), prev)) {
171 allSame = false;
172 }
173 prev = child.getNodeType();
174 }
175 TypeMirror commonNodeSuperType = ElementUtils.getCommonSuperType(context, nodeTypesList.toArray(new TypeMirror[nodeTypesList.size()]));
176
177 Types types = context.getEnvironment().getTypeUtils();
178 TypeMirror factoryType = context.getType(NodeFactory.class);
179 TypeMirror baseType;
180 if (allSame) {
181 baseType = ElementUtils.getDeclaredType(ElementUtils.fromTypeMirror(factoryType), commonNodeSuperType);
182 } else {
183 baseType = ElementUtils.getDeclaredType(ElementUtils.fromTypeMirror(factoryType), types.getWildcardType(commonNodeSuperType, null));
184 }
185 TypeMirror listType = ElementUtils.getDeclaredType(ElementUtils.fromTypeMirror(context.getType(List.class)), baseType);
186
187 CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, STATIC), listType, "getFactories");
188
189 CodeTreeBuilder builder = method.createBuilder();
190 builder.startReturn();
191 builder.startStaticCall(context.getType(Arrays.class), "asList");
192
193 for (NodeData child : factoryList) {
194 builder.startGroup();
195 NodeData childNode = child;
196 List<NodeData> factories = new ArrayList<>();
197 while (childNode.getDeclaringNode() != null) {
198 factories.add(childNode);
199 childNode = childNode.getDeclaringNode();
200 }
201 Collections.reverse(factories);
202 for (NodeData nodeData : factories) {
203
204 builder.string(getAccessorClassName(nodeData)).string(".");
205 }
206 builder.string("getInstance()");
207 builder.end();
208 }
209 builder.end();
210 builder.end();
211
212 return method;
213 }
214
94 } 215 }