comparison graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/TemplateMethodParser.java @ 7291:a748e4d44694

Truffle API to specify type-specalized Node classes; annotation processor for automatic code generation of the type-specialized Node classes during the build process
author Christian Humer <christian.humer@gmail.com>
date Fri, 21 Dec 2012 10:44:31 -0800
parents
children 6343a09b2ec1
comparison
equal deleted inserted replaced
7290:a81db08fe930 7291:a748e4d44694
1 /*
2 * Copyright (c) 2012, 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.codegen.processor.template;
24
25 import static com.oracle.truffle.codegen.processor.Utils.*;
26
27 import java.lang.annotation.*;
28 import java.util.*;
29
30 import javax.lang.model.element.*;
31 import javax.lang.model.type.*;
32
33 import com.oracle.truffle.codegen.processor.*;
34 import com.oracle.truffle.codegen.processor.template.ParameterSpec.Cardinality;
35
36 public abstract class TemplateMethodParser<E extends TemplateMethod> {
37
38 private final ProcessorContext context;
39
40 public TemplateMethodParser(ProcessorContext context) {
41 this.context = context;
42 }
43
44 public ProcessorContext getContext() {
45 return context;
46 }
47
48 public abstract MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror);
49
50 public abstract E create(TemplateMethod method);
51
52 public abstract Class<? extends Annotation> getAnnotationType();
53
54 public final E parse(ExecutableElement method, AnnotationMirror annotation, Template template) {
55 MethodSpec methodSpecification = createSpecification(method, annotation);
56 if (methodSpecification == null) {
57 return null;
58 }
59
60 ParameterSpec returnTypeSpec = methodSpecification.getReturnType();
61 List<ParameterSpec> parameterSpecs = new ArrayList<>();
62 parameterSpecs.addAll(methodSpecification.getParameters());
63
64 ActualParameter returnTypeMirror = resolveTypeMirror(returnTypeSpec, method.getReturnType(), template);
65 if (returnTypeMirror == null) {
66 String expectedReturnType = createTypeSignature(returnTypeSpec, true);
67 String actualReturnType = Utils.getSimpleName(method.getReturnType());
68
69 String message = String.format("The provided return type \"%s\" does not match expected return type \"%s\".\nExpected signature: \n %s", actualReturnType, expectedReturnType,
70 createExpectedSignature(method.getSimpleName().toString(), returnTypeSpec, parameterSpecs));
71
72 context.getLog().error(method, annotation, message);
73 return null;
74 }
75
76 Iterator< ? extends VariableElement> variableIterator = method.getParameters().iterator();
77 Iterator< ? extends ParameterSpec> specificationIterator = parameterSpecs.iterator();
78
79 List<ActualParameter> resolvedMirrors = new ArrayList<>();
80 VariableElement parameter = null;
81 ParameterSpec specification = null;
82 while (specificationIterator.hasNext() || specification != null) {
83 if (specification == null) {
84 specification = specificationIterator.next();
85 }
86
87 if (parameter == null && variableIterator.hasNext()) {
88 parameter = variableIterator.next();
89 }
90
91 if (parameter == null) {
92 if (specification.getCardinality() == Cardinality.MULTIPLE) {
93 specification = null;
94 continue;
95 } else if (!specification.isOptional()) {
96 // non option type specification found -> argument missing
97 String expectedType = createTypeSignature(specification, false);
98
99 String message = String.format("Missing argument \"%s\".\nExpected signature: \n %s", expectedType,
100 createExpectedSignature(method.getSimpleName().toString(), returnTypeSpec, parameterSpecs));
101
102 context.getLog().error(method, message);
103 return null;
104 } else {
105 // specification is optional -> continue
106 specification = null;
107 continue;
108 }
109 }
110
111 ActualParameter resolvedMirror = resolveTypeMirror(specification, parameter.asType(), template);
112
113 if (resolvedMirror == null) {
114 if (specification.isOptional()) {
115 specification = null;
116 continue;
117 }
118
119 String expectedReturnType = createTypeSignature(specification, false);
120 String actualReturnType = Utils.getSimpleName(parameter.asType()) + " " + parameter.getSimpleName();
121
122 String message = String.format("The provided argument type \"%s\" does not match expected type \"%s\".\nExpected signature: \n %s", actualReturnType, expectedReturnType,
123 createExpectedSignature(method.getSimpleName().toString(), returnTypeSpec, parameterSpecs));
124
125 context.getLog().error(parameter, message);
126 return null;
127 }
128
129 resolvedMirrors.add(resolvedMirror);
130 parameter = null; // consume parameter
131
132 if (specification.getCardinality() != Cardinality.MULTIPLE) {
133 specification = null;
134 }
135 }
136
137 if (variableIterator.hasNext()) {
138 parameter = variableIterator.next();
139 String actualReturnType = Utils.getSimpleName(parameter.asType()) + " " + parameter.getSimpleName();
140 String message = String.format("No argument expected but found \"%s\".\nExpected signature: \n %s", actualReturnType,
141 createExpectedSignature(method.getSimpleName().toString(), returnTypeSpec, parameterSpecs));
142
143 context.getLog().error(parameter, message);
144 return null;
145 }
146
147 ActualParameter[] paramMirrors = resolvedMirrors.toArray(new ActualParameter[resolvedMirrors.size()]);
148 return create(new TemplateMethod(methodSpecification, method, annotation, returnTypeMirror, paramMirrors));
149 }
150
151 private ActualParameter resolveTypeMirror(ParameterSpec specification, TypeMirror mirror, Template typeSystem) {
152 TypeMirror resolvedType = mirror;
153 if (hasError(resolvedType)) {
154 resolvedType = context.resolveNotYetCompiledType(mirror, typeSystem);
155 }
156
157 if (!specification.matches(resolvedType)) {
158 return null;
159 }
160 return new ActualParameter(specification, resolvedType);
161 }
162
163 public static String createExpectedSignature(String methodName, ParameterSpec returnType, List< ? extends ParameterSpec> parameters) {
164 StringBuilder b = new StringBuilder();
165
166 b.append(" ");
167 b.append(createTypeSignature(returnType, true));
168
169 b.append(" ");
170 b.append(methodName);
171 b.append("(");
172
173 for (int i = 0; i < parameters.size(); i++) {
174 ParameterSpec specification = parameters.get(i);
175 if (specification.isOptional()) {
176 b.append("[");
177 }
178 if (specification.getCardinality() == Cardinality.MULTIPLE) {
179 b.append("{");
180 }
181
182 b.append(createTypeSignature(specification, false));
183
184 if (specification.isOptional()) {
185 b.append("]");
186 }
187
188 if (specification.getCardinality() == Cardinality.MULTIPLE) {
189 b.append("}");
190 }
191
192 if (i < parameters.size() - 1) {
193 b.append(", ");
194 }
195
196 }
197
198 b.append(")");
199
200 TypeMirror[] types = null;
201
202 //TODO allowed types may differ so different <Any> must be generated.
203 if (returnType.getAllowedTypes().length > 1) {
204 types = returnType.getAllowedTypes();
205 }
206 for (ParameterSpec param : parameters) {
207 if (param.getAllowedTypes().length > 1) {
208 types = param.getAllowedTypes();
209 }
210 }
211 if (types != null) {
212 b.append("\n\n ");
213 b.append("<Any> = {");
214 String separator = "";
215 for (TypeMirror type : types) {
216 b.append(separator).append(Utils.getSimpleName(type));
217 separator = ", ";
218 }
219 b.append("}");
220 }
221 return b.toString();
222 }
223
224 private static String createTypeSignature(ParameterSpec spec, boolean typeOnly) {
225 StringBuilder builder = new StringBuilder();
226 if (spec.getAllowedTypes().length > 1) {
227 builder.append("<Any>");
228 } else if (spec.getAllowedTypes().length == 1) {
229 builder.append(Utils.getSimpleName(spec.getAllowedTypes()[0]));
230 } else {
231 builder.append("void");
232 }
233 if (!typeOnly) {
234 builder.append(" ");
235 builder.append(spec.getName());
236 }
237 return builder.toString();
238 }
239
240
241 }