comparison graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/NodeParser.java @ 16851:2db61eddcb97

Truffle-DSL: argument syntax support for guards
author Christian Humer <christian.humer@gmail.com>
date Mon, 18 Aug 2014 18:41:16 +0200
parents 21e0ab3c1395
children 09d99d3c0c95
comparison
equal deleted inserted replaced
16850:d6c002f4d2a9 16851:2db61eddcb97
188 if (importGuardClass.getKind() != TypeKind.DECLARED) { 188 if (importGuardClass.getKind() != TypeKind.DECLARED) {
189 node.addError(importAnnotation, importClassesValue, "The specified import guard class '%s' is not a declared type.", ElementUtils.getQualifiedName(importGuardClass)); 189 node.addError(importAnnotation, importClassesValue, "The specified import guard class '%s' is not a declared type.", ElementUtils.getQualifiedName(importGuardClass));
190 continue; 190 continue;
191 } 191 }
192 TypeElement typeElement = ElementUtils.fromTypeMirror(importGuardClass); 192 TypeElement typeElement = ElementUtils.fromTypeMirror(importGuardClass);
193 if (!typeElement.getModifiers().contains(Modifier.PUBLIC)) { 193
194 // hack to reload type is necessary for incremental compiling in eclipse.
195 // otherwise methods inside of import guard types are just not found.
196 typeElement = ElementUtils.fromTypeMirror(context.reloadType(typeElement.asType()));
197
198 if (typeElement.getEnclosingElement().getKind().isClass() && !typeElement.getModifiers().contains(Modifier.PUBLIC)) {
194 node.addError(importAnnotation, importClassesValue, "The specified import guard class '%s' must be public.", ElementUtils.getQualifiedName(importGuardClass)); 199 node.addError(importAnnotation, importClassesValue, "The specified import guard class '%s' must be public.", ElementUtils.getQualifiedName(importGuardClass));
195 continue; 200 continue;
196 } 201 }
197 202
198 List<? extends ExecutableElement> importMethods = ElementFilter.methodsIn(processingEnv.getElementUtils().getAllMembers(typeElement)); 203 List<? extends ExecutableElement> importMethods = ElementFilter.methodsIn(processingEnv.getElementUtils().getAllMembers(typeElement));
204
199 for (ExecutableElement importMethod : importMethods) { 205 for (ExecutableElement importMethod : importMethods) {
200 if (!importMethod.getModifiers().contains(Modifier.PUBLIC) || !importMethod.getModifiers().contains(Modifier.STATIC)) { 206 if (!importMethod.getModifiers().contains(Modifier.PUBLIC) || !importMethod.getModifiers().contains(Modifier.STATIC)) {
201 continue; 207 continue;
202 } 208 }
203 elements.add(importMethod); 209 elements.add(importMethod);
881 887
882 return signatures; 888 return signatures;
883 } 889 }
884 890
885 private void initializeGuards(List<? extends Element> elements, NodeData node) { 891 private void initializeGuards(List<? extends Element> elements, NodeData node) {
886 Map<String, List<GuardData>> guards = new HashMap<>(); 892 Map<String, List<ExecutableElement>> potentialGuards = new HashMap<>();
887 for (SpecializationData specialization : node.getSpecializations()) { 893 for (SpecializationData specialization : node.getSpecializations()) {
888 for (GuardExpression exp : specialization.getGuards()) { 894 for (GuardExpression exp : specialization.getGuards()) {
889 guards.put(exp.getGuardName(), null); 895 potentialGuards.put(exp.getGuardName(), null);
890 } 896 }
891 } 897 }
892 898
893 GuardParser parser = new GuardParser(context, node, null, guards.keySet()); 899 TypeMirror booleanType = context.getType(boolean.class);
894 List<GuardData> resolvedGuards = parser.parse(elements); 900 for (ExecutableElement potentialGuard : ElementFilter.methodsIn(elements)) {
895 for (GuardData guard : resolvedGuards) { 901 if (potentialGuard.getModifiers().contains(Modifier.PRIVATE)) {
896 List<GuardData> groupedGuards = guards.get(guard.getMethodName()); 902 continue;
897 if (groupedGuards == null) { 903 }
898 groupedGuards = new ArrayList<>(); 904 String methodName = potentialGuard.getSimpleName().toString();
899 guards.put(guard.getMethodName(), groupedGuards); 905 if (!potentialGuards.containsKey(methodName)) {
900 } 906 continue;
901 groupedGuards.add(guard); 907 }
908
909 if (!ElementUtils.typeEquals(potentialGuard.getReturnType(), booleanType)) {
910 continue;
911 }
912
913 List<ExecutableElement> potentialMethods = potentialGuards.get(methodName);
914 if (potentialMethods == null) {
915 potentialMethods = new ArrayList<>();
916 potentialGuards.put(methodName, potentialMethods);
917 }
918 potentialMethods.add(potentialGuard);
902 } 919 }
903 920
904 for (SpecializationData specialization : node.getSpecializations()) { 921 for (SpecializationData specialization : node.getSpecializations()) {
905 for (GuardExpression exp : specialization.getGuards()) { 922 for (GuardExpression exp : specialization.getGuards()) {
906 resolveGuardExpression(node, specialization, guards, exp); 923 resolveGuardExpression(node, specialization, potentialGuards, exp);
907 } 924 }
908 } 925 }
909 } 926 }
910 927
911 private void resolveGuardExpression(NodeData node, TemplateMethod source, Map<String, List<GuardData>> guards, GuardExpression expression) { 928 private void resolveGuardExpression(NodeData node, TemplateMethod source, Map<String, List<ExecutableElement>> guards, GuardExpression expression) {
912 List<GuardData> availableGuards = guards.get(expression.getGuardName()); 929 List<ExecutableElement> availableGuards = guards.get(expression.getGuardName());
913 if (availableGuards == null) { 930 if (availableGuards == null) {
914 source.addError("No compatible guard with method name '%s' found. Please note that all signature types of the method guard must be declared in the type system.", expression.getGuardName()); 931 source.addError("No compatible guard with method name '%s' found.", expression.getGuardName());
915 return; 932 return;
916 } 933 }
917 List<ExecutableElement> guardMethods = new ArrayList<>(); 934
918 for (GuardData guard : availableGuards) { 935 String[] childNames = expression.getChildNames();
919 guardMethods.add(guard.getMethod()); 936 if (childNames != null) {
920 } 937 NodeExecutionData[] resolvedExecutions = new NodeExecutionData[childNames.length];
921 GuardParser parser = new GuardParser(context, node, source, null); 938 for (int i = 0; i < childNames.length; i++) {
922 List<GuardData> matchingGuards = parser.parse(guardMethods); 939 String childName = childNames[i];
940 NodeExecutionData execution = node.findExecutionByExpression(childName);
941 if (execution == null) {
942 source.addError("Guard parameter '%s' for guard '%s' could not be mapped to a declared child node.", childName, expression.getGuardName());
943 return;
944 }
945 resolvedExecutions[i] = execution;
946 }
947 expression.setResolvedChildren(resolvedExecutions);
948 }
949
950 GuardParser parser = new GuardParser(context, node, source, expression);
951 List<GuardData> matchingGuards = parser.parse(availableGuards);
923 if (!matchingGuards.isEmpty()) { 952 if (!matchingGuards.isEmpty()) {
924 GuardData guard = matchingGuards.get(0); 953 GuardData guard = matchingGuards.get(0);
925 // use the shared instance of the guard data 954 // use the shared instance of the guard data
926 for (GuardData guardData : availableGuards) { 955 expression.setResolvedGuard(guard);
927 if (guardData.getMethod() == guard.getMethod()) {
928 expression.setGuard(guardData);
929 return;
930 }
931 }
932 throw new AssertionError("Should not reach here.");
933 } else { 956 } else {
934 MethodSpec spec = parser.createSpecification(source.getMethod(), source.getMarkerAnnotation()); 957 MethodSpec spec = parser.createSpecification(source.getMethod(), source.getMarkerAnnotation());
935 spec.applyTypeDefinitions("types"); 958 spec.applyTypeDefinitions("types");
936 source.addError("No guard with name '%s' matched the required signature. Expected signature: %n%s", expression.getGuardName(), spec.toSignatureString("guard")); 959 source.addError("No guard with name '%s' matched the required signature. Expected signature: %n%s", expression.getGuardName(), spec.toSignatureString("guard"));
937 } 960 }