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