comparison graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/TemplateMethodParser.java @ 13271:2b9fcffd6f36

Truffle-DSL: added support for generating execute methods with java varargs.
author Christian Humer <christian.humer@gmail.com>
date Sun, 01 Dec 2013 18:18:33 +0100
parents 43eab069ca9b
children e4862151eefd
comparison
equal deleted inserted replaced
13203:401e1473c546 13271:2b9fcffd6f36
138 id = Utils.getAnnotationValue(String.class, idAnnotation, "value"); 138 id = Utils.getAnnotationValue(String.class, idAnnotation, "value");
139 } 139 }
140 140
141 ParameterSpec returnTypeSpec = methodSpecification.getReturnType(); 141 ParameterSpec returnTypeSpec = methodSpecification.getReturnType();
142 142
143 ActualParameter returnTypeMirror = matchParameter(returnTypeSpec, method.getReturnType(), template, 0, false); 143 ActualParameter returnTypeMirror = matchParameter(returnTypeSpec, method.getReturnType(), template, 0, -1, false);
144 if (returnTypeMirror == null) { 144 if (returnTypeMirror == null) {
145 if (emitErrors) { 145 if (emitErrors) {
146 E invalidMethod = create(new TemplateMethod(id, template, methodSpecification, method, annotation, returnTypeMirror, Collections.<ActualParameter> emptyList()), true); 146 E invalidMethod = create(new TemplateMethod(id, template, methodSpecification, method, annotation, returnTypeMirror, Collections.<ActualParameter> emptyList()), true);
147 String expectedReturnType = returnTypeSpec.toSignatureString(true); 147 String expectedReturnType = returnTypeSpec.toSignatureString(true);
148 String actualReturnType = Utils.getSimpleName(method.getReturnType()); 148 String actualReturnType = Utils.getSimpleName(method.getReturnType());
159 List<TypeMirror> parameterTypes = new ArrayList<>(); 159 List<TypeMirror> parameterTypes = new ArrayList<>();
160 for (VariableElement var : method.getParameters()) { 160 for (VariableElement var : method.getParameters()) {
161 parameterTypes.add(var.asType()); 161 parameterTypes.add(var.asType());
162 } 162 }
163 163
164 List<ActualParameter> parameters = parseParameters(methodSpecification, parameterTypes); 164 List<ActualParameter> parameters = parseParameters(methodSpecification, parameterTypes, method.isVarArgs());
165 if (parameters == null) { 165 if (parameters == null) {
166 if (isEmitErrors()) { 166 if (isEmitErrors()) {
167 E invalidMethod = create(new TemplateMethod(id, template, methodSpecification, method, annotation, returnTypeMirror, Collections.<ActualParameter> emptyList()), true); 167 E invalidMethod = create(new TemplateMethod(id, template, methodSpecification, method, annotation, returnTypeMirror, Collections.<ActualParameter> emptyList()), true);
168 String message = String.format("Method signature %s does not match to the expected signature: \n%s", createActualSignature(methodSpecification, method), 168 String message = String.format("Method signature %s does not match to the expected signature: \n%s", createActualSignature(methodSpecification, method),
169 methodSpecification.toSignatureString(method.getSimpleName().toString())); 169 methodSpecification.toSignatureString(method.getSimpleName().toString()));
199 * offset until it finds a signature end that matches the required specification. If there is no 199 * offset until it finds a signature end that matches the required specification. If there is no
200 * end matching the required arguments, parsing fails. Parameters prior to the parsed required 200 * end matching the required arguments, parsing fails. Parameters prior to the parsed required
201 * ones are cut and used to parse the optional parameters. All those remaining parameters must 201 * ones are cut and used to parse the optional parameters. All those remaining parameters must
202 * be consumed otherwise its an error. 202 * be consumed otherwise its an error.
203 */ 203 */
204 private List<ActualParameter> parseParameters(MethodSpec spec, List<TypeMirror> parameterTypes) { 204 private List<ActualParameter> parseParameters(MethodSpec spec, List<TypeMirror> parameterTypes, boolean varArgs) {
205 List<TypeMirror> implicitTypes = spec.getImplicitRequiredTypes(); 205 List<TypeMirror> implicitTypes = spec.getImplicitRequiredTypes();
206 206
207 int offset = -1; 207 int offset = -1;
208 List<ActualParameter> parsedRequired = null; 208 List<ActualParameter> parsedRequired = null;
209 ConsumableListIterator<TypeMirror> types = null; 209 ConsumableListIterator<TypeMirror> types = null;
210 while (parsedRequired == null && offset < parameterTypes.size()) { 210 while (parsedRequired == null && offset < parameterTypes.size()) {
211 offset++; 211 offset++;
212 types = new ConsumableListIterator<>(new ArrayList<>(implicitTypes)); 212 types = new ConsumableListIterator<>(new ArrayList<>(implicitTypes));
213 types.data.addAll(parameterTypes.subList(offset, parameterTypes.size())); 213 types.data.addAll(parameterTypes.subList(offset, parameterTypes.size()));
214 parsedRequired = parseParametersRequired(spec, types); 214 parsedRequired = parseParametersRequired(spec, types, varArgs);
215 } 215 }
216 216
217 if (parsedRequired == null && offset >= 0) { 217 if (parsedRequired == null && offset >= 0) {
218 return null; 218 return null;
219 } 219 }
242 ConsumableListIterator<ParameterSpec> optionals = new ConsumableListIterator<>(spec.getOptional()); 242 ConsumableListIterator<ParameterSpec> optionals = new ConsumableListIterator<>(spec.getOptional());
243 for (TypeMirror type : types) { 243 for (TypeMirror type : types) {
244 int oldIndex = types.getIndex(); 244 int oldIndex = types.getIndex();
245 int optionalCount = 1; 245 int optionalCount = 1;
246 for (ParameterSpec paramspec : optionals) { 246 for (ParameterSpec paramspec : optionals) {
247 ActualParameter optionalParam = matchParameter(paramspec, type, template, 0, false); 247 ActualParameter optionalParam = matchParameter(paramspec, type, template, 0, -1, false);
248 if (optionalParam != null) { 248 if (optionalParam != null) {
249 optionals.consume(optionalCount); 249 optionals.consume(optionalCount);
250 types.consume(); 250 types.consume();
251 parsedParams.add(optionalParam); 251 parsedParams.add(optionalParam);
252 break; 252 break;
262 return null; 262 return null;
263 } 263 }
264 return parsedParams; 264 return parsedParams;
265 } 265 }
266 266
267 private List<ActualParameter> parseParametersRequired(MethodSpec spec, ConsumableListIterator<TypeMirror> types) { 267 private List<ActualParameter> parseParametersRequired(MethodSpec spec, ConsumableListIterator<TypeMirror> types, boolean varArgs) {
268 List<ActualParameter> parsedParams = new ArrayList<>(); 268 List<ActualParameter> parsedParams = new ArrayList<>();
269 269
270 int varArgsParameterIndex = -1;
270 int specificationParameterIndex = 0; 271 int specificationParameterIndex = 0;
271 ConsumableListIterator<ParameterSpec> required = new ConsumableListIterator<>(spec.getRequired()); 272 ConsumableListIterator<ParameterSpec> required = new ConsumableListIterator<>(spec.getRequired());
272 while (required.get() != null || types.get() != null) { 273 while (required.get() != null || types.get() != null) {
273 if (required.get() == null || types.get() == null) { 274 if (required.get() == null || types.get() == null) {
274 if (required.get() != null && required.get().getCardinality() == Cardinality.MANY) { 275 if (required.get() != null && required.get().getCardinality() == Cardinality.MANY) {
276 specificationParameterIndex = 0; 277 specificationParameterIndex = 0;
277 continue; 278 continue;
278 } 279 }
279 break; 280 break;
280 } 281 }
282 TypeMirror actualType = types.get();
283 if (varArgs && types.isLast()) {
284 if (actualType.getKind() == TypeKind.ARRAY) {
285 actualType = ((ArrayType) actualType).getComponentType();
286 }
287 varArgsParameterIndex++;
288 }
281 boolean implicit = types.getIndex() < spec.getImplicitRequiredTypes().size(); 289 boolean implicit = types.getIndex() < spec.getImplicitRequiredTypes().size();
282 ActualParameter resolvedParameter = matchParameter(required.get(), types.get(), template, specificationParameterIndex, implicit); 290 ActualParameter resolvedParameter = matchParameter(required.get(), actualType, template, specificationParameterIndex, varArgsParameterIndex, implicit);
283 if (resolvedParameter == null) { 291 if (resolvedParameter == null) {
284 if (required.get().getCardinality() == Cardinality.MANY) { 292 if (required.get().getCardinality() == Cardinality.MANY) {
285 required.consume(); 293 required.consume();
286 continue; 294 continue;
287 } 295 }
288 // direct mismatch but required -> error 296 // direct mismatch but required -> error
289 return null; 297 return null;
290 } else { 298 } else {
291 parsedParams.add(resolvedParameter); 299 parsedParams.add(resolvedParameter);
292 types.consume(); 300
301 if (varArgs && types.isLast()) {
302 /* Both varargs spec and varargs definition. Need to consume to terminate. */
303 if (required.get().getCardinality() == Cardinality.MANY) {
304 types.consume();
305 }
306 } else {
307 types.consume();
308 }
309
293 if (required.get().getCardinality() == Cardinality.ONE) { 310 if (required.get().getCardinality() == Cardinality.ONE) {
294 required.consume(); 311 required.consume();
295 specificationParameterIndex = 0; 312 specificationParameterIndex = 0;
296 } else if (required.get().getCardinality() == Cardinality.MANY) { 313 } else if (required.get().getCardinality() == Cardinality.MANY) {
297 specificationParameterIndex++; 314 specificationParameterIndex++;
298 } 315 }
299 } 316 }
300 } 317 }
301 318
302 if (!types.toList().isEmpty()) { 319 if (!types.toList().isEmpty() && !(varArgs && types.isLast())) {
303 // additional types -> error 320 // additional types -> error
304 return null; 321 return null;
305 } 322 }
306 323
307 if (!required.toList().isEmpty() && !spec.isVariableRequiredArguments()) { 324 if (!required.toList().isEmpty() && !spec.isVariableRequiredArguments()) {
309 return null; 326 return null;
310 } 327 }
311 return parsedParams; 328 return parsedParams;
312 } 329 }
313 330
314 private ActualParameter matchParameter(ParameterSpec specification, TypeMirror mirror, Template originalTemplate, int index, boolean implicit) { 331 private ActualParameter matchParameter(ParameterSpec specification, TypeMirror mirror, Template originalTemplate, int specificationIndex, int varArgsIndex, boolean implicit) {
315 TypeMirror resolvedType = mirror; 332 TypeMirror resolvedType = mirror;
316 if (hasError(resolvedType)) { 333 if (hasError(resolvedType)) {
317 resolvedType = context.resolveNotYetCompiledType(mirror, originalTemplate); 334 resolvedType = context.resolveNotYetCompiledType(mirror, originalTemplate);
318 } 335 }
319 336
321 return null; 338 return null;
322 } 339 }
323 340
324 TypeData resolvedTypeData = getTypeSystem().findTypeData(resolvedType); 341 TypeData resolvedTypeData = getTypeSystem().findTypeData(resolvedType);
325 if (resolvedTypeData != null) { 342 if (resolvedTypeData != null) {
326 return new ActualParameter(specification, resolvedTypeData, index, implicit); 343 return new ActualParameter(specification, resolvedTypeData, specificationIndex, varArgsIndex, implicit);
327 } else { 344 } else {
328 return new ActualParameter(specification, resolvedType, index, implicit); 345 return new ActualParameter(specification, resolvedType, specificationIndex, varArgsIndex, implicit);
329 } 346 }
330 } 347 }
331 348
332 /* Helper class for parsing. */ 349 /* Helper class for parsing. */
333 private static class ConsumableListIterator<E> implements Iterable<E> { 350 private static class ConsumableListIterator<E> implements Iterable<E> {
342 public E get() { 359 public E get() {
343 if (index >= data.size()) { 360 if (index >= data.size()) {
344 return null; 361 return null;
345 } 362 }
346 return data.get(index); 363 return data.get(index);
364 }
365
366 public boolean isLast() {
367 return index == data.size() - 1;
347 } 368 }
348 369
349 public E consume() { 370 public E consume() {
350 return consume(1); 371 return consume(1);
351 } 372 }