Mercurial > hg > graal-jvmci-8
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 } |