| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 library dart2js.ir_builder; | 5 library dart2js.ir_builder; |
| 6 | 6 |
| 7 import 'ir_nodes.dart' as ir; | 7 import 'ir_nodes.dart' as ir; |
| 8 import '../elements/elements.dart'; | 8 import '../elements/elements.dart'; |
| 9 import '../dart2jslib.dart'; | 9 import '../dart2jslib.dart'; |
| 10 import '../dart_types.dart'; | 10 import '../dart_types.dart'; |
| (...skipping 794 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 805 | 805 |
| 806 ir.Primitive visitLiteralSymbol(ast.LiteralSymbol node) { | 806 ir.Primitive visitLiteralSymbol(ast.LiteralSymbol node) { |
| 807 assert(isOpen); | 807 assert(isOpen); |
| 808 ir.Constant constant = new ir.Constant(getConstantForNode(node)); | 808 ir.Constant constant = new ir.Constant(getConstantForNode(node)); |
| 809 add(new ir.LetPrim(constant)); | 809 add(new ir.LetPrim(constant)); |
| 810 return constant; | 810 return constant; |
| 811 } | 811 } |
| 812 | 812 |
| 813 ir.Primitive visitIdentifier(ast.Identifier node) { | 813 ir.Primitive visitIdentifier(ast.Identifier node) { |
| 814 assert(isOpen); | 814 assert(isOpen); |
| 815 // "this" is the only identifier that should be met by the visitor. |
| 815 assert(node.isThis()); | 816 assert(node.isThis()); |
| 816 return lookupThis(); | 817 return lookupThis(); |
| 817 } | 818 } |
| 818 | 819 |
| 819 ir.Primitive visitParenthesizedExpression( | 820 ir.Primitive visitParenthesizedExpression( |
| 820 ast.ParenthesizedExpression node) { | 821 ast.ParenthesizedExpression node) { |
| 821 assert(isOpen); | 822 assert(isOpen); |
| 822 return visit(node.expression); | 823 return visit(node.expression); |
| 823 } | 824 } |
| 824 | 825 |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 887 arguments.add(visit(n)); | 888 arguments.add(visit(n)); |
| 888 } | 889 } |
| 889 ir.Parameter v = new ir.Parameter(null); | 890 ir.Parameter v = new ir.Parameter(null); |
| 890 ir.Continuation k = new ir.Continuation([v]); | 891 ir.Continuation k = new ir.Continuation([v]); |
| 891 ir.Expression invoke = | 892 ir.Expression invoke = |
| 892 new ir.InvokeMethod(closureTarget, namedCallSelector, k, arguments); | 893 new ir.InvokeMethod(closureTarget, namedCallSelector, k, arguments); |
| 893 add(new ir.LetCont(k, invoke)); | 894 add(new ir.LetCont(k, invoke)); |
| 894 return v; | 895 return v; |
| 895 } | 896 } |
| 896 | 897 |
| 898 /// If [node] is null, returns this. |
| 899 /// If [node] is super, returns null (for special handling) |
| 900 /// Otherwise visits [node] and returns the result. |
| 901 ir.Primitive visitReceiver(ast.Expression node) { |
| 902 if (node == null) return lookupThis(); |
| 903 if (node.isSuper()) return null; |
| 904 return visit(node); |
| 905 } |
| 906 |
| 907 /// Makes an [InvokeMethod] unless [node.receiver.isSuper()], in that case |
| 908 /// makes an [InvokeSuperMethod] ignoring [receiver]. |
| 909 ir.Expression createDynamicInvoke(ast.Send node, |
| 910 Selector selector, |
| 911 ir.Definition receiver, |
| 912 ir.Continuation k, |
| 913 List<ir.Definition> arguments) { |
| 914 return node.receiver != null && node.receiver.isSuper() |
| 915 ? new ir.InvokeSuperMethod(selector, k, arguments) |
| 916 : new ir.InvokeMethod(receiver, selector, k, arguments); |
| 917 } |
| 918 |
| 897 ir.Primitive visitDynamicSend(ast.Send node) { | 919 ir.Primitive visitDynamicSend(ast.Send node) { |
| 898 assert(isOpen); | 920 assert(isOpen); |
| 899 if (node.receiver == null || node.receiver.isSuper()) { | |
| 900 return giveup(node, 'DynamicSend without receiver, or super receiver'); | |
| 901 } | |
| 902 Selector selector = elements.getSelector(node); | 921 Selector selector = elements.getSelector(node); |
| 903 ir.Primitive receiver = visit(node.receiver); | 922 ir.Primitive receiver = visitReceiver(node.receiver); |
| 904 List<ir.Primitive> arguments = new List<ir.Primitive>(); | 923 List<ir.Primitive> arguments = new List<ir.Primitive>(); |
| 905 for (ast.Node n in node.arguments) { | 924 for (ast.Node n in node.arguments) { |
| 906 arguments.add(visit(n)); | 925 arguments.add(visit(n)); |
| 907 } | 926 } |
| 908 ir.Parameter v = new ir.Parameter(null); | 927 ir.Parameter v = new ir.Parameter(null); |
| 909 ir.Continuation k = new ir.Continuation([v]); | 928 ir.Continuation k = new ir.Continuation([v]); |
| 910 ir.Expression invoke = | 929 ir.Expression invoke = |
| 911 new ir.InvokeMethod(receiver, selector, k, arguments); | 930 createDynamicInvoke(node, selector, receiver, k, arguments); |
| 912 add(new ir.LetCont(k, invoke)); | 931 add(new ir.LetCont(k, invoke)); |
| 913 return v; | 932 return v; |
| 914 } | 933 } |
| 915 | 934 |
| 916 ir.Primitive visitGetterSend(ast.Send node) { | 935 ir.Primitive visitGetterSend(ast.Send node) { |
| 917 assert(isOpen); | 936 assert(isOpen); |
| 918 Element element = elements[node]; | 937 Element element = elements[node]; |
| 919 if (Elements.isLocal(element)) { | 938 if (Elements.isLocal(element)) { |
| 920 return lookupLocal(element); | 939 return lookupLocal(element); |
| 921 } else if (element == null || Elements.isInstanceField(element)) { | 940 } else if (element == null || Elements.isInstanceField(element)) { |
| 922 ir.Primitive receiver = node.receiver == null | 941 ir.Primitive receiver = visitReceiver(node.receiver); |
| 923 ? lookupThis() | |
| 924 : visit(node.receiver); | |
| 925 ir.Parameter v = new ir.Parameter(null); | 942 ir.Parameter v = new ir.Parameter(null); |
| 926 ir.Continuation k = new ir.Continuation([v]); | 943 ir.Continuation k = new ir.Continuation([v]); |
| 927 Selector selector = elements.getSelector(node); | 944 Selector selector = elements.getSelector(node); |
| 928 assert(selector.kind == SelectorKind.GETTER); | 945 assert(selector.kind == SelectorKind.GETTER); |
| 929 ir.InvokeMethod invoke = new ir.InvokeMethod(receiver, selector, k, []); | 946 ir.Expression invoke = |
| 947 createDynamicInvoke(node, selector, receiver, k, []); |
| 930 add(new ir.LetCont(k, invoke)); | 948 add(new ir.LetCont(k, invoke)); |
| 931 return v; | 949 return v; |
| 932 } else if (element.isField) { | 950 } else if (element.isField) { |
| 933 ir.Parameter v = new ir.Parameter(null); | 951 ir.Parameter v = new ir.Parameter(null); |
| 934 ir.Continuation k = new ir.Continuation([v]); | 952 ir.Continuation k = new ir.Continuation([v]); |
| 935 Selector selector = elements.getSelector(node); | 953 Selector selector = elements.getSelector(node); |
| 936 assert(selector.kind == SelectorKind.GETTER); | 954 assert(selector.kind == SelectorKind.GETTER); |
| 937 ir.InvokeStatic invoke = new ir.InvokeStatic(element, selector, k, []); | 955 ir.InvokeStatic invoke = new ir.InvokeStatic(element, selector, k, []); |
| 938 add(new ir.LetCont(k, invoke)); | 956 add(new ir.LetCont(k, invoke)); |
| 939 return v; | 957 return v; |
| (...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1115 ir.Parameter v = new ir.Parameter(null); | 1133 ir.Parameter v = new ir.Parameter(null); |
| 1116 ir.Continuation k = new ir.Continuation([v]); | 1134 ir.Continuation k = new ir.Continuation([v]); |
| 1117 ir.Expression invoke = | 1135 ir.Expression invoke = |
| 1118 new ir.InvokeStatic(element, selector, k, arguments); | 1136 new ir.InvokeStatic(element, selector, k, arguments); |
| 1119 add(new ir.LetCont(k, invoke)); | 1137 add(new ir.LetCont(k, invoke)); |
| 1120 return v; | 1138 return v; |
| 1121 } | 1139 } |
| 1122 | 1140 |
| 1123 ir.Primitive visitSuperSend(ast.Send node) { | 1141 ir.Primitive visitSuperSend(ast.Send node) { |
| 1124 assert(isOpen); | 1142 assert(isOpen); |
| 1125 return giveup(node, 'SuperSend'); | 1143 if (node.isPropertyAccess) { |
| 1144 return visitGetterSend(node); |
| 1145 } else { |
| 1146 return visitDynamicSend(node); |
| 1147 } |
| 1126 } | 1148 } |
| 1127 | 1149 |
| 1128 ir.Primitive visitTypeReferenceSend(ast.Send node) { | 1150 ir.Primitive visitTypeReferenceSend(ast.Send node) { |
| 1129 assert(isOpen); | 1151 assert(isOpen); |
| 1130 if (node.argumentsNode != null) { | 1152 if (node.argumentsNode != null) { |
| 1131 // May happen in strange, invalid code. | 1153 // May happen in strange, invalid code. |
| 1132 // TODO(asgerf): Generate code that throws a runtime error. | 1154 // TODO(asgerf): Generate code that throws a runtime error. |
| 1133 return giveup(node, 'TypeReferenceSend: has argument'); | 1155 return giveup(node, 'TypeReferenceSend: has argument'); |
| 1134 } | 1156 } |
| 1135 Element element = elements[node]; | 1157 Element element = elements[node]; |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1167 assert(element.isField || element.isSetter); | 1189 assert(element.isField || element.isSetter); |
| 1168 assert(!node.arguments.isEmpty && node.arguments.tail.isEmpty); | 1190 assert(!node.arguments.isEmpty && node.arguments.tail.isEmpty); |
| 1169 ir.Parameter v = new ir.Parameter(null); | 1191 ir.Parameter v = new ir.Parameter(null); |
| 1170 ir.Continuation k = new ir.Continuation([v]); | 1192 ir.Continuation k = new ir.Continuation([v]); |
| 1171 Selector selector = elements.getSelector(node); | 1193 Selector selector = elements.getSelector(node); |
| 1172 ir.Definition arg = visit(node.arguments.head); | 1194 ir.Definition arg = visit(node.arguments.head); |
| 1173 ir.InvokeStatic invoke = | 1195 ir.InvokeStatic invoke = |
| 1174 new ir.InvokeStatic(element, selector, k, [arg]); | 1196 new ir.InvokeStatic(element, selector, k, [arg]); |
| 1175 add(new ir.LetCont(k, invoke)); | 1197 add(new ir.LetCont(k, invoke)); |
| 1176 return arg; | 1198 return arg; |
| 1177 } else if (node.receiver == null) { | |
| 1178 // Nodes that fall in this case: | |
| 1179 // - Unresolved top-level | |
| 1180 // - Assignment to final variable (will not be resolved) | |
| 1181 return giveup(node, 'SendSet: non-local, non-static, but no receiver'); | |
| 1182 } else { | 1199 } else { |
| 1183 if (element != null && Elements.isUnresolved(element)) { | 1200 if (element != null && Elements.isUnresolved(element)) { |
| 1184 return giveup(node); | 1201 return giveup(node, 'SendSet: non-local, non-static, unresolved'); |
| 1185 } | 1202 } |
| 1186 | 1203 |
| 1187 // Setter or index-setter invocation | 1204 // Setter or index-setter invocation |
| 1188 assert(node.receiver != null); | |
| 1189 | 1205 |
| 1190 if (node.receiver.isSuper()) return giveup(node, 'Super SendSet'); | 1206 ir.Primitive receiver = visitReceiver(node.receiver); |
| 1191 | |
| 1192 ir.Primitive receiver = node.receiver == null | |
| 1193 ? lookupThis() | |
| 1194 : visit(node.receiver); | |
| 1195 ir.Parameter v = new ir.Parameter(null); | 1207 ir.Parameter v = new ir.Parameter(null); |
| 1196 ir.Continuation k = new ir.Continuation([v]); | 1208 ir.Continuation k = new ir.Continuation([v]); |
| 1197 Selector selector = elements.getSelector(node); | 1209 Selector selector = elements.getSelector(node); |
| 1198 assert(selector.kind == SelectorKind.SETTER || | 1210 assert(selector.kind == SelectorKind.SETTER || |
| 1199 selector.kind == SelectorKind.INDEX); | 1211 selector.kind == SelectorKind.INDEX); |
| 1200 List<ir.Definition> args = node.arguments.mapToList(visit, | 1212 List<ir.Definition> arguments = node.arguments.mapToList(visit, |
| 1201 growable:false); | 1213 growable:false); |
| 1202 ir.InvokeMethod invoke = | 1214 ir.Expression invoke = |
| 1203 new ir.InvokeMethod(receiver, selector, k, args); | 1215 createDynamicInvoke(node, selector, receiver, k, arguments); |
| 1204 add(new ir.LetCont(k, invoke)); | 1216 add(new ir.LetCont(k, invoke)); |
| 1205 return args.last; | 1217 return arguments.last; |
| 1206 } | 1218 } |
| 1207 } else if (ast.Operator.COMPLEX_OPERATORS.contains(op.source)) { | 1219 } else if (ast.Operator.COMPLEX_OPERATORS.contains(op.source)) { |
| 1208 Element selectorElement = elements[node.selector]; | 1220 Element selectorElement = elements[node.selector]; |
| 1209 if (selectorElement != null && !selectorElement.isAssignable) { | 1221 if (selectorElement != null && !selectorElement.isAssignable) { |
| 1210 return giveup(node, 'Unresolved or non-assignable compound assignment'); | 1222 return giveup(node, 'Unresolved or non-assignable compound assignment'); |
| 1211 } | 1223 } |
| 1212 if (!Elements.isLocal(selectorElement)) { | 1224 if (!Elements.isLocal(selectorElement)) { |
| 1213 return giveup(node, 'Non-local compound assignment'); | 1225 return giveup(node, 'Non-local compound assignment'); |
| 1214 } | 1226 } |
| 1215 | 1227 |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1301 | 1313 |
| 1302 static final String ABORT_IRNODE_BUILDER = "IrNode builder aborted"; | 1314 static final String ABORT_IRNODE_BUILDER = "IrNode builder aborted"; |
| 1303 | 1315 |
| 1304 ir.Primitive giveup(ast.Node node, [String reason]) { | 1316 ir.Primitive giveup(ast.Node node, [String reason]) { |
| 1305 throw ABORT_IRNODE_BUILDER; | 1317 throw ABORT_IRNODE_BUILDER; |
| 1306 } | 1318 } |
| 1307 | 1319 |
| 1308 ir.FunctionDefinition nullIfGiveup(ir.FunctionDefinition action()) { | 1320 ir.FunctionDefinition nullIfGiveup(ir.FunctionDefinition action()) { |
| 1309 try { | 1321 try { |
| 1310 return action(); | 1322 return action(); |
| 1311 } catch(e) { | 1323 } catch(e, tr) { |
| 1312 if (e == ABORT_IRNODE_BUILDER) return null; | 1324 if (e == ABORT_IRNODE_BUILDER) { |
| 1325 return null; |
| 1326 } |
| 1313 rethrow; | 1327 rethrow; |
| 1314 } | 1328 } |
| 1315 } | 1329 } |
| 1316 | 1330 |
| 1317 void internalError(String reason, {ast.Node node}) { | 1331 void internalError(String reason, {ast.Node node}) { |
| 1318 giveup(node); | 1332 giveup(node); |
| 1319 } | 1333 } |
| 1320 } | 1334 } |
| 1321 | 1335 |
| OLD | NEW |