comparison graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeCodeGenerator.java @ 8245:703c09f8640c

Implemented support for @NodeClass annotation to support builtins.
author Christian Humer <christian.humer@gmail.com>
date Wed, 06 Mar 2013 18:32:33 +0100
parents d81ff782fa1a
children c4c3f50fa9c2
comparison
equal deleted inserted replaced
8244:10d37f893471 8245:703c09f8640c
49 private TypeMirror getUnexpectedValueException() { 49 private TypeMirror getUnexpectedValueException() {
50 return getContext().getTruffleTypes().getUnexpectedValueException(); 50 return getContext().getTruffleTypes().getUnexpectedValueException();
51 } 51 }
52 52
53 private static String factoryClassName(NodeData node) { 53 private static String factoryClassName(NodeData node) {
54 return nodeClassName(node) + "Factory"; 54 return node.getNodeId() + "Factory";
55 } 55 }
56 56
57 private static String nodeClassName(NodeData node) { 57 private static String nodeSpecializationClassName(SpecializationData specialization) {
58 return Utils.getSimpleName(node.getTemplateType().asType()); 58 String nodeid = specialization.getNode().getNodeId();
59 } 59 if (nodeid.endsWith("Node") && !nodeid.equals("Node")) {
60 60 nodeid = nodeid.substring(0, nodeid.length() - 4);
61 private static String nodeClassName(SpecializationData specialization) { 61 }
62 String name = specializationId(specialization); 62
63 name += nodeClassName(specialization.getNode()); 63 String name = Utils.firstLetterUpperCase(nodeid);
64 if (name.equals(Utils.getSimpleName(specialization.getNode().getNodeType())) || name.equals(Utils.getSimpleName(specialization.getNode().getTemplateType()))) { 64 name += Utils.firstLetterUpperCase(specialization.getId());
65 name = name + "Impl"; 65 name += "Node";
66 }
67
68 return name;
69 }
70
71 private static String specializationId(SpecializationData specialization) {
72 String name = "";
73 NodeData node = specialization.getNode();
74 if (node.getSpecializations().size() > 1) {
75 name = specialization.getMethodName();
76 if (name.startsWith("do")) {
77 name = name.substring(2);
78 }
79 }
80 return name; 66 return name;
81 } 67 }
82 68
83 private static String valueName(ActualParameter param) { 69 private static String valueName(ActualParameter param) {
84 return param.getName(); 70 return param.getName();
86 72
87 private static String castValueName(ActualParameter parameter) { 73 private static String castValueName(ActualParameter parameter) {
88 return valueName(parameter) + "Cast"; 74 return valueName(parameter) + "Cast";
89 } 75 }
90 76
91 private void addValueParameters(CodeExecutableElement method, TemplateMethod specialization, boolean forceFrame) { 77 private void addValueParameters(CodeExecutableElement method, TemplateMethod specialization, boolean forceFrame, boolean includeHidden) {
92 if (forceFrame && specialization.getSpecification().findParameterSpec("frame") != null) { 78 if (forceFrame && specialization.getSpecification().findParameterSpec("frame") != null) {
93 method.addParameter(new CodeVariableElement(getContext().getTruffleTypes().getFrame(), "frameValue")); 79 method.addParameter(new CodeVariableElement(getContext().getTruffleTypes().getFrame(), "frameValue"));
94 } 80 }
95 for (ActualParameter parameter : specialization.getParameters()) { 81 for (ActualParameter parameter : specialization.getParameters()) {
96 ParameterSpec spec = parameter.getSpecification(); 82 ParameterSpec spec = parameter.getSpecification();
97 if (forceFrame && spec.getName().equals("frame")) { 83 if (forceFrame && spec.getName().equals("frame")) {
98 continue; 84 continue;
99 } 85 }
86 if (!includeHidden && parameter.isHidden()) {
87 continue;
88 }
89
100 method.addParameter(new CodeVariableElement(parameter.getActualType(), valueName(parameter))); 90 method.addParameter(new CodeVariableElement(parameter.getActualType(), valueName(parameter)));
101 } 91 }
102 } 92 }
103 93
104 private static void addValueParameterNames(CodeTreeBuilder builder, TemplateMethod specialization, String unexpectedValueName, boolean forceFrame) { 94 private static void addValueParameterNames(CodeTreeBuilder builder, TemplateMethod specialization, String unexpectedValueName, boolean forceFrame, boolean includeHidden) {
105 if (forceFrame && specialization.getSpecification().findParameterSpec("frame") != null) { 95 if (forceFrame && specialization.getSpecification().findParameterSpec("frame") != null) {
106 builder.string("frameValue"); 96 builder.string("frameValue");
107 } 97 }
108 for (ActualParameter parameter : specialization.getParameters()) { 98 for (ActualParameter parameter : specialization.getParameters()) {
109 ParameterSpec spec = parameter.getSpecification(); 99 ParameterSpec spec = parameter.getSpecification();
110 if (forceFrame && spec.getName().equals("frame")) { 100 if (forceFrame && spec.getName().equals("frame")) {
111 continue; 101 continue;
112 } 102 }
113 103
104 if (!includeHidden && parameter.isHidden()) {
105 continue;
106 }
107
114 if (unexpectedValueName != null && parameter.getName().equals(unexpectedValueName)) { 108 if (unexpectedValueName != null && parameter.getName().equals(unexpectedValueName)) {
115 builder.string("ex.getResult()"); 109 builder.string("ex.getResult()");
116 } else { 110 } else {
117 builder.string(valueName(parameter)); 111 builder.string(valueName(parameter));
118 } 112 }
119 } 113 }
120 } 114 }
121 115
122 private static void addValueParameterNamesWithCasts(CodeTreeBuilder body, SpecializationData valueSpecialization, SpecializationData targetSpecialization) { 116 private static void addValueParameterNamesWithCasts(CodeTreeBuilder body, SpecializationData valueSpecialization, SpecializationData targetSpecialization, boolean includeHidden) {
123 NodeData node = targetSpecialization.getNode(); 117 NodeData node = targetSpecialization.getNode();
124 TypeSystemData typeSystem = node.getTypeSystem(); 118 TypeSystemData typeSystem = node.getTypeSystem();
125 119
126 for (ActualParameter targetParameter : targetSpecialization.getParameters()) { 120 for (ActualParameter targetParameter : targetSpecialization.getParameters()) {
127 ActualParameter valueParameter = valueSpecialization.findParameter(targetParameter.getName()); 121 ActualParameter valueParameter = valueSpecialization.findParameter(targetParameter.getName());
128 TypeData targetType = targetParameter.getActualTypeData(typeSystem); 122 TypeData targetType = targetParameter.getActualTypeData(typeSystem);
129 123
124 if (!includeHidden && (targetParameter.isHidden() || valueParameter.isHidden())) {
125 continue;
126 }
127
130 TypeData valueType = null; 128 TypeData valueType = null;
131 if (valueParameter != null) { 129 if (valueParameter != null) {
132 valueType = valueParameter.getActualTypeData(typeSystem); 130 valueType = valueParameter.getActualTypeData(typeSystem);
133 } 131 }
134 132
142 140
143 private static String genClassName(Template operation) { 141 private static String genClassName(Template operation) {
144 return getSimpleName(operation.getTemplateType()) + "Gen"; 142 return getSimpleName(operation.getTemplateType()) + "Gen";
145 } 143 }
146 144
147 private static void startCallOperationMethod(CodeTreeBuilder body, TemplateMethod method) { 145 private static void startCallOperationMethod(CodeTreeBuilder body, TemplateMethod templateMethod, boolean castedValues) {
148 body.startGroup(); 146 body.startGroup();
149 if (body.findMethod().getModifiers().contains(STATIC)) { 147 ExecutableElement method = templateMethod.getMethod();
150 body.string(THIS_NODE_LOCAL_VAR_NAME); 148
149 TypeElement targetClass = Utils.findNearestEnclosingType(method.getEnclosingElement());
150 NodeData node = (NodeData) templateMethod.getTemplate();
151
152 boolean accessible = templateMethod.canBeAccessedByInstanceOf(node.getNodeType());
153 if (accessible) {
154 if (body.findMethod().getModifiers().contains(STATIC)) {
155 body.string(THIS_NODE_LOCAL_VAR_NAME);
156 } else {
157 body.string("super");
158 }
151 } else { 159 } else {
152 body.string("super"); 160 if (method.getModifiers().contains(STATIC)) {
161 body.type(targetClass.asType());
162 } else {
163 ActualParameter parameter = templateMethod.getParameters().get(0);
164 if (castedValues) {
165 body.string(castValueName(parameter));
166 } else {
167 body.string(valueName(parameter));
168 }
169 }
153 } 170 }
154 body.string("."); 171 body.string(".");
155 body.startCall(method.getMethodName()); 172 body.startCall(method.getSimpleName().toString());
156 } 173 }
157 174
158 private static String generatedGenericMethodName(SpecializationData specialization) { 175 private static String generatedGenericMethodName(SpecializationData specialization) {
159 final String prefix = "generic"; 176 final String prefix = "generic";
160 177
166 for (SpecializationData current : specialization.getNode().getSpecializations()) { 183 for (SpecializationData current : specialization.getNode().getSpecializations()) {
167 if (specialization == current) { 184 if (specialization == current) {
168 if (prev == null || prev.isUninitialized()) { 185 if (prev == null || prev.isUninitialized()) {
169 return prefix; 186 return prefix;
170 } else { 187 } else {
171 return prefix + specializationId(current); 188 return prefix + current.getId();
172 } 189 }
173 } 190 }
174 prev = current; 191 prev = current;
175 } 192 }
176 return prefix; 193 return prefix;
247 // Explicitly specified guards 264 // Explicitly specified guards
248 for (SpecializationGuardData guard : guardedSpecialization.getGuards()) { 265 for (SpecializationGuardData guard : guardedSpecialization.getGuards()) {
249 if ((guard.isOnSpecialization() && onSpecialization) || (guard.isOnExecution() && !onSpecialization)) { 266 if ((guard.isOnSpecialization() && onSpecialization) || (guard.isOnExecution() && !onSpecialization)) {
250 builder.string(andOperator); 267 builder.string(andOperator);
251 268
252 startCallOperationMethod(builder, guard.getGuardDeclaration()); 269 startCallOperationMethod(builder, guard.getGuardDeclaration(), true);
253 addValueParameterNamesWithCasts(builder, valueSpecialization, guardedSpecialization); 270 addValueParameterNamesWithCasts(builder, valueSpecialization, guardedSpecialization, false);
254 271
255 builder.end().end(); // call 272 builder.end().end(); // call
256 andOperator = " && "; 273 andOperator = " && ";
257 } 274 }
258 } 275 }
703 if (node.needsFactory()) { 720 if (node.needsFactory()) {
704 children.add(node); 721 children.add(node);
705 } 722 }
706 723
707 List<TypeMirror> nodeTypesList = new ArrayList<>(); 724 List<TypeMirror> nodeTypesList = new ArrayList<>();
725 TypeMirror prev = null;
726 boolean allSame = true;
708 for (NodeData child : children) { 727 for (NodeData child : children) {
709 nodeTypesList.add(child.getTemplateType().asType()); 728 nodeTypesList.add(child.getNodeType());
729 if (prev != null && !Utils.typeEquals(child.getNodeType(), prev)) {
730 allSame = false;
731 }
732 prev = child.getNodeType();
710 } 733 }
711 TypeMirror commonNodeSuperType = Utils.getCommonSuperType(getContext(), nodeTypesList.toArray(new TypeMirror[nodeTypesList.size()])); 734 TypeMirror commonNodeSuperType = Utils.getCommonSuperType(getContext(), nodeTypesList.toArray(new TypeMirror[nodeTypesList.size()]));
712 735
713 Types types = getContext().getEnvironment().getTypeUtils(); 736 Types types = getContext().getEnvironment().getTypeUtils();
714 TypeMirror factoryType = getContext().getType(NodeFactory.class); 737 TypeMirror factoryType = getContext().getType(NodeFactory.class);
715 TypeMirror baseType; 738 TypeMirror baseType;
716 if (children.size() == 1) { 739 if (allSame) {
717 baseType = types.getDeclaredType(Utils.fromTypeMirror(factoryType), commonNodeSuperType); 740 baseType = types.getDeclaredType(Utils.fromTypeMirror(factoryType), commonNodeSuperType);
718 } else { 741 } else {
719 baseType = types.getDeclaredType(Utils.fromTypeMirror(factoryType), types.getWildcardType(commonNodeSuperType, null)); 742 baseType = types.getDeclaredType(Utils.fromTypeMirror(factoryType), types.getWildcardType(commonNodeSuperType, null));
720 } 743 }
721 TypeMirror listType = types.getDeclaredType(Utils.fromTypeMirror(getContext().getType(List.class)), baseType); 744 TypeMirror listType = types.getDeclaredType(Utils.fromTypeMirror(getContext().getType(List.class)), baseType);
782 CodeTreeBuilder body = method.createBuilder(); 805 CodeTreeBuilder body = method.createBuilder();
783 body.startReturn(); 806 body.startReturn();
784 if (node.getSpecializations().isEmpty()) { 807 if (node.getSpecializations().isEmpty()) {
785 body.null_(); 808 body.null_();
786 } else { 809 } else {
787 body.startNew(nodeClassName(node.getSpecializations().get(0))); 810 body.startNew(nodeSpecializationClassName(node.getSpecializations().get(0)));
788 for (VariableElement var : method.getParameters()) { 811 for (VariableElement var : method.getParameters()) {
789 body.string(var.getSimpleName().toString()); 812 body.string(var.getSimpleName().toString());
790 } 813 }
791 body.end(); 814 body.end();
792 } 815 }
814 first = false; 837 first = false;
815 } else { 838 } else {
816 body.startElseIf(); 839 body.startElseIf();
817 } 840 }
818 body.string("specializationClass == ").type(type.getBoxedType()).string(".class").end().startBlock(); 841 body.string("specializationClass == ").type(type.getBoxedType()).string(".class").end().startBlock();
819 body.startReturn().startNew(nodeClassName(specialization)); 842 body.startReturn().startNew(nodeSpecializationClassName(specialization));
820 body.string(THIS_NODE_LOCAL_VAR_NAME); 843 body.string(THIS_NODE_LOCAL_VAR_NAME);
821 body.end().end(); // new, return 844 body.end().end(); // new, return
822 845
823 body.end(); // if 846 body.end(); // if
824 } 847 }
825 } 848 }
826 body.startReturn().startNew(nodeClassName(node.getGenericSpecialization())); 849 body.startReturn().startNew(nodeSpecializationClassName(node.getGenericSpecialization()));
827 body.string(THIS_NODE_LOCAL_VAR_NAME); 850 body.string(THIS_NODE_LOCAL_VAR_NAME);
828 body.end().end(); 851 body.end().end();
829 return method; 852 return method;
830 } 853 }
831 854
832 private CodeExecutableElement createSpecializeMethod(NodeData node) { 855 private CodeExecutableElement createSpecializeMethod(NodeData node) {
833 CodeExecutableElement method = new CodeExecutableElement(modifiers(PRIVATE, STATIC), node.getNodeType(), "specialize"); 856 CodeExecutableElement method = new CodeExecutableElement(modifiers(PRIVATE, STATIC), node.getNodeType(), "specialize");
834 method.addParameter(new CodeVariableElement(node.getNodeType(), THIS_NODE_LOCAL_VAR_NAME)); 857 method.addParameter(new CodeVariableElement(node.getNodeType(), THIS_NODE_LOCAL_VAR_NAME));
835 method.addParameter(new CodeVariableElement(getContext().getType(Class.class), "minimumState")); 858 method.addParameter(new CodeVariableElement(getContext().getType(Class.class), "minimumState"));
836 addValueParameters(method, node.getGenericSpecialization(), false); 859 addValueParameters(method, node.getGenericSpecialization(), false, true);
837 860
838 CodeTreeBuilder body = method.createBuilder(); 861 CodeTreeBuilder body = method.createBuilder();
839 body.startStatement().string("boolean allowed = (minimumState == ").string(nodeClassName(node.getSpecializations().get(0))).string(".class)").end(); 862 body.startStatement().string("boolean allowed = (minimumState == ").string(nodeSpecializationClassName(node.getSpecializations().get(0))).string(".class)").end();
840 863
841 for (int i = 1; i < node.getSpecializations().size(); i++) { 864 for (int i = 1; i < node.getSpecializations().size(); i++) {
842 SpecializationData specialization = node.getSpecializations().get(i); 865 SpecializationData specialization = node.getSpecializations().get(i);
843 body.startStatement().string("allowed = allowed || (minimumState == ").string(nodeClassName(specialization)).string(".class)").end(); 866 body.startStatement().string("allowed = allowed || (minimumState == ").string(nodeSpecializationClassName(specialization)).string(".class)").end();
844 867
845 CodeTreeBuilder guarded = new CodeTreeBuilder(body); 868 CodeTreeBuilder guarded = new CodeTreeBuilder(body);
846 guarded.startReturn().startNew(nodeClassName(specialization)); 869 guarded.startReturn().startNew(nodeSpecializationClassName(specialization));
847 guarded.string(THIS_NODE_LOCAL_VAR_NAME); 870 guarded.string(THIS_NODE_LOCAL_VAR_NAME);
848 guarded.end().end(); 871 guarded.end().end();
849 872
850 body.tree(createGuardAndCast(body, "allowed", node.getGenericSpecialization(), specialization, true, guarded.getRoot(), null)); 873 body.tree(createGuardAndCast(body, "allowed", node.getGenericSpecialization(), specialization, true, guarded.getRoot(), null));
851 } 874 }
869 continue; 892 continue;
870 } else { 893 } else {
871 String methodName = generatedGenericMethodName(current); 894 String methodName = generatedGenericMethodName(current);
872 CodeExecutableElement method = new CodeExecutableElement(modifiers(PRIVATE, STATIC), genericReturnType, methodName); 895 CodeExecutableElement method = new CodeExecutableElement(modifiers(PRIVATE, STATIC), genericReturnType, methodName);
873 method.addParameter(new CodeVariableElement(node.getNodeType(), THIS_NODE_LOCAL_VAR_NAME)); 896 method.addParameter(new CodeVariableElement(node.getNodeType(), THIS_NODE_LOCAL_VAR_NAME));
874 addValueParameters(method, node.getGenericSpecialization(), true); 897 addValueParameters(method, node.getGenericSpecialization(), true, true);
875 898
876 emitGeneratedGenericSpecialization(method.createBuilder(), current, next); 899 emitGeneratedGenericSpecialization(method.createBuilder(), current, next);
877 900
878 methods.add(method); 901 methods.add(method);
879 } 902 }
882 905
883 return methods; 906 return methods;
884 } else { 907 } else {
885 CodeExecutableElement method = new CodeExecutableElement(modifiers(PRIVATE, STATIC), genericReturnType, generatedGenericMethodName(null)); 908 CodeExecutableElement method = new CodeExecutableElement(modifiers(PRIVATE, STATIC), genericReturnType, generatedGenericMethodName(null));
886 method.addParameter(new CodeVariableElement(node.getNodeType(), THIS_NODE_LOCAL_VAR_NAME)); 909 method.addParameter(new CodeVariableElement(node.getNodeType(), THIS_NODE_LOCAL_VAR_NAME));
887 addValueParameters(method, node.getGenericSpecialization(), true); 910 addValueParameters(method, node.getGenericSpecialization(), true, true);
888 emitInvokeDoMethod(method.createBuilder(), node.getGenericSpecialization(), 0); 911 emitInvokeDoMethod(method.createBuilder(), node.getGenericSpecialization(), 0);
889 return Arrays.asList(method); 912 return Arrays.asList(method);
890 } 913 }
891 } 914 }
892 915
904 if (next != null) { 927 if (next != null) {
905 builder.end(); 928 builder.end();
906 929
907 builder.startReturn().startCall(generatedGenericMethodName(next)); 930 builder.startReturn().startCall(generatedGenericMethodName(next));
908 builder.string(THIS_NODE_LOCAL_VAR_NAME); 931 builder.string(THIS_NODE_LOCAL_VAR_NAME);
909 addValueParameterNames(builder, next, null, true); 932 addValueParameterNames(builder, next, null, true, true);
910 builder.end().end(); 933 builder.end().end();
911 } 934 }
912 } 935 }
913 936
914 private void emitInvokeDoMethod(CodeTreeBuilder builder, SpecializationData specialization, int level) { 937 private void emitInvokeDoMethod(CodeTreeBuilder builder, SpecializationData specialization, int level) {
915 if (!specialization.getExceptions().isEmpty()) { 938 if (!specialization.getExceptions().isEmpty()) {
916 builder.startTryBlock(); 939 builder.startTryBlock();
917 } 940 }
918 941
919 builder.startReturn(); 942 builder.startReturn();
920 startCallOperationMethod(builder, specialization); 943 startCallOperationMethod(builder, specialization, true);
921 addValueParameterNamesWithCasts(builder, specialization.getNode().getGenericSpecialization(), specialization); 944 addValueParameterNamesWithCasts(builder, specialization.getNode().getGenericSpecialization(), specialization, false);
922 builder.end().end(); // start call operation 945 builder.end().end(); // start call operation
923 builder.end(); // return 946 builder.end(); // return
924 947
925 if (!specialization.getExceptions().isEmpty()) { 948 if (!specialization.getExceptions().isEmpty()) {
926 for (SpecializationThrowsData exception : specialization.getExceptions()) { 949 for (SpecializationThrowsData exception : specialization.getExceptions()) {
927 builder.end().startCatchBlock(exception.getJavaClass(), "ex" + level); 950 builder.end().startCatchBlock(exception.getJavaClass(), "ex" + level);
928 951
929 builder.startReturn().startCall(generatedGenericMethodName(exception.getTransitionTo())); 952 builder.startReturn().startCall(generatedGenericMethodName(exception.getTransitionTo()));
930 builder.string(THIS_NODE_LOCAL_VAR_NAME); 953 builder.string(THIS_NODE_LOCAL_VAR_NAME);
931 addValueParameterNames(builder, exception.getTransitionTo(), null, true); 954 addValueParameterNames(builder, exception.getTransitionTo(), null, true, true);
932 builder.end().end(); 955 builder.end().end();
933 } 956 }
934 builder.end(); 957 builder.end();
935 } 958 }
936 } 959 }
943 } 966 }
944 967
945 @Override 968 @Override
946 public CodeTypeElement create(SpecializationData specialization) { 969 public CodeTypeElement create(SpecializationData specialization) {
947 NodeData node = specialization.getNode(); 970 NodeData node = specialization.getNode();
948 CodeTypeElement clazz = createClass(node, modifiers(PRIVATE, STATIC, FINAL), nodeClassName(specialization), node.getNodeType(), false); 971 CodeTypeElement clazz = createClass(node, modifiers(PRIVATE, STATIC, FINAL), nodeSpecializationClassName(specialization), node.getNodeType(), false);
949 return clazz; 972 return clazz;
950 } 973 }
951 974
952 @Override 975 @Override
953 protected void createChildren(SpecializationData specialization) { 976 protected void createChildren(SpecializationData specialization) {
1108 builder.startCall("replace"); 1131 builder.startCall("replace");
1109 if (node.needsRewrites(getContext())) { 1132 if (node.needsRewrites(getContext())) {
1110 builder.startCall(factoryClassName(node), "specialize"); 1133 builder.startCall(factoryClassName(node), "specialize");
1111 builder.string("this"); 1134 builder.string("this");
1112 builder.typeLiteral(builder.findMethod().getEnclosingElement().asType()); 1135 builder.typeLiteral(builder.findMethod().getEnclosingElement().asType());
1113 addValueParameterNames(builder, specialization, null, false); 1136 addValueParameterNames(builder, specialization, null, false, true);
1114 builder.end(); // call replace, call specialize 1137 builder.end(); // call replace, call specialize
1115 } else { 1138 } else {
1116 builder.startCall(factoryClassName(node), "createSpecialized").string("this").string("null").end(); 1139 builder.startCall(factoryClassName(node), "createSpecialized").string("this").string("null").end();
1117 } 1140 }
1118 builder.end().end(); 1141 builder.end().end();
1127 } 1150 }
1128 1151
1129 if ((specialization.isUninitialized() || specialization.isGeneric()) && node.needsRewrites(getContext())) { 1152 if ((specialization.isUninitialized() || specialization.isGeneric()) && node.needsRewrites(getContext())) {
1130 builder.startReturn().startCall(factoryClassName(node), generatedGenericMethodName(null)); 1153 builder.startReturn().startCall(factoryClassName(node), generatedGenericMethodName(null));
1131 builder.string("this"); 1154 builder.string("this");
1132 addValueParameterNames(builder, specialization, null, true); 1155 addValueParameterNames(builder, specialization, null, true, true);
1133 builder.end().end(); 1156 builder.end().end();
1134 } else { 1157 } else {
1135 builder.startReturn(); 1158 builder.startReturn();
1136 1159
1137 if (specialization.isUninitialized()) { 1160 if (specialization.isUninitialized()) {
1138 startCallOperationMethod(builder, specialization.getNode().getGenericSpecialization()); 1161 startCallOperationMethod(builder, specialization.getNode().getGenericSpecialization(), false);
1139 } else { 1162 } else {
1140 startCallOperationMethod(builder, specialization); 1163 startCallOperationMethod(builder, specialization, false);
1141 } 1164 }
1142 addValueParameterNames(builder, specialization, null, false); 1165 addValueParameterNames(builder, specialization, null, false, false);
1143 builder.end().end(); // operation call 1166 builder.end().end(); // operation call
1144 builder.end(); // return 1167 builder.end(); // return
1145 } 1168 }
1146 1169
1147 if (!specialization.getExceptions().isEmpty()) { 1170 if (!specialization.getExceptions().isEmpty()) {
1154 return builder.getRoot(); 1177 return builder.getRoot();
1155 } 1178 }
1156 1179
1157 private CodeTree createExecuteChildren(CodeTreeBuilder parent, SpecializationData specialization) { 1180 private CodeTree createExecuteChildren(CodeTreeBuilder parent, SpecializationData specialization) {
1158 CodeTreeBuilder builder = new CodeTreeBuilder(parent); 1181 CodeTreeBuilder builder = new CodeTreeBuilder(parent);
1182
1159 for (ActualParameter parameter : specialization.getParameters()) { 1183 for (ActualParameter parameter : specialization.getParameters()) {
1160 NodeFieldData field = specialization.getNode().findField(parameter.getSpecification().getName()); 1184 NodeFieldData field = specialization.getNode().findField(parameter.getSpecification().getName());
1161 if (field == null) { 1185 if (field == null) {
1162 continue; 1186 continue;
1163 } 1187 }
1164 1188
1165 if (parameter.getActualTypeData(specialization.getNode().getTypeSystem()).isGeneric()) { 1189 buildFieldExecute(builder, specialization, parameter, field, null);
1166 buildGenericValueExecute(builder, specialization, parameter, field, null);
1167 } else {
1168 buildSpecializedValueExecute(builder, specialization, parameter, field);
1169 }
1170 } 1190 }
1171 return builder.getRoot(); 1191 return builder.getRoot();
1172 } 1192 }
1173 1193
1174 private void emitSpecializationListeners(CodeTreeBuilder builder, NodeData node) { 1194 private void emitSpecializationListeners(CodeTreeBuilder builder, NodeData node) {
1175 for (TemplateMethod listener : node.getSpecializationListeners()) { 1195 for (TemplateMethod listener : node.getSpecializationListeners()) {
1176 builder.startStatement(); 1196 builder.startStatement();
1177 startCallOperationMethod(builder, listener); 1197 startCallOperationMethod(builder, listener, false);
1178 addValueParameterNames(builder, listener, null, false); 1198 addValueParameterNames(builder, listener, null, false, false);
1179 builder.end().end(); 1199 builder.end().end();
1180 builder.end(); // statement 1200 builder.end(); // statement
1181 } 1201 }
1182 } 1202 }
1183 1203
1184 private void buildGenericValueExecute(CodeTreeBuilder builder, SpecializationData specialization, ActualParameter param, NodeFieldData field, ActualParameter exceptionParam) { 1204 private void buildFieldExecute(CodeTreeBuilder builder, SpecializationData specialization, ActualParameter param, NodeFieldData field, ActualParameter exceptionParam) {
1185 NodeData node = specialization.getNode();
1186 boolean shortCircuit = startShortCircuit(builder, specialization, param, exceptionParam); 1205 boolean shortCircuit = startShortCircuit(builder, specialization, param, exceptionParam);
1187 1206 ExecutableTypeData execType = field.getNodeData().findExecutableType(param.getActualTypeData(field.getNodeData().getTypeSystem()));
1188 builder.startStatement(); 1207 boolean unexpected = execType.hasUnexpectedValue(getContext());
1189 if (!shortCircuit) { 1208
1190 builder.type(specialization.getNode().getTypeSystem().getGenericType()); 1209 if (!shortCircuit && unexpected) {
1191 builder.string(" "); 1210 builder.startStatement().type(param.getActualType()).string(" ").string(valueName(param)).end();
1192 } 1211 }
1193 1212
1194 builder.string(valueName(param)); 1213 if (unexpected) {
1195 builder.string(" = "); 1214 builder.startTryBlock();
1196 ExecutableTypeData genericExecutableType = field.getNodeData().findGenericExecutableType(getContext(), param.getActualTypeData(node.getTypeSystem())); 1215 }
1197 if (genericExecutableType == null) { 1216
1198 throw new AssertionError("Must have generic executable type. Parser validation most likely failed. " + (field.getNodeData().getExecutableTypes())); 1217 if (!shortCircuit && !unexpected) {
1199 } 1218 builder.startStatement().type(param.getActualType()).string(" ").string(valueName(param)).string(" = ");
1200 buildExecute(builder, param, field, genericExecutableType); 1219 } else {
1220 builder.startStatement().string(valueName(param)).string(" = ");
1221 }
1222 buildExecute(builder, param, field, execType);
1201 builder.end(); 1223 builder.end();
1202 1224
1225 if (unexpected) {
1226 builder.end().startCatchBlock(getUnexpectedValueException(), "ex");
1227 SpecializationData generic = specialization.getNode().getGenericSpecialization();
1228 boolean execute = false;
1229 for (ActualParameter exParam : generic.getParameters()) {
1230 NodeFieldData exField = generic.getNode().findField(exParam.getSpecification().getName());
1231 if (exField == null) {
1232 continue;
1233 }
1234 if (execute) {
1235 buildFieldExecute(builder, specialization.getNode().getGenericSpecialization(), exParam, exField, param);
1236 } else if (exParam.getName().equals(param.getName())) {
1237 execute = true;
1238 }
1239 }
1240 builder.tree(createReturnSpecializeAndExecute(builder, specialization.findNextSpecialization(), param));
1241 builder.end(); // catch block
1242 }
1243
1203 endShortCircuit(builder, shortCircuit); 1244 endShortCircuit(builder, shortCircuit);
1245 builder.newLine();
1204 } 1246 }
1205 1247
1206 private void buildExecute(CodeTreeBuilder builder, ActualParameter parameter, NodeFieldData field, ExecutableTypeData execType) { 1248 private void buildExecute(CodeTreeBuilder builder, ActualParameter parameter, NodeFieldData field, ExecutableTypeData execType) {
1207 if (field != null) { 1249 if (field != null) {
1208 Element accessElement = field.getAccessElement(); 1250 Element accessElement = field.getAccessElement();
1217 builder.string("[" + parameter.getIndex() + "]"); 1259 builder.string("[" + parameter.getIndex() + "]");
1218 } 1260 }
1219 builder.string("."); 1261 builder.string(".");
1220 } 1262 }
1221 builder.startCall(execType.getMethodName()); 1263 builder.startCall(execType.getMethodName());
1222 if (execType.getParameters().length == 1) { 1264 if (execType.getParameters().size() == 1) {
1223 builder.string("frameValue"); 1265 builder.string("frameValue");
1224 } 1266 }
1225 builder.end(); 1267 builder.end();
1226 }
1227
1228 private void buildSpecializedValueExecute(CodeTreeBuilder builder, SpecializationData specialization, ActualParameter param, NodeFieldData field) {
1229 boolean shortCircuit = startShortCircuit(builder, specialization, param, null);
1230
1231 if (!shortCircuit) {
1232 builder.startStatement().type(param.getActualType()).string(" ").string(valueName(param)).end();
1233 }
1234
1235 ExecutableTypeData execType = field.getNodeData().findExecutableType(param.getActualTypeData(field.getNodeData().getTypeSystem()));
1236
1237 if (execType.hasUnexpectedValue(getContext())) {
1238 builder.startTryBlock();
1239 }
1240
1241 builder.startStatement().string(valueName(param)).string(" = ");
1242 buildExecute(builder, param, field, execType);
1243 builder.end();
1244
1245 if (execType.hasUnexpectedValue(getContext())) {
1246 builder.end().startCatchBlock(getUnexpectedValueException(), "ex");
1247 SpecializationData generic = specialization.getNode().getGenericSpecialization();
1248 boolean execute = false;
1249 for (ActualParameter exParam : generic.getParameters()) {
1250 NodeFieldData exField = generic.getNode().findField(exParam.getSpecification().getName());
1251 if (exField == null) {
1252 continue;
1253 }
1254 if (execute) {
1255 buildGenericValueExecute(builder, specialization.getNode().getGenericSpecialization(), exParam, exField, param);
1256 } else if (exParam.getName().equals(param.getName())) {
1257 execute = true;
1258 }
1259 }
1260 builder.tree(createReturnSpecializeAndExecute(builder, specialization.findNextSpecialization(), param));
1261 builder.end(); // catch block
1262 }
1263
1264 endShortCircuit(builder, shortCircuit);
1265 builder.newLine();
1266 } 1268 }
1267 1269
1268 private boolean startShortCircuit(CodeTreeBuilder builder, SpecializationData specialization, ActualParameter parameter, ActualParameter exceptionParam) { 1270 private boolean startShortCircuit(CodeTreeBuilder builder, SpecializationData specialization, ActualParameter parameter, ActualParameter exceptionParam) {
1269 NodeFieldData forField = specialization.getNode().findField(parameter.getSpecification().getName()); 1271 NodeFieldData forField = specialization.getNode().findField(parameter.getSpecification().getName());
1270 if (forField == null) { 1272 if (forField == null) {
1288 } 1290 }
1289 1291
1290 builder.startStatement().type(shortCircuitParam.getActualType()).string(" ").string(valueName(shortCircuitParam)).string(" = "); 1292 builder.startStatement().type(shortCircuitParam.getActualType()).string(" ").string(valueName(shortCircuitParam)).string(" = ");
1291 ShortCircuitData shortCircuitData = specialization.getShortCircuits()[shortCircuitIndex]; 1293 ShortCircuitData shortCircuitData = specialization.getShortCircuits()[shortCircuitIndex];
1292 1294
1293 startCallOperationMethod(builder, shortCircuitData); 1295 startCallOperationMethod(builder, shortCircuitData, false);
1294 addValueParameterNames(builder, shortCircuitData, exceptionParam != null ? exceptionParam.getName() : null, false); 1296 addValueParameterNames(builder, shortCircuitData, exceptionParam != null ? exceptionParam.getName() : null, false, false);
1295 builder.end().end(); // call operation 1297 builder.end().end(); // call operation
1296 1298
1297 builder.end(); // statement 1299 builder.end(); // statement
1298 1300
1299 builder.declaration(parameter.getActualType(), valueName(parameter), CodeTreeBuilder.createBuilder().defaultValue(parameter.getActualType())); 1301 builder.declaration(parameter.getActualType(), valueName(parameter), CodeTreeBuilder.createBuilder().defaultValue(parameter.getActualType()));
1310 } 1312 }
1311 1313
1312 private CodeTree createReturnSpecializeAndExecute(CodeTreeBuilder parent, SpecializationData nextSpecialization, ActualParameter exceptionParam) { 1314 private CodeTree createReturnSpecializeAndExecute(CodeTreeBuilder parent, SpecializationData nextSpecialization, ActualParameter exceptionParam) {
1313 CodeTreeBuilder specializeCall = new CodeTreeBuilder(parent); 1315 CodeTreeBuilder specializeCall = new CodeTreeBuilder(parent);
1314 specializeCall.startCall("specializeAndExecute"); 1316 specializeCall.startCall("specializeAndExecute");
1315 specializeCall.string(nodeClassName(nextSpecialization) + ".class"); 1317 specializeCall.string(nodeSpecializationClassName(nextSpecialization) + ".class");
1316 addValueParameterNames(specializeCall, nextSpecialization.getNode().getGenericSpecialization(), exceptionParam != null ? exceptionParam.getName() : null, true); 1318 addValueParameterNames(specializeCall, nextSpecialization.getNode().getGenericSpecialization(), exceptionParam != null ? exceptionParam.getName() : null, true, true);
1317 specializeCall.end().end(); 1319 specializeCall.end().end();
1318 1320
1319 CodeTreeBuilder builder = new CodeTreeBuilder(parent); 1321 CodeTreeBuilder builder = new CodeTreeBuilder(parent);
1320 builder.startReturn(); 1322 builder.startReturn();
1321 builder.tree(specializeCall.getRoot()); 1323 builder.tree(specializeCall.getRoot());
1332 CodeExecutableElement method = new CodeExecutableElement(modifiers(PRIVATE), returnType.getPrimitiveType(), "specializeAndExecute"); 1334 CodeExecutableElement method = new CodeExecutableElement(modifiers(PRIVATE), returnType.getPrimitiveType(), "specializeAndExecute");
1333 method.addParameter(new CodeVariableElement(getContext().getType(Class.class), "minimumState")); 1335 method.addParameter(new CodeVariableElement(getContext().getType(Class.class), "minimumState"));
1334 if (canThrowUnexpected) { 1336 if (canThrowUnexpected) {
1335 method.addThrownType(getUnexpectedValueException()); 1337 method.addThrownType(getUnexpectedValueException());
1336 } 1338 }
1337 addValueParameters(method, specialization.getNode().getGenericSpecialization(), true); 1339 addValueParameters(method, specialization.getNode().getGenericSpecialization(), true, true);
1338 clazz.add(method); 1340 clazz.add(method);
1339 1341
1340 CodeTreeBuilder builder = method.createBuilder(); 1342 CodeTreeBuilder builder = method.createBuilder();
1341 1343
1342 builder.tree(createDeoptimize(builder)); 1344 builder.tree(createDeoptimize(builder));
1343 emitSpecializationListeners(builder, specialization.getNode()); 1345 emitSpecializationListeners(builder, specialization.getNode());
1344 1346
1345 builder.startStatement(); 1347 builder.startStatement();
1346 builder.startCall("replace"); 1348 builder.startCall("replace");
1347 builder.startCall(factoryClassName(specialization.getNode()), "specialize").string("this").string("minimumState"); 1349 builder.startCall(factoryClassName(specialization.getNode()), "specialize").string("this").string("minimumState");
1348 addValueParameterNames(builder, specialization.getNode().getGenericSpecialization(), null, false); 1350 addValueParameterNames(builder, specialization.getNode().getGenericSpecialization(), null, false, true);
1349 builder.end(); 1351 builder.end();
1350 builder.end(); // call replace 1352 builder.end(); // call replace
1351 builder.end(); // statement 1353 builder.end(); // statement
1352 1354
1353 String generatedMethodName = generatedGenericMethodName(specialization.findNextSpecialization()); 1355 String generatedMethodName = generatedGenericMethodName(specialization.findNextSpecialization());
1354 ExecutableElement generatedGeneric = clazz.getEnclosingClass().getMethod(generatedMethodName); 1356 ExecutableElement generatedGeneric = clazz.getEnclosingClass().getMethod(generatedMethodName);
1355 1357
1356 CodeTreeBuilder genericExecute = CodeTreeBuilder.createBuilder(); 1358 CodeTreeBuilder genericExecute = CodeTreeBuilder.createBuilder();
1357 genericExecute.startCall(factoryClassName(specialization.getNode()), generatedMethodName); 1359 genericExecute.startCall(factoryClassName(specialization.getNode()), generatedMethodName);
1358 genericExecute.string("this"); 1360 genericExecute.string("this");
1359 addValueParameterNames(genericExecute, specialization.getNode().getGenericSpecialization(), null, true); 1361 addValueParameterNames(genericExecute, specialization.getNode().getGenericSpecialization(), null, true, true);
1360 genericExecute.end(); // call generated generic 1362 genericExecute.end(); // call generated generic
1361 1363
1362 CodeTree genericInvocation = createExpectType(node, returnExecutableType, genericExecute.getRoot()); 1364 CodeTree genericInvocation = createExpectType(node, returnExecutableType, genericExecute.getRoot());
1363 1365
1364 if (generatedGeneric != null && Utils.isVoid(generatedGeneric.getReturnType())) { 1366 if (generatedGeneric != null && Utils.isVoid(generatedGeneric.getReturnType())) {