Mercurial > hg > graal-compiler
comparison graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/NodeParser.java @ 19289:62c43fcf5be2
Truffle-DSL: implement @Cached and fixes for the new guard expression syntax.
author | Christian Humer <christian.humer@gmail.com> |
---|---|
date | Tue, 03 Feb 2015 15:07:07 +0100 |
parents | 259a416388d7 |
children | f4792a544170 |
comparison
equal
deleted
inserted
replaced
19288:3a37116ef37f | 19289:62c43fcf5be2 |
---|---|
34 import com.oracle.truffle.api.nodes.*; | 34 import com.oracle.truffle.api.nodes.*; |
35 import com.oracle.truffle.dsl.processor.*; | 35 import com.oracle.truffle.dsl.processor.*; |
36 import com.oracle.truffle.dsl.processor.expression.*; | 36 import com.oracle.truffle.dsl.processor.expression.*; |
37 import com.oracle.truffle.dsl.processor.java.*; | 37 import com.oracle.truffle.dsl.processor.java.*; |
38 import com.oracle.truffle.dsl.processor.java.compiler.*; | 38 import com.oracle.truffle.dsl.processor.java.compiler.*; |
39 import com.oracle.truffle.dsl.processor.java.model.*; | |
39 import com.oracle.truffle.dsl.processor.model.*; | 40 import com.oracle.truffle.dsl.processor.model.*; |
40 import com.oracle.truffle.dsl.processor.model.NodeChildData.Cardinality; | 41 import com.oracle.truffle.dsl.processor.model.NodeChildData.Cardinality; |
41 import com.oracle.truffle.dsl.processor.model.SpecializationData.SpecializationKind; | 42 import com.oracle.truffle.dsl.processor.model.SpecializationData.SpecializationKind; |
42 import com.oracle.truffle.dsl.processor.model.TemplateMethod.TypeSignature; | 43 import com.oracle.truffle.dsl.processor.model.TemplateMethod.TypeSignature; |
43 | 44 |
97 try { | 98 try { |
98 node = parseNode(rootType); | 99 node = parseNode(rootType); |
99 } catch (CompileErrorException e) { | 100 } catch (CompileErrorException e) { |
100 throw e; | 101 throw e; |
101 } catch (Throwable e) { | 102 } catch (Throwable e) { |
102 throw new RuntimeException(String.format("Parsing of Node %s failed.", ElementUtils.getQualifiedName(rootType)), e); | 103 e.addSuppressed(new RuntimeException(String.format("Parsing of Node %s failed.", ElementUtils.getQualifiedName(rootType)), e)); |
104 throw e; | |
103 } | 105 } |
104 if (node == null && !enclosedNodes.isEmpty()) { | 106 if (node == null && !enclosedNodes.isEmpty()) { |
105 node = new NodeData(context, rootType); | 107 node = new NodeData(context, rootType); |
106 } | 108 } |
107 | 109 |
207 for (TypeMirror importGuardClass : importClasses) { | 209 for (TypeMirror importGuardClass : importClasses) { |
208 if (importGuardClass.getKind() != TypeKind.DECLARED) { | 210 if (importGuardClass.getKind() != TypeKind.DECLARED) { |
209 node.addError(importAnnotation, importClassesValue, "The specified import guard class '%s' is not a declared type.", ElementUtils.getQualifiedName(importGuardClass)); | 211 node.addError(importAnnotation, importClassesValue, "The specified import guard class '%s' is not a declared type.", ElementUtils.getQualifiedName(importGuardClass)); |
210 continue; | 212 continue; |
211 } | 213 } |
214 | |
212 TypeElement typeElement = ElementUtils.fromTypeMirror(importGuardClass); | 215 TypeElement typeElement = ElementUtils.fromTypeMirror(importGuardClass); |
213 | |
214 // hack to reload type is necessary for incremental compiling in eclipse. | |
215 // otherwise methods inside of import guard types are just not found. | |
216 typeElement = ElementUtils.fromTypeMirror(context.reloadType(typeElement.asType())); | |
217 | |
218 if (typeElement.getEnclosingElement().getKind().isClass() && !typeElement.getModifiers().contains(Modifier.PUBLIC)) { | 216 if (typeElement.getEnclosingElement().getKind().isClass() && !typeElement.getModifiers().contains(Modifier.PUBLIC)) { |
219 node.addError(importAnnotation, importClassesValue, "The specified import guard class '%s' must be public.", ElementUtils.getQualifiedName(importGuardClass)); | 217 node.addError(importAnnotation, importClassesValue, "The specified import guard class '%s' must be public.", ElementUtils.getQualifiedName(importGuardClass)); |
220 continue; | 218 continue; |
221 } | 219 } |
222 | 220 elements.addAll(importPublicStaticMembers(typeElement, false)); |
223 List<? extends ExecutableElement> importMethods = ElementFilter.methodsIn(processingEnv.getElementUtils().getAllMembers(typeElement)); | 221 } |
224 | 222 } |
225 for (ExecutableElement importMethod : importMethods) { | 223 } |
226 if (!importMethod.getModifiers().contains(Modifier.PUBLIC) || !importMethod.getModifiers().contains(Modifier.STATIC)) { | 224 |
227 continue; | 225 private List<? extends Element> importPublicStaticMembers(TypeElement importGuardClass, boolean includeConstructors) { |
228 } | 226 // hack to reload type is necessary for incremental compiling in eclipse. |
229 elements.add(importMethod); | 227 // otherwise methods inside of import guard types are just not found. |
230 } | 228 TypeElement typeElement = ElementUtils.fromTypeMirror(context.reloadType(importGuardClass.asType())); |
231 } | 229 |
232 } | 230 List<Element> members = new ArrayList<>(); |
231 for (Element importElement : processingEnv.getElementUtils().getAllMembers(typeElement)) { | |
232 if (!importElement.getModifiers().contains(Modifier.PUBLIC)) { | |
233 continue; | |
234 } | |
235 | |
236 if (includeConstructors && importElement.getKind() == ElementKind.CONSTRUCTOR) { | |
237 members.add(importElement); | |
238 } | |
239 | |
240 if (!importElement.getModifiers().contains(Modifier.STATIC)) { | |
241 continue; | |
242 } | |
243 | |
244 ElementKind kind = importElement.getKind(); | |
245 if (kind.isField() || kind == ElementKind.METHOD) { | |
246 members.add(importElement); | |
247 } | |
248 } | |
249 return members; | |
233 } | 250 } |
234 | 251 |
235 private NodeData parseNodeData(TypeElement templateType, List<TypeElement> typeHierarchy) { | 252 private NodeData parseNodeData(TypeElement templateType, List<TypeElement> typeHierarchy) { |
236 AnnotationMirror typeSystemMirror = findFirstAnnotation(typeHierarchy, TypeSystemReference.class); | 253 AnnotationMirror typeSystemMirror = findFirstAnnotation(typeHierarchy, TypeSystemReference.class); |
237 if (typeSystemMirror == null) { | 254 if (typeSystemMirror == null) { |
284 if (field.getModifiers().contains(Modifier.STATIC)) { | 301 if (field.getModifiers().contains(Modifier.STATIC)) { |
285 continue; | 302 continue; |
286 } | 303 } |
287 if (field.getModifiers().contains(Modifier.PUBLIC) || field.getModifiers().contains(Modifier.PROTECTED)) { | 304 if (field.getModifiers().contains(Modifier.PUBLIC) || field.getModifiers().contains(Modifier.PROTECTED)) { |
288 String name = field.getSimpleName().toString(); | 305 String name = field.getSimpleName().toString(); |
289 fields.add(new NodeFieldData(field, null, field.asType(), name, false)); | 306 fields.add(new NodeFieldData(field, null, field, false)); |
290 names.add(name); | 307 names.add(name); |
291 } | 308 } |
292 } | 309 } |
293 | 310 |
294 List<TypeElement> reversedTypeHierarchy = new ArrayList<>(typeHierarchy); | 311 List<TypeElement> reversedTypeHierarchy = new ArrayList<>(typeHierarchy); |
299 | 316 |
300 for (AnnotationMirror mirror : children) { | 317 for (AnnotationMirror mirror : children) { |
301 String name = ElementUtils.firstLetterLowerCase(ElementUtils.getAnnotationValue(String.class, mirror, "name")); | 318 String name = ElementUtils.firstLetterLowerCase(ElementUtils.getAnnotationValue(String.class, mirror, "name")); |
302 TypeMirror type = ElementUtils.getAnnotationValue(TypeMirror.class, mirror, "type"); | 319 TypeMirror type = ElementUtils.getAnnotationValue(TypeMirror.class, mirror, "type"); |
303 | 320 |
304 NodeFieldData field = new NodeFieldData(typeElement, mirror, type, name, true); | 321 NodeFieldData field = new NodeFieldData(typeElement, mirror, new CodeVariableElement(type, name), true); |
305 if (name.isEmpty()) { | 322 if (name.isEmpty()) { |
306 field.addError(ElementUtils.getAnnotationValue(mirror, "name"), "Field name cannot be empty."); | 323 field.addError(ElementUtils.getAnnotationValue(mirror, "name"), "Field name cannot be empty."); |
307 } else if (names.contains(name)) { | 324 } else if (names.contains(name)) { |
308 field.addError(ElementUtils.getAnnotationValue(mirror, "name"), "Duplicate field name '%s'.", name); | 325 field.addError(ElementUtils.getAnnotationValue(mirror, "name"), "Duplicate field name '%s'.", name); |
309 } | 326 } |
467 } else { | 484 } else { |
468 maxSignatureSize = children.size(); | 485 maxSignatureSize = children.size(); |
469 } | 486 } |
470 } | 487 } |
471 | 488 |
489 TypeMirror cacheAnnotation = context.getType(Cached.class); | |
472 List<TypeMirror> frameTypes = context.getFrameTypes(); | 490 List<TypeMirror> frameTypes = context.getFrameTypes(); |
473 // pre-parse specializations to find signature size | 491 // pre-parse specializations to find signature size |
474 for (ExecutableElement method : methods) { | 492 for (ExecutableElement method : methods) { |
475 AnnotationMirror mirror = ElementUtils.findAnnotationMirror(processingEnv, method, Specialization.class); | 493 AnnotationMirror mirror = ElementUtils.findAnnotationMirror(processingEnv, method, Specialization.class); |
476 if (mirror == null) { | 494 if (mirror == null) { |
477 continue; | 495 continue; |
478 } | 496 } |
479 | |
480 int currentArgumentIndex = 0; | 497 int currentArgumentIndex = 0; |
481 boolean skipShortCircuit = false; | 498 boolean skipShortCircuit = false; |
482 outer: for (VariableElement var : method.getParameters()) { | 499 outer: for (VariableElement var : method.getParameters()) { |
500 | |
483 TypeMirror type = var.asType(); | 501 TypeMirror type = var.asType(); |
484 if (currentArgumentIndex == 0) { | 502 if (currentArgumentIndex == 0) { |
485 // skip optionals | 503 // skip optionals |
486 for (TypeMirror frameType : frameTypes) { | 504 for (TypeMirror frameType : frameTypes) { |
487 if (ElementUtils.typeEquals(type, frameType)) { | 505 if (ElementUtils.typeEquals(type, frameType)) { |
488 continue outer; | 506 continue outer; |
489 } | 507 } |
490 } | 508 } |
491 } | 509 } |
510 | |
511 if (ElementUtils.findAnnotationMirror(var.getAnnotationMirrors(), cacheAnnotation) != null) { | |
512 continue outer; | |
513 } | |
514 | |
492 int childIndex = currentArgumentIndex < children.size() ? currentArgumentIndex : children.size() - 1; | 515 int childIndex = currentArgumentIndex < children.size() ? currentArgumentIndex : children.size() - 1; |
493 if (childIndex == -1) { | 516 if (childIndex == -1) { |
494 continue; | 517 continue; |
495 } | 518 } |
496 if (!skipShortCircuit) { | 519 if (!skipShortCircuit) { |
667 List<TypeElement> lookupTypes = collectSuperClasses(new ArrayList<TypeElement>(), templateType); | 690 List<TypeElement> lookupTypes = collectSuperClasses(new ArrayList<TypeElement>(), templateType); |
668 | 691 |
669 // Declaration order is not required for child nodes. | 692 // Declaration order is not required for child nodes. |
670 List<? extends Element> members = processingEnv.getElementUtils().getAllMembers(templateType); | 693 List<? extends Element> members = processingEnv.getElementUtils().getAllMembers(templateType); |
671 NodeData node = parseNodeData(templateType, lookupTypes); | 694 NodeData node = parseNodeData(templateType, lookupTypes); |
672 | 695 if (node.hasErrors()) { |
696 return node; | |
697 } | |
673 node.setExecutableTypes(groupExecutableTypes(new ExecutableTypeMethodParser(context, node, createAllowedChildFrameTypes(parentNode)).parse(members))); | 698 node.setExecutableTypes(groupExecutableTypes(new ExecutableTypeMethodParser(context, node, createAllowedChildFrameTypes(parentNode)).parse(members))); |
674 node.setFrameType(parentNode.getFrameType()); | 699 node.setFrameType(parentNode.getFrameType()); |
675 return node; | 700 return node; |
676 } | 701 } |
677 | 702 |
689 if (node.getSpecializations().isEmpty()) { | 714 if (node.getSpecializations().isEmpty()) { |
690 return; | 715 return; |
691 } | 716 } |
692 | 717 |
693 initializeExpressions(elements, node); | 718 initializeExpressions(elements, node); |
719 | |
694 if (node.hasErrors()) { | 720 if (node.hasErrors()) { |
695 return; | 721 return; |
696 } | 722 } |
697 | 723 |
698 initializeGeneric(node); | 724 initializeGeneric(node); |
699 initializeUninitialized(node); | 725 initializeUninitialized(node); |
700 initializeOrder(node); | 726 initializeOrder(node); |
701 initializePolymorphism(node); // requires specializations | 727 initializePolymorphism(node); // requires specializations |
702 initializeReachability(node); | 728 initializeReachability(node); |
703 initializeContains(node); | 729 initializeContains(node); |
704 | |
705 resolveContains(node); | 730 resolveContains(node); |
706 | 731 |
707 List<SpecializationData> specializations = node.getSpecializations(); | 732 List<SpecializationData> specializations = node.getSpecializations(); |
708 for (SpecializationData cur : specializations) { | 733 for (SpecializationData cur : specializations) { |
709 for (SpecializationData child : specializations) { | 734 for (SpecializationData contained : cur.getContains()) { |
710 if (child != null && child != cur && child.getContains().contains(cur)) { | 735 if (contained != cur) { |
711 cur.getExcludedBy().add(child); | 736 contained.getExcludedBy().add(cur); |
712 } | 737 } |
713 } | 738 } |
714 } | 739 } |
715 | 740 |
716 // verify specialization parameter length | |
717 initializeSpecializationIdsWithMethodNames(node.getSpecializations()); | 741 initializeSpecializationIdsWithMethodNames(node.getSpecializations()); |
718 } | 742 } |
719 | 743 |
720 private static void initializeOrder(NodeData node) { | 744 private static void initializeOrder(NodeData node) { |
721 List<SpecializationData> specializations = node.getSpecializations(); | 745 List<SpecializationData> specializations = node.getSpecializations(); |
776 | 800 |
777 if (foundSpecialization == null) { | 801 if (foundSpecialization == null) { |
778 AnnotationValue value = ElementUtils.getAnnotationValue(specialization.getMarkerAnnotation(), "contains"); | 802 AnnotationValue value = ElementUtils.getAnnotationValue(specialization.getMarkerAnnotation(), "contains"); |
779 specialization.addError(value, "The referenced specialization '%s' could not be found.", includeName); | 803 specialization.addError(value, "The referenced specialization '%s' could not be found.", includeName); |
780 } else { | 804 } else { |
781 if (!foundSpecialization.isContainedBy(specialization)) { | 805 if (foundSpecialization.compareTo(specialization) > 0) { |
782 AnnotationValue value = ElementUtils.getAnnotationValue(specialization.getMarkerAnnotation(), "contains"); | 806 AnnotationValue value = ElementUtils.getAnnotationValue(specialization.getMarkerAnnotation(), "contains"); |
783 if (foundSpecialization.compareTo(specialization) > 0) { | 807 if (foundSpecialization.compareTo(specialization) > 0) { |
784 specialization.addError(value, "The contained specialization '%s' must be declared before the containing specialization.", includeName); | 808 specialization.addError(value, "The contained specialization '%s' must be declared before the containing specialization.", includeName); |
785 }/* | 809 } |
786 * else { specialization.addError(value, | |
787 * "The contained specialization '%s' is not fully compatible. The contained specialization must be strictly more generic than the containing one." | |
788 * , includeName); } | |
789 */ | |
790 | 810 |
791 } | 811 } |
792 resolvedSpecializations.add(foundSpecialization); | 812 resolvedSpecializations.add(foundSpecialization); |
793 } | 813 } |
794 } | 814 } |
933 } | 953 } |
934 | 954 |
935 private void initializeExpressions(List<? extends Element> elements, NodeData node) { | 955 private void initializeExpressions(List<? extends Element> elements, NodeData node) { |
936 List<Element> members = filterNotAccessibleElements(node.getTemplateType(), elements); | 956 List<Element> members = filterNotAccessibleElements(node.getTemplateType(), elements); |
937 | 957 |
938 final TypeMirror booleanType = context.getType(boolean.class); | 958 List<VariableElement> fields = new ArrayList<>(); |
959 for (NodeFieldData field : node.getFields()) { | |
960 fields.add(field.getVariable()); | |
961 } | |
939 | 962 |
940 for (SpecializationData specialization : node.getSpecializations()) { | 963 for (SpecializationData specialization : node.getSpecializations()) { |
941 if (specialization.getMethod() == null) { | 964 if (specialization.getMethod() == null) { |
942 continue; | 965 continue; |
943 } | 966 } |
944 | 967 |
945 List<Element> specializationMembers = new ArrayList<>(); | 968 List<Element> specializationMembers = new ArrayList<>(members.size() + specialization.getParameters().size() + fields.size()); |
946 for (Parameter p : specialization.getParameters()) { | 969 for (Parameter p : specialization.getParameters()) { |
947 VariableElement variableElement = p.getVariableElement(); | 970 specializationMembers.add(p.getVariableElement()); |
948 if (variableElement == null) { | 971 } |
949 throw new AssertionError("All parameters must be resolved for " + specialization); | 972 specializationMembers.addAll(fields); |
950 } | |
951 | |
952 specializationMembers.add(variableElement); | |
953 } | |
954 specializationMembers.addAll(members); | 973 specializationMembers.addAll(members); |
955 | |
956 DSLExpressionResolver resolver = new DSLExpressionResolver(context, specializationMembers); | 974 DSLExpressionResolver resolver = new DSLExpressionResolver(context, specializationMembers); |
957 List<String> guardDefinitions = ElementUtils.getAnnotationValueList(String.class, specialization.getMarkerAnnotation(), "guards"); | 975 |
958 List<GuardExpression> guardExpressions = new ArrayList<>(); | 976 initializeCaches(specialization, resolver); |
959 for (String guard : guardDefinitions) { | 977 initializeGuards(specialization, resolver); |
960 GuardExpression guardExpression; | 978 if (specialization.hasErrors()) { |
979 continue; | |
980 } | |
981 initializeLimit(specialization, resolver); | |
982 } | |
983 } | |
984 | |
985 private void initializeLimit(SpecializationData specialization, DSLExpressionResolver resolver) { | |
986 AnnotationValue annotationValue = ElementUtils.getAnnotationValue(specialization.getMessageAnnotation(), "limit"); | |
987 | |
988 String limitValue; | |
989 if (annotationValue == null) { | |
990 limitValue = ""; | |
991 } else { | |
992 limitValue = (String) annotationValue.getValue(); | |
993 } | |
994 if (limitValue.isEmpty()) { | |
995 limitValue = "3"; | |
996 } else if (!specialization.hasMultipleInstances()) { | |
997 specialization.addWarning(annotationValue, "The limit expression has no effect. Multiple specialization instantiations are impossible for this specialization."); | |
998 return; | |
999 } | |
1000 | |
1001 TypeMirror expectedType = context.getType(int.class); | |
1002 try { | |
1003 DSLExpression expression = DSLExpression.parse(limitValue); | |
1004 expression.accept(resolver); | |
1005 if (!ElementUtils.typeEquals(expression.getResolvedType(), expectedType)) { | |
1006 specialization.addError(annotationValue, "Incompatible return type %s. Limit expressions must return %s.", ElementUtils.getSimpleName(expression.getResolvedType()), | |
1007 ElementUtils.getSimpleName(expectedType)); | |
1008 } | |
1009 if (specialization.isDynamicParameterBound(expression)) { | |
1010 specialization.addError(annotationValue, "Limit expressions must not bind dynamic parameter values."); | |
1011 } | |
1012 | |
1013 specialization.setLimitExpression(expression); | |
1014 } catch (InvalidExpressionException e) { | |
1015 specialization.addError(annotationValue, "Error parsing expression '%s': %s", limitValue, e.getMessage()); | |
1016 } | |
1017 } | |
1018 | |
1019 private void initializeCaches(SpecializationData specialization, DSLExpressionResolver resolver) { | |
1020 TypeMirror cacheMirror = context.getType(Cached.class); | |
1021 List<CacheExpression> expressions = new ArrayList<>(); | |
1022 for (Parameter parameter : specialization.getParameters()) { | |
1023 AnnotationMirror annotationMirror = ElementUtils.findAnnotationMirror(parameter.getVariableElement().getAnnotationMirrors(), cacheMirror); | |
1024 if (annotationMirror != null) { | |
1025 String initializer = ElementUtils.getAnnotationValue(String.class, annotationMirror, "value"); | |
1026 | |
1027 TypeMirror parameterType = parameter.getType(); | |
1028 | |
1029 DSLExpressionResolver localResolver = resolver; | |
1030 if (parameterType.getKind() == TypeKind.DECLARED) { | |
1031 localResolver = localResolver.copy(importPublicStaticMembers(ElementUtils.fromTypeMirror(parameterType), true)); | |
1032 } | |
1033 | |
1034 CacheExpression cacheExpression; | |
961 DSLExpression expression = null; | 1035 DSLExpression expression = null; |
962 try { | 1036 try { |
963 expression = DSLExpression.parse(guard); | 1037 expression = DSLExpression.parse(initializer); |
964 expression.accept(resolver); | 1038 expression.accept(localResolver); |
965 guardExpression = new GuardExpression(specialization, expression); | 1039 cacheExpression = new CacheExpression(parameter, annotationMirror, expression); |
966 if (!ElementUtils.typeEquals(expression.getResolvedType(), booleanType)) { | 1040 if (!ElementUtils.typeEquals(expression.getResolvedType(), parameter.getType())) { |
967 guardExpression.addError("Incompatible return type %s. Guard expressions must return boolean.", ElementUtils.getSimpleName(expression.getResolvedType())); | 1041 cacheExpression.addError("Incompatible return type %s. The expression type must be equal to the parameter type %s.", ElementUtils.getSimpleName(expression.getResolvedType()), |
1042 ElementUtils.getSimpleName(parameter.getType())); | |
968 } | 1043 } |
969 // guardExpression.addWarning("Expression:%s", expression.toString()); | |
970 } catch (InvalidExpressionException e) { | 1044 } catch (InvalidExpressionException e) { |
971 guardExpression = new GuardExpression(specialization, null); | 1045 cacheExpression = new CacheExpression(parameter, annotationMirror, null); |
972 guardExpression.addError("Error parsing expression '%s': %s", guard, e.getMessage()); | 1046 cacheExpression.addError("Error parsing expression '%s': %s", initializer, e.getMessage()); |
973 } | 1047 } |
974 guardExpressions.add(guardExpression); | 1048 expressions.add(cacheExpression); |
975 } | 1049 } |
976 specialization.setGuards(guardExpressions); | 1050 } |
977 } | 1051 specialization.setCaches(expressions); |
1052 | |
1053 if (specialization.hasErrors()) { | |
1054 return; | |
1055 } | |
1056 | |
1057 // verify that cache expressions are bound in the correct order. | |
1058 for (int i = 0; i < expressions.size(); i++) { | |
1059 CacheExpression currentExpression = expressions.get(i); | |
1060 Set<VariableElement> boundVariables = currentExpression.getExpression().findBoundVariableElements(); | |
1061 for (int j = i + 1; j < expressions.size(); j++) { | |
1062 CacheExpression boundExpression = expressions.get(j); | |
1063 if (boundVariables.contains(boundExpression.getParameter().getVariableElement())) { | |
1064 currentExpression.addError("The initializer expression of parameter '%s' binds unitialized parameter '%s. Reorder the parameters to resolve the problem.", | |
1065 currentExpression.getParameter().getLocalName(), boundExpression.getParameter().getLocalName()); | |
1066 break; | |
1067 } | |
1068 } | |
1069 } | |
1070 } | |
1071 | |
1072 private void initializeGuards(SpecializationData specialization, DSLExpressionResolver resolver) { | |
1073 final TypeMirror booleanType = context.getType(boolean.class); | |
1074 List<String> guardDefinitions = ElementUtils.getAnnotationValueList(String.class, specialization.getMarkerAnnotation(), "guards"); | |
1075 List<GuardExpression> guardExpressions = new ArrayList<>(); | |
1076 for (String guard : guardDefinitions) { | |
1077 GuardExpression guardExpression; | |
1078 DSLExpression expression = null; | |
1079 try { | |
1080 expression = DSLExpression.parse(guard); | |
1081 expression.accept(resolver); | |
1082 guardExpression = new GuardExpression(specialization, expression); | |
1083 if (!ElementUtils.typeEquals(expression.getResolvedType(), booleanType)) { | |
1084 guardExpression.addError("Incompatible return type %s. Guards must return %s.", ElementUtils.getSimpleName(expression.getResolvedType()), ElementUtils.getSimpleName(booleanType)); | |
1085 } | |
1086 } catch (InvalidExpressionException e) { | |
1087 guardExpression = new GuardExpression(specialization, null); | |
1088 guardExpression.addError("Error parsing expression '%s': %s", guard, e.getMessage()); | |
1089 } | |
1090 guardExpressions.add(guardExpression); | |
1091 } | |
1092 specialization.setGuards(guardExpressions); | |
978 } | 1093 } |
979 | 1094 |
980 private static List<Element> filterNotAccessibleElements(TypeElement templateType, List<? extends Element> elements) { | 1095 private static List<Element> filterNotAccessibleElements(TypeElement templateType, List<? extends Element> elements) { |
981 String packageName = ElementUtils.getPackageName(templateType); | 1096 String packageName = ElementUtils.getPackageName(templateType); |
982 List<Element> filteredElements = new ArrayList<>(elements); | 1097 List<Element> filteredElements = new ArrayList<>(elements); |
1028 | 1143 |
1029 private SpecializationData createGenericSpecialization(final NodeData node) { | 1144 private SpecializationData createGenericSpecialization(final NodeData node) { |
1030 GenericParser parser = new GenericParser(context, node); | 1145 GenericParser parser = new GenericParser(context, node); |
1031 MethodSpec specification = parser.createDefaultMethodSpec(node.getSpecializations().iterator().next().getMethod(), null, true, null); | 1146 MethodSpec specification = parser.createDefaultMethodSpec(node.getSpecializations().iterator().next().getMethod(), null, true, null); |
1032 | 1147 |
1033 List<TypeMirror> parameterTypes = new ArrayList<>(); | 1148 List<VariableElement> parameterTypes = new ArrayList<>(); |
1034 int signatureIndex = 1; | 1149 int signatureIndex = 1; |
1035 for (ParameterSpec spec : specification.getRequired()) { | 1150 for (ParameterSpec spec : specification.getRequired()) { |
1036 parameterTypes.add(createGenericType(spec, node.getSpecializations(), signatureIndex)); | 1151 parameterTypes.add(new CodeVariableElement(createGenericType(spec, node.getSpecializations(), signatureIndex), "arg" + signatureIndex)); |
1037 if (spec.isSignature()) { | 1152 if (spec.isSignature()) { |
1038 signatureIndex++; | 1153 signatureIndex++; |
1039 } | 1154 } |
1040 } | 1155 } |
1041 | 1156 |