Chromium Code Reviews| 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 809 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 820 return result; | 820 return result; |
| 821 } | 821 } |
| 822 | 822 |
| 823 ir.Primitive visitLiteralSymbol(ast.LiteralSymbol node) { | 823 ir.Primitive visitLiteralSymbol(ast.LiteralSymbol node) { |
| 824 assert(isOpen); | 824 assert(isOpen); |
| 825 return translateConstant(node); | 825 return translateConstant(node); |
| 826 } | 826 } |
| 827 | 827 |
| 828 ir.Primitive visitIdentifier(ast.Identifier node) { | 828 ir.Primitive visitIdentifier(ast.Identifier node) { |
| 829 assert(isOpen); | 829 assert(isOpen); |
| 830 // "this" is the only identifier that should be met by the visitor. | |
| 830 assert(node.isThis()); | 831 assert(node.isThis()); |
| 831 return lookupThis(); | 832 return lookupThis(); |
| 832 } | 833 } |
| 833 | 834 |
| 834 ir.Primitive visitParenthesizedExpression( | 835 ir.Primitive visitParenthesizedExpression( |
| 835 ast.ParenthesizedExpression node) { | 836 ast.ParenthesizedExpression node) { |
| 836 assert(isOpen); | 837 assert(isOpen); |
| 837 return visit(node.expression); | 838 return visit(node.expression); |
| 838 } | 839 } |
| 839 | 840 |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 906 closureTarget = visit(node.selector); | 907 closureTarget = visit(node.selector); |
| 907 } else { | 908 } else { |
| 908 assert(Elements.isLocal(element)); | 909 assert(Elements.isLocal(element)); |
| 909 closureTarget = lookupLocal(element); | 910 closureTarget = lookupLocal(element); |
| 910 } | 911 } |
| 911 Selector closureSelector = elements.getSelector(node); | 912 Selector closureSelector = elements.getSelector(node); |
| 912 return translateClosureCall(closureTarget, closureSelector, | 913 return translateClosureCall(closureTarget, closureSelector, |
| 913 node.argumentsNode); | 914 node.argumentsNode); |
| 914 } | 915 } |
| 915 | 916 |
| 917 /// If [node] is null, returns this. | |
| 918 /// If [node] is super, returns null (for special handling) | |
| 919 /// Otherwise visits [node] and returns the result. | |
| 920 ir.Primitive visitReceiver(ast.Expression node) { | |
| 921 if (node == null) return lookupThis(); | |
| 922 if (node.isSuper()) return null; | |
| 923 return visit(node); | |
| 924 } | |
| 925 | |
| 926 /// Makes an [InvokeMethod] unless [node.receiver.isSuper()], in that case | |
| 927 /// makes an [InvokeSuperMethod] ignoring [receiver]. | |
| 928 ir.Expression createDynamicInvoke(ast.Send node, | |
| 929 Selector selector, | |
| 930 ir.Definition receiver, | |
| 931 ir.Continuation k, | |
| 932 List<ir.Definition> arguments) { | |
| 933 return node.receiver != null && node.receiver.isSuper() | |
| 934 ? new ir.InvokeSuperMethod(selector, k, arguments) | |
| 935 : new ir.InvokeMethod(receiver, selector, k, arguments); | |
| 936 } | |
| 937 | |
| 916 ir.Primitive visitDynamicSend(ast.Send node) { | 938 ir.Primitive visitDynamicSend(ast.Send node) { |
| 917 assert(isOpen); | 939 assert(isOpen); |
| 918 if (node.receiver == null || node.receiver.isSuper()) { | |
| 919 return giveup(node, 'DynamicSend without receiver, or super receiver'); | |
| 920 } | |
| 921 Selector selector = elements.getSelector(node); | 940 Selector selector = elements.getSelector(node); |
| 922 ir.Primitive receiver = visit(node.receiver); | 941 ir.Primitive receiver = visitReceiver(node.receiver); |
| 923 List<ir.Primitive> arguments = new List<ir.Primitive>(); | 942 List<ir.Primitive> arguments = new List<ir.Primitive>(); |
| 924 for (ast.Node n in node.arguments) { | 943 for (ast.Node n in node.arguments) { |
| 925 arguments.add(visit(n)); | 944 arguments.add(visit(n)); |
| 926 } | 945 } |
| 927 ir.Parameter v = new ir.Parameter(null); | 946 ir.Parameter v = new ir.Parameter(null); |
| 928 ir.Continuation k = new ir.Continuation([v]); | 947 ir.Continuation k = new ir.Continuation([v]); |
| 929 ir.Expression invoke = | 948 ir.Expression invoke = |
| 930 new ir.InvokeMethod(receiver, selector, k, arguments); | 949 createDynamicInvoke(node, selector, receiver, k, arguments); |
| 931 add(new ir.LetCont(k, invoke)); | 950 add(new ir.LetCont(k, invoke)); |
| 932 return v; | 951 return v; |
| 933 } | 952 } |
| 934 | 953 |
| 935 ir.Primitive visitGetterSend(ast.Send node) { | 954 ir.Primitive visitGetterSend(ast.Send node) { |
| 955 // This code should be kept in sync with the getter part of visitSendSet | |
| 936 assert(isOpen); | 956 assert(isOpen); |
| 937 Element element = elements[node]; | 957 Element element = elements[node]; |
| 958 Selector selector = elements.getSelector(node); | |
| 938 | 959 |
| 939 // TODO(asgerf): Generate code for erroneous getter access | 960 // TODO(asgerf): Generate code for erroneous getter access |
| 940 if (Elements.isErroneousElement(element)) { | 961 if (Elements.isErroneousElement(element)) { |
| 941 return giveup(node, 'Erroneous element on GetterSend'); | 962 return giveup(node, 'Erroneous element on GetterSend'); |
| 942 } | 963 } |
| 943 | 964 |
| 944 // Reference to constant local, top-level or static field | 965 // Reference to constant local, top-level or static field |
| 945 if (element != null && element.isConst) { | 966 if (element != null && element.isConst) { |
| 946 return translateConstant(node); | 967 return translateConstant(node); |
| 947 } | 968 } |
| 948 | 969 |
| 949 // Reference to local variable | 970 // Reference to local variable |
| 950 if (Elements.isLocal(element)) { | 971 if (Elements.isLocal(element)) { |
| 951 return lookupLocal(element); | 972 return lookupLocal(element); |
| 952 } | 973 } |
| 953 | 974 |
| 954 // Dynamic dispatch to a getter. Sometimes resolution will suggest a target | 975 // Dynamic dispatch to a getter. Sometimes resolution will suggest a target |
| 955 // element, but in these cases we must still emit a dynamic dispatch. | 976 // element, but in these cases we must still emit a dynamic dispatch. |
| 956 // The target element may be an instance method in case we are converting | 977 // The target element may be an instance method in case we are converting |
| 957 // a method to a function object. | 978 // a method to a function object. |
| 958 if (element == null || | 979 if (element == null || |
| 959 Elements.isInstanceField(element) || | 980 Elements.isInstanceField(element) || |
| 960 Elements.isInstanceMethod(element)) { | 981 Elements.isInstanceMethod(element)) { |
| 961 ir.Primitive receiver = node.receiver == null | 982 ir.Primitive receiver = visitReceiver(node.receiver); |
| 962 ? lookupThis() | |
| 963 : visit(node.receiver); | |
| 964 ir.Parameter v = new ir.Parameter(null); | 983 ir.Parameter v = new ir.Parameter(null); |
| 965 ir.Continuation k = new ir.Continuation([v]); | 984 ir.Continuation k = new ir.Continuation([v]); |
| 966 Selector selector = elements.getSelector(node); | |
| 967 assert(selector.kind == SelectorKind.GETTER); | 985 assert(selector.kind == SelectorKind.GETTER); |
| 968 ir.InvokeMethod invoke = new ir.InvokeMethod(receiver, selector, k, []); | 986 ir.Expression invoke = |
| 987 createDynamicInvoke(node, selector, receiver, k, []); | |
| 969 add(new ir.LetCont(k, invoke)); | 988 add(new ir.LetCont(k, invoke)); |
| 970 return v; | 989 return v; |
| 971 } | 990 } |
| 972 | 991 |
| 973 // Access to a static field or getter (non-static case handled above). | 992 // Access to a static field or getter (non-static case handled above). |
| 974 if (element.isField || element.isGetter) { | 993 if (element.isField || element.isGetter) { |
| 975 ir.Parameter v = new ir.Parameter(null); | 994 ir.Parameter v = new ir.Parameter(null); |
| 976 ir.Continuation k = new ir.Continuation([v]); | 995 ir.Continuation k = new ir.Continuation([v]); |
| 977 Selector selector = elements.getSelector(node); | 996 ir.Expression invoke = |
| 978 assert(selector.kind == SelectorKind.GETTER); | 997 new ir.InvokeStatic(element, selector, k, []); |
| 979 ir.InvokeStatic invoke = new ir.InvokeStatic(element, selector, k, []); | |
| 980 add(new ir.LetCont(k, invoke)); | 998 add(new ir.LetCont(k, invoke)); |
| 981 return v; | 999 return v; |
| 982 } | 1000 } |
| 983 | 1001 |
| 984 // Convert a top-level or static function to a function object. | 1002 // Convert a top-level or static function to a function object. |
| 985 if (Elements.isStaticOrTopLevelFunction(element)) { | 1003 if (Elements.isStaticOrTopLevelFunction(element)) { |
| 986 return translateConstant(node); | 1004 return translateConstant(node); |
| 987 } | 1005 } |
| 988 | 1006 |
| 989 throw "Unexpected GetterSend: $node, $element"; | 1007 throw "Unexpected GetterSend: $node, $element"; |
| (...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1174 ir.Parameter v = new ir.Parameter(null); | 1192 ir.Parameter v = new ir.Parameter(null); |
| 1175 ir.Continuation k = new ir.Continuation([v]); | 1193 ir.Continuation k = new ir.Continuation([v]); |
| 1176 ir.Expression invoke = | 1194 ir.Expression invoke = |
| 1177 new ir.InvokeStatic(element, selector, k, arguments); | 1195 new ir.InvokeStatic(element, selector, k, arguments); |
| 1178 add(new ir.LetCont(k, invoke)); | 1196 add(new ir.LetCont(k, invoke)); |
| 1179 return v; | 1197 return v; |
| 1180 } | 1198 } |
| 1181 | 1199 |
| 1182 ir.Primitive visitSuperSend(ast.Send node) { | 1200 ir.Primitive visitSuperSend(ast.Send node) { |
| 1183 assert(isOpen); | 1201 assert(isOpen); |
| 1184 return giveup(node, 'SuperSend'); | 1202 if (node.isPropertyAccess) { |
| 1203 return visitGetterSend(node); | |
| 1204 } else { | |
| 1205 return visitDynamicSend(node); | |
| 1206 } | |
| 1185 } | 1207 } |
| 1186 | 1208 |
| 1187 ir.Primitive visitTypeReferenceSend(ast.Send node) { | 1209 ir.Primitive visitTypeReferenceSend(ast.Send node) { |
| 1188 assert(isOpen); | 1210 assert(isOpen); |
| 1189 Element element = elements[node]; | 1211 Element element = elements[node]; |
| 1190 assert(element is TypeDeclarationElement || element.isTypeVariable); | 1212 assert(element is TypeDeclarationElement || element.isTypeVariable); |
| 1191 | 1213 |
| 1192 // If the user is trying to invoke the type literal or variable, | 1214 // If the user is trying to invoke the type literal or variable, |
| 1193 // it must be treated as a function call. | 1215 // it must be treated as a function call. |
| 1194 if (node.argumentsNode != null) { | 1216 if (node.argumentsNode != null) { |
| 1195 return visitDynamicSend(node); | 1217 return visitDynamicSend(node); |
| 1196 } | 1218 } |
| 1197 | 1219 |
| 1198 if (element is TypeDeclarationElement) { | 1220 if (element is TypeDeclarationElement) { |
| 1199 return translateConstant(node); | 1221 return translateConstant(node); |
| 1200 } else { | 1222 } else { |
| 1201 ir.Primitive prim = new ir.ReifyTypeVar(element); | 1223 ir.Primitive prim = new ir.ReifyTypeVar(element); |
| 1202 add(new ir.LetPrim(prim)); | 1224 add(new ir.LetPrim(prim)); |
| 1203 return prim; | 1225 return prim; |
| 1204 } | 1226 } |
| 1205 } | 1227 } |
| 1206 | 1228 |
| 1207 ir.Primitive visitSendSet(ast.SendSet node) { | 1229 ir.Primitive visitSendSet(ast.SendSet node) { |
| 1208 assert(isOpen); | 1230 assert(isOpen); |
| 1209 Element element = elements[node]; | 1231 Element element = elements[node]; |
| 1210 ast.Operator op = node.assignmentOperator; | 1232 ast.Operator op = node.assignmentOperator; |
| 1211 ir.Primitive result; | 1233 // For complex operators, this is the result of getting (before assigning) |
| 1212 ir.Primitive getter; | 1234 ir.Primitive originalValue; |
| 1213 if (op.source == '=') { | 1235 // For []+= style operators, this saves the index. |
| 1214 if (Elements.isLocal(element)) { | 1236 ir.Primitive index; |
| 1215 // Exactly one argument expected for a simple assignment. | 1237 ir.Primitive receiver; |
| 1216 assert(!node.arguments.isEmpty); | 1238 // This is what gets assigned. |
| 1217 assert(node.arguments.tail.isEmpty); | 1239 ir.Primitive valueToStore; |
| 1218 result = visit(node.arguments.head); | 1240 Selector selector = elements.getSelector(node); |
| 1219 result.useElementAsHint(element); | 1241 Selector operatorSelector = |
| 1220 assignedVars[variableIndex[element]] = result; | 1242 elements.getOperatorSelectorInComplexSendSet(node); |
| 1221 return result; | 1243 Selector getterSelector = |
| 1222 } else if (Elements.isStaticOrTopLevel(element)) { | 1244 elements.getGetterSelectorInComplexSendSet(node); |
| 1223 assert(element.isField || element.isSetter); | 1245 assert( |
| 1224 assert(!node.arguments.isEmpty && node.arguments.tail.isEmpty); | 1246 // Indexing send-sets have an argument for the index. |
| 1225 ir.Parameter v = new ir.Parameter(null); | 1247 (selector.isIndexSet ? 1 : 0) + |
| 1226 ir.Continuation k = new ir.Continuation([v]); | 1248 // Non-increment send-sets have one more argument. |
| 1227 Selector selector = elements.getSelector(node); | 1249 (ast.Operator.INCREMENT_OPERATORS.contains(op.source) ? 0 : 1) |
| 1228 ir.Definition arg = visit(node.arguments.head); | 1250 == node.argumentCount()); |
| 1229 ir.InvokeStatic invoke = | 1251 |
| 1230 new ir.InvokeStatic(element, selector, k, [arg]); | 1252 ast.Node assignArg = selector.isIndexSet |
| 1231 add(new ir.LetCont(k, invoke)); | 1253 ? node.arguments.tail.head |
| 1232 return arg; | 1254 : node.arguments.head; |
| 1233 } else if (node.receiver == null) { | 1255 |
| 1234 // Nodes that fall in this case: | 1256 // Get the value into valueToStore |
| 1235 // - Unresolved top-level | 1257 if (op.source == "=") { |
| 1236 // - Assignment to final variable (will not be resolved) | 1258 if (selector.isIndexSet) { |
| 1237 return giveup(node, 'SendSet: non-local, non-static, but no receiver'); | 1259 receiver = visitReceiver(node.receiver); |
| 1238 } else { | 1260 index = visit(node.arguments.head); |
| 1239 if (element != null && Elements.isUnresolved(element)) { | 1261 } else if (element == null || Elements.isInstanceField(element)) { |
| 1240 return giveup(node); | 1262 receiver = visitReceiver(node.receiver); |
| 1263 } | |
| 1264 valueToStore = visit(assignArg); | |
| 1265 } else { | |
| 1266 // Get the original value into getter | |
| 1267 assert(ast.Operator.COMPLEX_OPERATORS.contains(op.source)); | |
| 1268 | |
| 1269 // This code should be kept in sync with visitGetterSend | |
| 1270 // We have to handle index-set specially, to ensure the index only is | |
| 1271 // computed once - therefore the duplication. | |
| 1272 ir.Primitive getter() { | |
|
asgerf
2014/06/27 08:09:56
As discussed offline, we should look for a way to
sigurdm
2014/06/27 09:20:21
Done.
| |
| 1273 if (Elements.isErroneousElement(element)) { | |
| 1274 return giveup(node, 'Erroneous element on GetterSend'); | |
| 1241 } | 1275 } |
| 1242 | 1276 |
| 1243 // Setter or index-setter invocation | 1277 // Reference to constant local, top-level or static field |
| 1244 assert(node.receiver != null); | 1278 if (element != null && element.isConst) { |
| 1279 return translateConstant(node); | |
| 1280 } | |
| 1245 | 1281 |
| 1246 if (node.receiver.isSuper()) return giveup(node, 'Super SendSet'); | 1282 // Reference to local variable |
| 1283 if (Elements.isLocal(element)) { | |
| 1284 return lookupLocal(element); | |
| 1285 } | |
| 1247 | 1286 |
| 1248 ir.Primitive receiver = node.receiver == null | 1287 // Dynamic dispatch to a getter. Sometimes resolution will suggest a |
| 1249 ? lookupThis() | 1288 // target element, but in these cases we must still emit a dynamic |
| 1250 : visit(node.receiver); | 1289 // dispatch. The target element may be an instance method in case we are |
| 1251 ir.Parameter v = new ir.Parameter(null); | 1290 // converting a method to a function object. |
| 1252 ir.Continuation k = new ir.Continuation([v]); | 1291 if (element == null || |
| 1253 Selector selector = elements.getSelector(node); | 1292 Elements.isInstanceField(element) || |
| 1254 assert(selector.kind == SelectorKind.SETTER || | 1293 Elements.isInstanceMethod(element) || |
| 1255 selector.kind == SelectorKind.INDEX); | 1294 getterSelector.isIndex || |
| 1256 List<ir.Definition> args = node.arguments.mapToList(visit, | 1295 node.isSuperCall) { |
| 1257 growable:false); | 1296 |
| 1258 ir.InvokeMethod invoke = | 1297 receiver = visitReceiver(node.receiver); |
| 1259 new ir.InvokeMethod(receiver, selector, k, args); | 1298 List<ir.Primitive> arguments = new List<ir.Primitive>(); |
| 1260 add(new ir.LetCont(k, invoke)); | 1299 if (getterSelector.isIndex) { |
| 1261 return args.last; | 1300 index = visit(node.arguments.head); |
| 1262 } | 1301 arguments.add(index); |
| 1263 } else if (ast.Operator.COMPLEX_OPERATORS.contains(op.source)) { | 1302 } |
| 1264 Element selectorElement = elements[node.selector]; | 1303 |
| 1265 if (selectorElement != null && !selectorElement.isAssignable) { | 1304 ir.Parameter v = new ir.Parameter(null); |
| 1266 return giveup(node, 'Unresolved or non-assignable compound assignment'); | 1305 ir.Continuation k = new ir.Continuation([v]); |
| 1267 } | 1306 assert(getterSelector.kind == SelectorKind.GETTER || |
| 1268 if (!Elements.isLocal(selectorElement)) { | 1307 getterSelector.kind == SelectorKind.INDEX); |
| 1269 return giveup(node, 'Non-local compound assignment'); | 1308 ir.Expression invoke = |
| 1309 createDynamicInvoke(node, getterSelector, receiver, k, arguments); | |
| 1310 add(new ir.LetCont(k, invoke)); | |
| 1311 return v; | |
| 1312 } | |
| 1313 | |
| 1314 // Access to a static field or getter (non-static case handled above). | |
| 1315 if (element.isField || element.isGetter || | |
| 1316 // Even if there is only a setter, we compile as if it was a getter, | |
| 1317 // so the vm can fail at runtime. | |
| 1318 element.isSetter) { | |
| 1319 ir.Parameter v = new ir.Parameter(null); | |
| 1320 ir.Continuation k = new ir.Continuation([v]); | |
| 1321 assert(getterSelector.kind == SelectorKind.GETTER); | |
| 1322 ir.Expression invoke = | |
| 1323 new ir.InvokeStatic(element, getterSelector, k, []); | |
| 1324 add(new ir.LetCont(k, invoke)); | |
| 1325 return v; | |
| 1326 } | |
| 1327 | |
| 1328 // Convert a top-level or static function to a function object. | |
| 1329 if (Elements.isStaticOrTopLevelFunction(element)) { | |
| 1330 return translateConstant(node); | |
| 1331 } | |
| 1332 | |
| 1333 throw "Unexpected SendSet getter: $node, $element"; | |
| 1270 } | 1334 } |
| 1271 | 1335 |
| 1272 Selector selector = elements.getOperatorSelectorInComplexSendSet(node); | 1336 originalValue = getter(); |
| 1273 getter = lookupLocal(selectorElement); | |
| 1274 | 1337 |
| 1338 // Do the modification of the value in getter. | |
| 1275 ir.Primitive arg; | 1339 ir.Primitive arg; |
| 1276 if (ast.Operator.INCREMENT_OPERATORS.contains(op.source)) { | 1340 if (ast.Operator.INCREMENT_OPERATORS.contains(op.source)) { |
| 1277 assert(node.arguments.isEmpty); | |
| 1278 arg = makePrimConst(constantSystem.createInt(1)); | 1341 arg = makePrimConst(constantSystem.createInt(1)); |
| 1279 add(new ir.LetPrim(arg)); | 1342 add(new ir.LetPrim(arg)); |
| 1280 } else { | 1343 } else { |
| 1281 assert(!node.arguments.isEmpty); | 1344 arg = visit(assignArg); |
| 1282 assert(node.arguments.tail.isEmpty); | |
| 1283 arg = visit(node.arguments.head); | |
| 1284 } | 1345 } |
| 1285 arg.useElementAsHint(element); | 1346 valueToStore = new ir.Parameter(null); |
| 1286 result = new ir.Parameter(null); | 1347 ir.Continuation k = new ir.Continuation([valueToStore]); |
| 1287 ir.Continuation k = new ir.Continuation([result]); | 1348 ir.Expression invoke = |
| 1288 ir.Expression invoke = new ir.InvokeMethod(getter, selector, k, [arg]); | 1349 new ir.InvokeMethod(originalValue, operatorSelector, k, [arg]); |
| 1289 add(new ir.LetCont(k, invoke)); | 1350 add(new ir.LetCont(k, invoke)); |
| 1351 } | |
| 1290 | 1352 |
| 1291 assignedVars[variableIndex[element]] = result; | 1353 // Set the value |
| 1354 if (Elements.isLocal(element)) { | |
| 1355 valueToStore.useElementAsHint(element); | |
| 1356 assignedVars[variableIndex[element]] = valueToStore; | |
| 1357 } else if (Elements.isStaticOrTopLevel(element)) { | |
| 1358 assert(element.isField || element.isSetter); | |
| 1359 ir.Parameter v = new ir.Parameter(null); | |
| 1360 ir.Continuation k = new ir.Continuation([v]); | |
| 1361 Selector selector = elements.getSelector(node); | |
| 1362 ir.InvokeStatic invoke = | |
| 1363 new ir.InvokeStatic(element, selector, k, [valueToStore]); | |
| 1364 add(new ir.LetCont(k, invoke)); | |
| 1365 } else { | |
| 1366 if (element != null && Elements.isUnresolved(element)) { | |
| 1367 return giveup(node, 'SendSet: non-local, non-static, unresolved'); | |
| 1368 } | |
| 1369 // Setter or index-setter invocation | |
| 1370 ir.Parameter v = new ir.Parameter(null); | |
| 1371 ir.Continuation k = new ir.Continuation([v]); | |
| 1372 Selector selector = elements.getSelector(node); | |
| 1373 assert(selector.kind == SelectorKind.SETTER || | |
| 1374 selector.kind == SelectorKind.INDEX); | |
| 1375 List<ir.Definition> arguments = selector.isIndexSet | |
| 1376 ? [index, valueToStore] | |
| 1377 : [valueToStore]; | |
| 1378 ir.Expression invoke = | |
| 1379 createDynamicInvoke(node, selector, receiver, k, arguments); | |
| 1380 add(new ir.LetCont(k, invoke)); | |
| 1381 } | |
| 1292 | 1382 |
| 1293 if (ast.Operator.INCREMENT_OPERATORS.contains(op.source) && | 1383 if (node.isPostfix) { |
| 1294 !node.isPrefix) { | 1384 assert(originalValue != null); |
| 1295 assert(getter != null); | 1385 return originalValue; |
| 1296 return getter; | |
| 1297 } else { | |
| 1298 return result; | |
| 1299 } | |
| 1300 } else { | 1386 } else { |
| 1301 compiler.internalError(node, "Unknown assignment operator ${op.source}"); | 1387 return valueToStore; |
| 1302 return null; | |
| 1303 } | 1388 } |
| 1304 } | 1389 } |
| 1305 | 1390 |
| 1306 ir.Primitive visitNewExpression(ast.NewExpression node) { | 1391 ir.Primitive visitNewExpression(ast.NewExpression node) { |
| 1307 assert(isOpen); | 1392 assert(isOpen); |
| 1308 if (node.isConst) { | 1393 if (node.isConst) { |
| 1309 return translateConstant(node); | 1394 return translateConstant(node); |
| 1310 } | 1395 } |
| 1311 FunctionElement element = elements[node.send]; | 1396 FunctionElement element = elements[node.send]; |
| 1312 if (Elements.isUnresolved(element)) { | 1397 if (Elements.isUnresolved(element)) { |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1366 | 1451 |
| 1367 static final String ABORT_IRNODE_BUILDER = "IrNode builder aborted"; | 1452 static final String ABORT_IRNODE_BUILDER = "IrNode builder aborted"; |
| 1368 | 1453 |
| 1369 ir.Primitive giveup(ast.Node node, [String reason]) { | 1454 ir.Primitive giveup(ast.Node node, [String reason]) { |
| 1370 throw ABORT_IRNODE_BUILDER; | 1455 throw ABORT_IRNODE_BUILDER; |
| 1371 } | 1456 } |
| 1372 | 1457 |
| 1373 ir.FunctionDefinition nullIfGiveup(ir.FunctionDefinition action()) { | 1458 ir.FunctionDefinition nullIfGiveup(ir.FunctionDefinition action()) { |
| 1374 try { | 1459 try { |
| 1375 return action(); | 1460 return action(); |
| 1376 } catch(e) { | 1461 } catch(e, tr) { |
| 1377 if (e == ABORT_IRNODE_BUILDER) return null; | 1462 if (e == ABORT_IRNODE_BUILDER) { |
| 1463 return null; | |
| 1464 } | |
| 1378 rethrow; | 1465 rethrow; |
| 1379 } | 1466 } |
| 1380 } | 1467 } |
| 1381 | 1468 |
| 1382 void internalError(String reason, {ast.Node node}) { | 1469 void internalError(String reason, {ast.Node node}) { |
| 1383 giveup(node); | 1470 giveup(node); |
| 1384 } | 1471 } |
| 1385 } | 1472 } |
| 1386 | 1473 |
| 1387 /// Translates constant expressions from the AST to the [ConstExp] language. | 1474 /// Translates constant expressions from the AST to the [ConstExp] language. |
| (...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1532 ConstExp visitConditional(ast.Conditional node) { | 1619 ConstExp visitConditional(ast.Conditional node) { |
| 1533 BoolConstant condition = computeConstant(node.condition); | 1620 BoolConstant condition = computeConstant(node.condition); |
| 1534 return visit(condition.isTrue ? node.thenExpression : node.elseExpression); | 1621 return visit(condition.isTrue ? node.thenExpression : node.elseExpression); |
| 1535 } | 1622 } |
| 1536 | 1623 |
| 1537 ConstExp visitNode(ast.Node node) { | 1624 ConstExp visitNode(ast.Node node) { |
| 1538 throw "Unexpected constant: $node"; | 1625 throw "Unexpected constant: $node"; |
| 1539 } | 1626 } |
| 1540 | 1627 |
| 1541 } | 1628 } |
| OLD | NEW |