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