comparison graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/TemplateMethodParser.java @ 8595:8a1115c92271

Implemented codegen guard definitions can now omit unused parameters.
author Christian Humer <christian.humer@gmail.com>
date Mon, 01 Apr 2013 21:43:20 +0200
parents 2be3865d9ea0
children 61ba6fc21ba4
comparison
equal deleted inserted replaced
8594:ce6e8672f798 8595:8a1115c92271
108 parsedMethods.add(parsedMethod); 108 parsedMethods.add(parsedMethod);
109 } else { 109 } else {
110 valid = false; 110 valid = false;
111 } 111 }
112 } 112 }
113 Collections.sort(parsedMethods, new Comparator<TemplateMethod>() { 113 Collections.sort(parsedMethods);
114
115 @Override
116 public int compare(TemplateMethod o1, TemplateMethod o2) {
117 return o1.getMethodName().compareTo(o2.getMethodName());
118 }
119 });
120 114
121 if (!valid && parseNullOnError) { 115 if (!valid && parseNullOnError) {
122 return null; 116 return null;
123 } 117 }
124 return parsedMethods; 118 return parsedMethods;
127 private E parse(ExecutableElement method, AnnotationMirror annotation) { 121 private E parse(ExecutableElement method, AnnotationMirror annotation) {
128 MethodSpec methodSpecification = createSpecification(method, annotation); 122 MethodSpec methodSpecification = createSpecification(method, annotation);
129 if (methodSpecification == null) { 123 if (methodSpecification == null) {
130 return null; 124 return null;
131 } 125 }
126
127 methodSpecification.applyTypeDefinitions("types");
132 128
133 String id = method.getSimpleName().toString(); 129 String id = method.getSimpleName().toString();
134 AnnotationMirror idAnnotation = Utils.findAnnotationMirror(context.getEnvironment(), method, NodeId.class); 130 AnnotationMirror idAnnotation = Utils.findAnnotationMirror(context.getEnvironment(), method, NodeId.class);
135 if (idAnnotation != null) { 131 if (idAnnotation != null) {
136 id = Utils.getAnnotationValue(String.class, idAnnotation, "value"); 132 id = Utils.getAnnotationValue(String.class, idAnnotation, "value");
137 } 133 }
138 134
139 List<TypeDef> typeDefs = createTypeDefinitions(methodSpecification.getReturnType(), methodSpecification.getParameters());
140
141 ParameterSpec returnTypeSpec = methodSpecification.getReturnType(); 135 ParameterSpec returnTypeSpec = methodSpecification.getReturnType();
142 List<ParameterSpec> parameterSpecs = new ArrayList<>();
143 parameterSpecs.addAll(methodSpecification.getParameters());
144 136
145 ActualParameter returnTypeMirror = matchParameter(returnTypeSpec, method.getReturnType(), template, 0, false); 137 ActualParameter returnTypeMirror = matchParameter(returnTypeSpec, method.getReturnType(), template, 0, false);
146 if (returnTypeMirror == null) { 138 if (returnTypeMirror == null) {
147 if (emitErrors) { 139 if (emitErrors) {
148 E invalidMethod = create(new TemplateMethod(id, template, methodSpecification, method, annotation, returnTypeMirror, Collections.<ActualParameter> emptyList())); 140 E invalidMethod = create(new TemplateMethod(id, template, methodSpecification, method, annotation, returnTypeMirror, Collections.<ActualParameter> emptyList()));
149 String expectedReturnType = createTypeSignature(returnTypeSpec, typeDefs, true); 141 String expectedReturnType = returnTypeSpec.toSignatureString(true);
150 String actualReturnType = Utils.getSimpleName(method.getReturnType()); 142 String actualReturnType = Utils.getSimpleName(method.getReturnType());
151 143
152 String message = String.format("The provided return type \"%s\" does not match expected return type \"%s\".\nExpected signature: \n %s", actualReturnType, expectedReturnType, 144 String message = String.format("The provided return type \"%s\" does not match expected return type \"%s\".\nExpected signature: \n %s", actualReturnType, expectedReturnType,
153 createExpectedSignature(method.getSimpleName().toString(), returnTypeSpec, parameterSpecs, typeDefs)); 145 methodSpecification.toSignatureString(method.getSimpleName().toString()));
154 invalidMethod.addError(message); 146 invalidMethod.addError(message);
155 return invalidMethod; 147 return invalidMethod;
156 } else { 148 } else {
157 return null; 149 return null;
158 } 150 }
161 List<TypeMirror> parameterTypes = new ArrayList<>(); 153 List<TypeMirror> parameterTypes = new ArrayList<>();
162 for (VariableElement var : method.getParameters()) { 154 for (VariableElement var : method.getParameters()) {
163 parameterTypes.add(var.asType()); 155 parameterTypes.add(var.asType());
164 } 156 }
165 157
166 List<ActualParameter> parameters = parseParameters(parameterTypes, methodSpecification.getImplicitTypes(), parameterSpecs); 158 List<ActualParameter> parameters = parseParameters(methodSpecification, parameterTypes);
167 if (parameters == null) { 159 if (parameters == null) {
168 if (isEmitErrors()) { 160 if (isEmitErrors()) {
169 E invalidMethod = create(new TemplateMethod(id, template, methodSpecification, method, annotation, returnTypeMirror, Collections.<ActualParameter> emptyList())); 161 E invalidMethod = create(new TemplateMethod(id, template, methodSpecification, method, annotation, returnTypeMirror, Collections.<ActualParameter> emptyList()));
170 String message = String.format("Method signature %s does not match to the expected signature: \n%s", createActualSignature(methodSpecification, method), 162 String message = String.format("Method signature %s does not match to the expected signature: \n%s", createActualSignature(methodSpecification, method),
171 createExpectedSignature(method.getSimpleName().toString(), returnTypeSpec, parameterSpecs, typeDefs)); 163 methodSpecification.toSignatureString(method.getSimpleName().toString()));
172 invalidMethod.addError(message); 164 invalidMethod.addError(message);
173 return invalidMethod; 165 return invalidMethod;
174 } else { 166 } else {
175 return null; 167 return null;
176 } 168 }
178 170
179 return create(new TemplateMethod(id, template, methodSpecification, method, annotation, returnTypeMirror, parameters)); 171 return create(new TemplateMethod(id, template, methodSpecification, method, annotation, returnTypeMirror, parameters));
180 } 172 }
181 173
182 private static String createActualSignature(MethodSpec spec, ExecutableElement method) { 174 private static String createActualSignature(MethodSpec spec, ExecutableElement method) {
183 List<String> types = new ArrayList<>(); 175 StringBuilder b = new StringBuilder("(");
184 for (TypeMirror implicitType : spec.getImplicitTypes()) { 176 String sep = "";
185 types.add("implicit " + Utils.getSimpleName(implicitType)); 177 for (TypeMirror implicitType : spec.getImplicitRequiredTypes()) {
178 b.append(sep);
179 b.append("implicit " + Utils.getSimpleName(implicitType));
180 sep = ", ";
186 } 181 }
187 for (VariableElement var : method.getParameters()) { 182 for (VariableElement var : method.getParameters()) {
188 types.add(Utils.getSimpleName(var.asType())); 183 b.append(sep);
189 } 184 b.append(Utils.getSimpleName(var.asType()));
190 185 sep = ", ";
191 StringBuilder b = new StringBuilder("(");
192 for (Iterator<String> iterator = types.iterator(); iterator.hasNext();) {
193 b.append(iterator.next());
194 if (iterator.hasNext()) {
195 b.append(", ");
196 }
197 } 186 }
198 b.append(")"); 187 b.append(")");
199 return b.toString(); 188 return b.toString();
200 } 189 }
201 190
202 private List<ActualParameter> parseParameters(List<TypeMirror> types, List<TypeMirror> implicitTypes, List<ParameterSpec> parameterSpecs) { 191 private List<ActualParameter> parseParameters(MethodSpec spec, List<TypeMirror> parameterTypes) {
203 Iterator<? extends TypeMirror> parameterIterator = types.iterator(); 192 List<ActualParameter> parsedParams = new ArrayList<>();
204 Iterator<? extends TypeMirror> implicitParametersIterator = implicitTypes.iterator(); 193 ConsumableListIterator<TypeMirror> types = new ConsumableListIterator<>(parameterTypes);
205 Iterator<? extends ParameterSpec> specificationIterator = parameterSpecs.iterator(); 194
206 195 // parse optional parameters
207 TypeMirror parameter = parameterIterator.hasNext() ? parameterIterator.next() : null; 196 ConsumableListIterator<ParameterSpec> optionals = new ConsumableListIterator<>(spec.getOptional());
208 TypeMirror implicitParameter = implicitParametersIterator.hasNext() ? implicitParametersIterator.next() : null; 197 for (TypeMirror type : types) {
209 ParameterSpec specification = specificationIterator.hasNext() ? specificationIterator.next() : null; 198 int oldIndex = types.getIndex();
199 int optionalCount = 1;
200 for (ParameterSpec paramspec : optionals) {
201 ActualParameter optionalParam = matchParameter(paramspec, type, template, 0, false);
202 if (optionalParam != null) {
203 optionals.consume(optionalCount);
204 types.consume();
205 parsedParams.add(optionalParam);
206 break;
207 }
208 optionalCount++;
209 }
210 if (oldIndex == types.getIndex()) {
211 // nothing found anymore skip optional
212 break;
213 }
214 }
215
216 List<TypeMirror> typesWithImplicit = new ArrayList<>(spec.getImplicitRequiredTypes());
217 typesWithImplicit.addAll(types.toList());
218 types = new ConsumableListIterator<>(typesWithImplicit);
210 219
211 int specificationParameterIndex = 0; 220 int specificationParameterIndex = 0;
212 List<ActualParameter> resolvedParameters = new ArrayList<>(); 221 ConsumableListIterator<ParameterSpec> required = new ConsumableListIterator<>(spec.getRequired());
213 while (parameter != null || specification != null || implicitParameter != null) { 222 while (required.get() != null || types.get() != null) {
214 if (parameter == null || specification == null) { 223 if (required.get() == null || types.get() == null) {
215 if (specification != null && (specification.isOptional() || specification.getCardinality() == Cardinality.MULTIPLE)) { 224 if (required.get() != null && required.get().getCardinality() == Cardinality.MULTIPLE) {
216 specification = specificationIterator.hasNext() ? specificationIterator.next() : null; 225 required.consume();
217 specificationParameterIndex = 0; 226 specificationParameterIndex = 0;
218 continue; 227 continue;
219 } 228 }
229 break;
230 }
231 boolean implicit = types.getIndex() < spec.getImplicitRequiredTypes().size();
232 ActualParameter resolvedParameter = matchParameter(required.get(), types.get(), template, specificationParameterIndex, implicit);
233 if (resolvedParameter == null) {
234 if (required.get().getCardinality() == Cardinality.MULTIPLE) {
235 required.consume();
236 continue;
237 }
238 // direct mismatch but required -> error
220 return null; 239 return null;
221 } 240 } else {
222 241 parsedParams.add(resolvedParameter);
223 ActualParameter resolvedParameter = null; 242 types.consume();
224 243 if (required.get().getCardinality() == Cardinality.ONE) {
225 boolean implicit = false; 244 required.consume();
226 if (implicitParameter != null) {
227 resolvedParameter = matchParameter(specification, implicitParameter, template, specificationParameterIndex, true);
228 if (resolvedParameter != null) {
229 implicit = true;
230 }
231 }
232
233 if (resolvedParameter == null) {
234 resolvedParameter = matchParameter(specification, parameter, template, specificationParameterIndex, false);
235 }
236
237 if (resolvedParameter == null) {
238 // mismatch
239 if (specification.isOptional()) {
240 specification = specificationIterator.hasNext() ? specificationIterator.next() : null;
241 specificationParameterIndex = 0; 245 specificationParameterIndex = 0;
242 } else { 246 } else if (required.get().getCardinality() == Cardinality.MULTIPLE) {
243 return null;
244 }
245 } else {
246 resolvedParameters.add(resolvedParameter);
247
248 // match
249 if (implicit) {
250 implicitParameter = implicitParametersIterator.hasNext() ? implicitParametersIterator.next() : null;
251 } else {
252 parameter = parameterIterator.hasNext() ? parameterIterator.next() : null;
253 }
254
255 if (specification.getCardinality() == Cardinality.ONE) {
256 specification = specificationIterator.hasNext() ? specificationIterator.next() : null;
257 specificationParameterIndex = 0;
258 } else if (specification.getCardinality() == Cardinality.MULTIPLE) {
259 specificationParameterIndex++; 247 specificationParameterIndex++;
260 } 248 }
261 } 249 }
262 } 250 }
263 return resolvedParameters; 251
252 if (!types.toList().isEmpty()) {
253 // additional types -> error
254 return null;
255 }
256
257 if (!required.toList().isEmpty() && !spec.isVariableRequiredArguments()) {
258 // additional specifications -> error
259 return null;
260 }
261
262 // success!
263 return parsedParams;
264 } 264 }
265 265
266 private ActualParameter matchParameter(ParameterSpec specification, TypeMirror mirror, Template typeSystem, int index, boolean implicit) { 266 private ActualParameter matchParameter(ParameterSpec specification, TypeMirror mirror, Template typeSystem, int index, boolean implicit) {
267 TypeMirror resolvedType = mirror; 267 TypeMirror resolvedType = mirror;
268 if (hasError(resolvedType)) { 268 if (hasError(resolvedType)) {
273 return null; 273 return null;
274 } 274 }
275 return new ActualParameter(specification, resolvedType, index, implicit); 275 return new ActualParameter(specification, resolvedType, index, implicit);
276 } 276 }
277 277
278 protected List<TypeDef> createTypeDefinitions(ParameterSpec returnType, List<? extends ParameterSpec> parameters) { 278 /* Helper class for parsing. */
279 List<TypeDef> typeDefs = new ArrayList<>(); 279 private static class ConsumableListIterator<E> implements Iterable<E> {
280 280
281 List<ParameterSpec> allParams = new ArrayList<>(); 281 private final List<E> data;
282 allParams.add(returnType); 282 private int index;
283 allParams.addAll(parameters); 283
284 284 public ConsumableListIterator(List<E> data) {
285 int defIndex = 0; 285 this.data = data;
286 for (ParameterSpec spec : allParams) { 286 }
287 List<TypeMirror> allowedTypes = spec.getAllowedTypes(); 287
288 List<TypeMirror> types = spec.getAllowedTypes(); 288 public E get() {
289 if (types != null && allowedTypes.size() > 1) { 289 if (index >= data.size()) {
290 TypeDef foundDef = null; 290 return null;
291 for (TypeDef def : typeDefs) { 291 }
292 if (allowedTypes.equals(def.getTypes())) { 292 return data.get(index);
293 foundDef = def; 293 }
294 break; 294
295 } 295 public E consume() {
296 } 296 return consume(1);
297 if (foundDef == null) { 297 }
298 foundDef = new TypeDef(types, "Types" + defIndex); 298
299 typeDefs.add(foundDef); 299 public E consume(int count) {
300 defIndex++; 300 if (index + count <= data.size()) {
301 } 301 index += count;
302 302 return get();
303 foundDef.getParameters().add(spec); 303 } else {
304 } 304 throw new ArrayIndexOutOfBoundsException(count + 1);
305 } 305 }
306 306 }
307 return typeDefs; 307
308 } 308 public int getIndex() {
309 309 return index;
310 protected static class TypeDef { 310 }
311 311
312 private final List<TypeMirror> types; 312 @Override
313 private final String name; 313 public Iterator<E> iterator() {
314 private final List<ParameterSpec> parameters = new ArrayList<>(); 314 return toList().iterator();
315 315 }
316 public TypeDef(List<TypeMirror> types, String name) { 316
317 this.types = types; 317 public List<E> toList() {
318 this.name = name; 318 if (index < data.size()) {
319 } 319 return data.subList(index, data.size());
320 320 } else {
321 public List<ParameterSpec> getParameters() { 321 return Collections.<E> emptyList();
322 return parameters; 322 }
323 } 323 }
324 324
325 public List<TypeMirror> getTypes() {
326 return types;
327 }
328
329 public String getName() {
330 return name;
331 }
332 }
333
334 public static String createExpectedSignature(String methodName, ParameterSpec returnType, List<? extends ParameterSpec> parameters, List<TypeDef> typeDefs) {
335 StringBuilder b = new StringBuilder();
336
337 b.append(" ");
338 b.append(createTypeSignature(returnType, typeDefs, true));
339
340 b.append(" ");
341 b.append(methodName);
342 b.append("(");
343
344 for (int i = 0; i < parameters.size(); i++) {
345 ParameterSpec specification = parameters.get(i);
346 if (specification.isOptional()) {
347 b.append("[");
348 }
349 if (specification.getCardinality() == Cardinality.MULTIPLE) {
350 b.append("{");
351 }
352
353 b.append(createTypeSignature(specification, typeDefs, false));
354
355 if (specification.isOptional()) {
356 b.append("]");
357 }
358
359 if (specification.getCardinality() == Cardinality.MULTIPLE) {
360 b.append("}");
361 }
362
363 if (i < parameters.size() - 1) {
364 b.append(", ");
365 }
366
367 }
368
369 b.append(")");
370
371 if (!typeDefs.isEmpty()) {
372 b.append("\n\n");
373
374 String lineSep = "";
375 for (TypeDef def : typeDefs) {
376 b.append(lineSep);
377 b.append(" <").append(def.getName()).append(">");
378 b.append(" = {");
379 String separator = "";
380 for (TypeMirror type : def.getTypes()) {
381 b.append(separator).append(Utils.getSimpleName(type));
382 separator = ", ";
383 }
384 b.append("}");
385 lineSep = "\n";
386
387 }
388 }
389 return b.toString();
390 }
391
392 private static String createTypeSignature(ParameterSpec spec, List<TypeDef> typeDefs, boolean typeOnly) {
393 StringBuilder builder = new StringBuilder();
394 if (spec.getAllowedTypes().size() > 1) {
395 TypeDef foundTypeDef = null;
396 for (TypeDef typeDef : typeDefs) {
397 if (typeDef.getParameters().contains(spec)) {
398 foundTypeDef = typeDef;
399 break;
400 }
401 }
402 if (foundTypeDef != null) {
403 builder.append("<" + foundTypeDef.getName() + ">");
404 }
405 } else if (spec.getAllowedTypes().size() == 1) {
406 builder.append(Utils.getSimpleName(spec.getAllowedTypes().get(0)));
407 } else {
408 builder.append("void");
409 }
410 if (!typeOnly) {
411 builder.append(" ");
412 builder.append(spec.getName());
413 }
414 return builder.toString();
415 } 325 }
416 326
417 } 327 }