Mercurial > hg > truffle
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 } |