| 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 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 130 | 130 |
| 131 SourceFile elementSourceFile(Element element) { | 131 SourceFile elementSourceFile(Element element) { |
| 132 if (element is FunctionElement) { | 132 if (element is FunctionElement) { |
| 133 FunctionElement functionElement = element; | 133 FunctionElement functionElement = element; |
| 134 if (functionElement.patch != null) element = functionElement.patch; | 134 if (functionElement.patch != null) element = functionElement.patch; |
| 135 } | 135 } |
| 136 return element.compilationUnit.script.file; | 136 return element.compilationUnit.script.file; |
| 137 } | 137 } |
| 138 } | 138 } |
| 139 | 139 |
| 140 class _GetterElements { |
| 141 ir.Primitive result; |
| 142 ir.Primitive index; |
| 143 ir.Primitive receiver; |
| 144 |
| 145 _GetterElements({this.result, this.index, this.receiver}) ; |
| 146 } |
| 147 |
| 140 /** | 148 /** |
| 141 * A tree visitor that builds [IrNodes]. The visit methods add statements using | 149 * A tree visitor that builds [IrNodes]. The visit methods add statements using |
| 142 * to the [builder] and return the last added statement for trees that represent | 150 * to the [builder] and return the last added statement for trees that represent |
| 143 * an expression. | 151 * an expression. |
| 144 */ | 152 */ |
| 145 class IrBuilder extends ResolvedVisitor<ir.Primitive> { | 153 class IrBuilder extends ResolvedVisitor<ir.Primitive> { |
| 146 final SourceFile sourceFile; | 154 final SourceFile sourceFile; |
| 147 final ir.Continuation returnContinuation; | 155 final ir.Continuation returnContinuation; |
| 148 final List<ir.Parameter> parameters; | 156 final List<ir.Parameter> parameters; |
| 149 | 157 |
| (...skipping 670 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 820 return result; | 828 return result; |
| 821 } | 829 } |
| 822 | 830 |
| 823 ir.Primitive visitLiteralSymbol(ast.LiteralSymbol node) { | 831 ir.Primitive visitLiteralSymbol(ast.LiteralSymbol node) { |
| 824 assert(isOpen); | 832 assert(isOpen); |
| 825 return translateConstant(node); | 833 return translateConstant(node); |
| 826 } | 834 } |
| 827 | 835 |
| 828 ir.Primitive visitIdentifier(ast.Identifier node) { | 836 ir.Primitive visitIdentifier(ast.Identifier node) { |
| 829 assert(isOpen); | 837 assert(isOpen); |
| 838 // "this" is the only identifier that should be met by the visitor. |
| 830 assert(node.isThis()); | 839 assert(node.isThis()); |
| 831 return lookupThis(); | 840 return lookupThis(); |
| 832 } | 841 } |
| 833 | 842 |
| 834 ir.Primitive visitParenthesizedExpression( | 843 ir.Primitive visitParenthesizedExpression( |
| 835 ast.ParenthesizedExpression node) { | 844 ast.ParenthesizedExpression node) { |
| 836 assert(isOpen); | 845 assert(isOpen); |
| 837 return visit(node.expression); | 846 return visit(node.expression); |
| 838 } | 847 } |
| 839 | 848 |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 906 closureTarget = visit(node.selector); | 915 closureTarget = visit(node.selector); |
| 907 } else { | 916 } else { |
| 908 assert(Elements.isLocal(element)); | 917 assert(Elements.isLocal(element)); |
| 909 closureTarget = lookupLocal(element); | 918 closureTarget = lookupLocal(element); |
| 910 } | 919 } |
| 911 Selector closureSelector = elements.getSelector(node); | 920 Selector closureSelector = elements.getSelector(node); |
| 912 return translateClosureCall(closureTarget, closureSelector, | 921 return translateClosureCall(closureTarget, closureSelector, |
| 913 node.argumentsNode); | 922 node.argumentsNode); |
| 914 } | 923 } |
| 915 | 924 |
| 925 /// If [node] is null, returns this. |
| 926 /// If [node] is super, returns null (for special handling) |
| 927 /// Otherwise visits [node] and returns the result. |
| 928 ir.Primitive visitReceiver(ast.Expression node) { |
| 929 if (node == null) return lookupThis(); |
| 930 if (node.isSuper()) return null; |
| 931 return visit(node); |
| 932 } |
| 933 |
| 934 /// Makes an [InvokeMethod] unless [node.receiver.isSuper()], in that case |
| 935 /// makes an [InvokeSuperMethod] ignoring [receiver]. |
| 936 ir.Expression createDynamicInvoke(ast.Send node, |
| 937 Selector selector, |
| 938 ir.Definition receiver, |
| 939 ir.Continuation k, |
| 940 List<ir.Definition> arguments) { |
| 941 return node.receiver != null && node.receiver.isSuper() |
| 942 ? new ir.InvokeSuperMethod(selector, k, arguments) |
| 943 : new ir.InvokeMethod(receiver, selector, k, arguments); |
| 944 } |
| 945 |
| 916 ir.Primitive visitDynamicSend(ast.Send node) { | 946 ir.Primitive visitDynamicSend(ast.Send node) { |
| 917 assert(isOpen); | 947 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); | 948 Selector selector = elements.getSelector(node); |
| 922 ir.Primitive receiver = visit(node.receiver); | 949 ir.Primitive receiver = visitReceiver(node.receiver); |
| 923 List<ir.Primitive> arguments = new List<ir.Primitive>(); | 950 List<ir.Primitive> arguments = new List<ir.Primitive>(); |
| 924 for (ast.Node n in node.arguments) { | 951 for (ast.Node n in node.arguments) { |
| 925 arguments.add(visit(n)); | 952 arguments.add(visit(n)); |
| 926 } | 953 } |
| 927 ir.Parameter v = new ir.Parameter(null); | 954 ir.Parameter v = new ir.Parameter(null); |
| 928 ir.Continuation k = new ir.Continuation([v]); | 955 ir.Continuation k = new ir.Continuation([v]); |
| 929 ir.Expression invoke = | 956 ir.Expression invoke = |
| 930 new ir.InvokeMethod(receiver, selector, k, arguments); | 957 createDynamicInvoke(node, selector, receiver, k, arguments); |
| 931 add(new ir.LetCont(k, invoke)); | 958 add(new ir.LetCont(k, invoke)); |
| 932 return v; | 959 return v; |
| 933 } | 960 } |
| 934 | 961 |
| 962 _GetterElements translateGetter(ast.Send node, Selector selector) { |
| 963 Element element = elements[node]; |
| 964 ir.Primitive result; |
| 965 ir.Primitive receiver; |
| 966 ir.Primitive index; |
| 967 |
| 968 if (Elements.isErroneousElement(element)) { |
| 969 giveup(node, 'Erroneous element on GetterSend'); |
| 970 return null; |
| 971 } |
| 972 |
| 973 if (element != null && element.isConst) { |
| 974 // Reference to constant local, top-level or static field |
| 975 |
| 976 result = translateConstant(node); |
| 977 } else if (Elements.isLocal(element)) { |
| 978 // Reference to local variable |
| 979 |
| 980 result = lookupLocal(element); |
| 981 } else if (element == null || |
| 982 Elements.isInstanceField(element) || |
| 983 Elements.isInstanceMethod(element) || |
| 984 selector.isIndex || |
| 985 node.isSuperCall) { |
| 986 // Dynamic dispatch to a getter. Sometimes resolution will suggest a target |
| 987 // element, but in these cases we must still emit a dynamic dispatch. The |
| 988 // target element may be an instance method in case we are converting a |
| 989 // method to a function object. |
| 990 |
| 991 receiver = visitReceiver(node.receiver); |
| 992 List<ir.Primitive> arguments = new List<ir.Primitive>(); |
| 993 if (selector.isIndex) { |
| 994 index = visit(node.arguments.head); |
| 995 arguments.add(index); |
| 996 } |
| 997 |
| 998 ir.Parameter v = new ir.Parameter(null); |
| 999 ir.Continuation k = new ir.Continuation([v]); |
| 1000 assert(selector.kind == SelectorKind.GETTER || |
| 1001 selector.kind == SelectorKind.INDEX); |
| 1002 ir.Expression invoke = |
| 1003 createDynamicInvoke(node, selector, receiver, k, arguments); |
| 1004 add(new ir.LetCont(k, invoke)); |
| 1005 result = v; |
| 1006 } else if (element.isField || element.isGetter || |
| 1007 // Access to a static field or getter (non-static case handled above). |
| 1008 // Even if there is only a setter, we compile as if it was a getter, |
| 1009 // so the vm can fail at runtime. |
| 1010 |
| 1011 element.isSetter) { |
| 1012 ir.Parameter v = new ir.Parameter(null); |
| 1013 ir.Continuation k = new ir.Continuation([v]); |
| 1014 assert(selector.kind == SelectorKind.GETTER || |
| 1015 selector.kind == SelectorKind.SETTER); |
| 1016 ir.Expression invoke = |
| 1017 new ir.InvokeStatic(element, selector, k, []); |
| 1018 add(new ir.LetCont(k, invoke)); |
| 1019 result = v; |
| 1020 } else if (Elements.isStaticOrTopLevelFunction(element)) { |
| 1021 // Convert a top-level or static function to a function object. |
| 1022 |
| 1023 result = translateConstant(node); |
| 1024 } else { |
| 1025 throw "Unexpected SendSet getter: $node, $element"; |
| 1026 } |
| 1027 return new _GetterElements( |
| 1028 result: result,index: index, receiver: receiver); |
| 1029 } |
| 1030 |
| 935 ir.Primitive visitGetterSend(ast.Send node) { | 1031 ir.Primitive visitGetterSend(ast.Send node) { |
| 936 assert(isOpen); | 1032 assert(isOpen); |
| 937 Element element = elements[node]; | 1033 return translateGetter(node, elements.getSelector(node)).result; |
| 938 | 1034 |
| 939 // TODO(asgerf): Generate code for erroneous getter access | |
| 940 if (Elements.isErroneousElement(element)) { | |
| 941 return giveup(node, 'Erroneous element on GetterSend'); | |
| 942 } | |
| 943 | |
| 944 // Reference to constant local, top-level or static field | |
| 945 if (element != null && element.isConst) { | |
| 946 return translateConstant(node); | |
| 947 } | |
| 948 | |
| 949 // Reference to local variable | |
| 950 if (Elements.isLocal(element)) { | |
| 951 return lookupLocal(element); | |
| 952 } | |
| 953 | |
| 954 // Dynamic dispatch to a getter. Sometimes resolution will suggest a target | |
| 955 // 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 | |
| 957 // a method to a function object. | |
| 958 if (element == null || | |
| 959 Elements.isInstanceField(element) || | |
| 960 Elements.isInstanceMethod(element)) { | |
| 961 ir.Primitive receiver = node.receiver == null | |
| 962 ? lookupThis() | |
| 963 : visit(node.receiver); | |
| 964 ir.Parameter v = new ir.Parameter(null); | |
| 965 ir.Continuation k = new ir.Continuation([v]); | |
| 966 Selector selector = elements.getSelector(node); | |
| 967 assert(selector.kind == SelectorKind.GETTER); | |
| 968 ir.InvokeMethod invoke = new ir.InvokeMethod(receiver, selector, k, []); | |
| 969 add(new ir.LetCont(k, invoke)); | |
| 970 return v; | |
| 971 } | |
| 972 | |
| 973 // Access to a static field or getter (non-static case handled above). | |
| 974 if (element.isField || element.isGetter) { | |
| 975 ir.Parameter v = new ir.Parameter(null); | |
| 976 ir.Continuation k = new ir.Continuation([v]); | |
| 977 Selector selector = elements.getSelector(node); | |
| 978 assert(selector.kind == SelectorKind.GETTER); | |
| 979 ir.InvokeStatic invoke = new ir.InvokeStatic(element, selector, k, []); | |
| 980 add(new ir.LetCont(k, invoke)); | |
| 981 return v; | |
| 982 } | |
| 983 | |
| 984 // Convert a top-level or static function to a function object. | |
| 985 if (Elements.isStaticOrTopLevelFunction(element)) { | |
| 986 return translateConstant(node); | |
| 987 } | |
| 988 | |
| 989 throw "Unexpected GetterSend: $node, $element"; | |
| 990 } | 1035 } |
| 991 | 1036 |
| 992 ir.Primitive buildNegation(ir.Primitive condition) { | 1037 ir.Primitive buildNegation(ir.Primitive condition) { |
| 993 // ! e is translated as e ? false : true | 1038 // ! e is translated as e ? false : true |
| 994 | 1039 |
| 995 // Add a continuation parameter for the result of the expression. | 1040 // Add a continuation parameter for the result of the expression. |
| 996 ir.Parameter resultParameter = new ir.Parameter(null); | 1041 ir.Parameter resultParameter = new ir.Parameter(null); |
| 997 | 1042 |
| 998 ir.Continuation joinContinuation = new ir.Continuation([resultParameter]); | 1043 ir.Continuation joinContinuation = new ir.Continuation([resultParameter]); |
| 999 ir.Continuation thenContinuation = new ir.Continuation([]); | 1044 ir.Continuation thenContinuation = new ir.Continuation([]); |
| (...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1174 ir.Parameter v = new ir.Parameter(null); | 1219 ir.Parameter v = new ir.Parameter(null); |
| 1175 ir.Continuation k = new ir.Continuation([v]); | 1220 ir.Continuation k = new ir.Continuation([v]); |
| 1176 ir.Expression invoke = | 1221 ir.Expression invoke = |
| 1177 new ir.InvokeStatic(element, selector, k, arguments); | 1222 new ir.InvokeStatic(element, selector, k, arguments); |
| 1178 add(new ir.LetCont(k, invoke)); | 1223 add(new ir.LetCont(k, invoke)); |
| 1179 return v; | 1224 return v; |
| 1180 } | 1225 } |
| 1181 | 1226 |
| 1182 ir.Primitive visitSuperSend(ast.Send node) { | 1227 ir.Primitive visitSuperSend(ast.Send node) { |
| 1183 assert(isOpen); | 1228 assert(isOpen); |
| 1184 return giveup(node, 'SuperSend'); | 1229 if (node.isPropertyAccess) { |
| 1230 return visitGetterSend(node); |
| 1231 } else { |
| 1232 return visitDynamicSend(node); |
| 1233 } |
| 1185 } | 1234 } |
| 1186 | 1235 |
| 1187 ir.Primitive visitTypeReferenceSend(ast.Send node) { | 1236 ir.Primitive visitTypeReferenceSend(ast.Send node) { |
| 1188 assert(isOpen); | 1237 assert(isOpen); |
| 1189 Element element = elements[node]; | 1238 Element element = elements[node]; |
| 1190 assert(element is TypeDeclarationElement || element.isTypeVariable); | 1239 assert(element is TypeDeclarationElement || element.isTypeVariable); |
| 1191 | 1240 |
| 1192 // If the user is trying to invoke the type literal or variable, | 1241 // If the user is trying to invoke the type literal or variable, |
| 1193 // it must be treated as a function call. | 1242 // it must be treated as a function call. |
| 1194 if (node.argumentsNode != null) { | 1243 if (node.argumentsNode != null) { |
| 1195 return visitDynamicSend(node); | 1244 return visitDynamicSend(node); |
| 1196 } | 1245 } |
| 1197 | 1246 |
| 1198 if (element is TypeDeclarationElement) { | 1247 if (element is TypeDeclarationElement) { |
| 1199 return translateConstant(node); | 1248 return translateConstant(node); |
| 1200 } else { | 1249 } else { |
| 1201 ir.Primitive prim = new ir.ReifyTypeVar(element); | 1250 ir.Primitive prim = new ir.ReifyTypeVar(element); |
| 1202 add(new ir.LetPrim(prim)); | 1251 add(new ir.LetPrim(prim)); |
| 1203 return prim; | 1252 return prim; |
| 1204 } | 1253 } |
| 1205 } | 1254 } |
| 1206 | 1255 |
| 1207 ir.Primitive visitSendSet(ast.SendSet node) { | 1256 ir.Primitive visitSendSet(ast.SendSet node) { |
| 1208 assert(isOpen); | 1257 assert(isOpen); |
| 1209 Element element = elements[node]; | 1258 Element element = elements[node]; |
| 1210 ast.Operator op = node.assignmentOperator; | 1259 ast.Operator op = node.assignmentOperator; |
| 1211 ir.Primitive result; | 1260 // For complex operators, this is the result of getting (before assigning) |
| 1212 ir.Primitive getter; | 1261 ir.Primitive originalValue; |
| 1213 if (op.source == '=') { | 1262 // For []+= style operators, this saves the index. |
| 1214 if (Elements.isLocal(element)) { | 1263 ir.Primitive index; |
| 1215 // Exactly one argument expected for a simple assignment. | 1264 ir.Primitive receiver; |
| 1216 assert(!node.arguments.isEmpty); | 1265 // This is what gets assigned. |
| 1217 assert(node.arguments.tail.isEmpty); | 1266 ir.Primitive valueToStore; |
| 1218 result = visit(node.arguments.head); | 1267 Selector selector = elements.getSelector(node); |
| 1219 result.useElementAsHint(element); | 1268 Selector operatorSelector = |
| 1220 assignedVars[variableIndex[element]] = result; | 1269 elements.getOperatorSelectorInComplexSendSet(node); |
| 1221 return result; | 1270 Selector getterSelector = |
| 1222 } else if (Elements.isStaticOrTopLevel(element)) { | 1271 elements.getGetterSelectorInComplexSendSet(node); |
| 1223 assert(element.isField || element.isSetter); | 1272 assert( |
| 1224 assert(!node.arguments.isEmpty && node.arguments.tail.isEmpty); | 1273 // Indexing send-sets have an argument for the index. |
| 1225 ir.Parameter v = new ir.Parameter(null); | 1274 (selector.isIndexSet ? 1 : 0) + |
| 1226 ir.Continuation k = new ir.Continuation([v]); | 1275 // Non-increment send-sets have one more argument. |
| 1227 Selector selector = elements.getSelector(node); | 1276 (ast.Operator.INCREMENT_OPERATORS.contains(op.source) ? 0 : 1) |
| 1228 ir.Definition arg = visit(node.arguments.head); | 1277 == node.argumentCount()); |
| 1229 ir.InvokeStatic invoke = | |
| 1230 new ir.InvokeStatic(element, selector, k, [arg]); | |
| 1231 add(new ir.LetCont(k, invoke)); | |
| 1232 return arg; | |
| 1233 } else if (node.receiver == null) { | |
| 1234 // Nodes that fall in this case: | |
| 1235 // - Unresolved top-level | |
| 1236 // - Assignment to final variable (will not be resolved) | |
| 1237 return giveup(node, 'SendSet: non-local, non-static, but no receiver'); | |
| 1238 } else { | |
| 1239 if (element != null && Elements.isUnresolved(element)) { | |
| 1240 return giveup(node); | |
| 1241 } | |
| 1242 | 1278 |
| 1243 // Setter or index-setter invocation | 1279 ast.Node assignArg = selector.isIndexSet |
| 1244 assert(node.receiver != null); | 1280 ? node.arguments.tail.head |
| 1281 : node.arguments.head; |
| 1245 | 1282 |
| 1246 if (node.receiver.isSuper()) return giveup(node, 'Super SendSet'); | 1283 // Get the value into valueToStore |
| 1284 if (op.source == "=") { |
| 1285 if (selector.isIndexSet) { |
| 1286 receiver = visitReceiver(node.receiver); |
| 1287 index = visit(node.arguments.head); |
| 1288 } else if (element == null || Elements.isInstanceField(element)) { |
| 1289 receiver = visitReceiver(node.receiver); |
| 1290 } |
| 1291 valueToStore = visit(assignArg); |
| 1292 } else { |
| 1293 // Get the original value into getter |
| 1294 assert(ast.Operator.COMPLEX_OPERATORS.contains(op.source)); |
| 1247 | 1295 |
| 1248 ir.Primitive receiver = node.receiver == null | 1296 _GetterElements getterResult = translateGetter(node, getterSelector); |
| 1249 ? lookupThis() | 1297 index = getterResult.index; |
| 1250 : visit(node.receiver); | 1298 receiver = getterResult.receiver; |
| 1251 ir.Parameter v = new ir.Parameter(null); | 1299 originalValue = getterResult.result; |
| 1252 ir.Continuation k = new ir.Continuation([v]); | |
| 1253 Selector selector = elements.getSelector(node); | |
| 1254 assert(selector.kind == SelectorKind.SETTER || | |
| 1255 selector.kind == SelectorKind.INDEX); | |
| 1256 List<ir.Definition> args = node.arguments.mapToList(visit, | |
| 1257 growable:false); | |
| 1258 ir.InvokeMethod invoke = | |
| 1259 new ir.InvokeMethod(receiver, selector, k, args); | |
| 1260 add(new ir.LetCont(k, invoke)); | |
| 1261 return args.last; | |
| 1262 } | |
| 1263 } else if (ast.Operator.COMPLEX_OPERATORS.contains(op.source)) { | |
| 1264 Element selectorElement = elements[node.selector]; | |
| 1265 if (selectorElement != null && !selectorElement.isAssignable) { | |
| 1266 return giveup(node, 'Unresolved or non-assignable compound assignment'); | |
| 1267 } | |
| 1268 if (!Elements.isLocal(selectorElement)) { | |
| 1269 return giveup(node, 'Non-local compound assignment'); | |
| 1270 } | |
| 1271 | 1300 |
| 1272 Selector selector = elements.getOperatorSelectorInComplexSendSet(node); | 1301 // Do the modification of the value in getter. |
| 1273 getter = lookupLocal(selectorElement); | |
| 1274 | |
| 1275 ir.Primitive arg; | 1302 ir.Primitive arg; |
| 1276 if (ast.Operator.INCREMENT_OPERATORS.contains(op.source)) { | 1303 if (ast.Operator.INCREMENT_OPERATORS.contains(op.source)) { |
| 1277 assert(node.arguments.isEmpty); | |
| 1278 arg = makePrimConst(constantSystem.createInt(1)); | 1304 arg = makePrimConst(constantSystem.createInt(1)); |
| 1279 add(new ir.LetPrim(arg)); | 1305 add(new ir.LetPrim(arg)); |
| 1280 } else { | 1306 } else { |
| 1281 assert(!node.arguments.isEmpty); | 1307 arg = visit(assignArg); |
| 1282 assert(node.arguments.tail.isEmpty); | |
| 1283 arg = visit(node.arguments.head); | |
| 1284 } | 1308 } |
| 1285 arg.useElementAsHint(element); | 1309 valueToStore = new ir.Parameter(null); |
| 1286 result = new ir.Parameter(null); | 1310 ir.Continuation k = new ir.Continuation([valueToStore]); |
| 1287 ir.Continuation k = new ir.Continuation([result]); | 1311 ir.Expression invoke = |
| 1288 ir.Expression invoke = new ir.InvokeMethod(getter, selector, k, [arg]); | 1312 new ir.InvokeMethod(originalValue, operatorSelector, k, [arg]); |
| 1289 add(new ir.LetCont(k, invoke)); | 1313 add(new ir.LetCont(k, invoke)); |
| 1314 } |
| 1290 | 1315 |
| 1291 assignedVars[variableIndex[element]] = result; | 1316 // Set the value |
| 1317 if (Elements.isLocal(element)) { |
| 1318 valueToStore.useElementAsHint(element); |
| 1319 assignedVars[variableIndex[element]] = valueToStore; |
| 1320 } else if (Elements.isStaticOrTopLevel(element)) { |
| 1321 assert(element.isField || element.isSetter); |
| 1322 ir.Parameter v = new ir.Parameter(null); |
| 1323 ir.Continuation k = new ir.Continuation([v]); |
| 1324 Selector selector = elements.getSelector(node); |
| 1325 ir.InvokeStatic invoke = |
| 1326 new ir.InvokeStatic(element, selector, k, [valueToStore]); |
| 1327 add(new ir.LetCont(k, invoke)); |
| 1328 } else { |
| 1329 if (element != null && Elements.isUnresolved(element)) { |
| 1330 return giveup(node, 'SendSet: non-local, non-static, unresolved'); |
| 1331 } |
| 1332 // Setter or index-setter invocation |
| 1333 ir.Parameter v = new ir.Parameter(null); |
| 1334 ir.Continuation k = new ir.Continuation([v]); |
| 1335 Selector selector = elements.getSelector(node); |
| 1336 assert(selector.kind == SelectorKind.SETTER || |
| 1337 selector.kind == SelectorKind.INDEX); |
| 1338 List<ir.Definition> arguments = selector.isIndexSet |
| 1339 ? [index, valueToStore] |
| 1340 : [valueToStore]; |
| 1341 ir.Expression invoke = |
| 1342 createDynamicInvoke(node, selector, receiver, k, arguments); |
| 1343 add(new ir.LetCont(k, invoke)); |
| 1344 } |
| 1292 | 1345 |
| 1293 if (ast.Operator.INCREMENT_OPERATORS.contains(op.source) && | 1346 if (node.isPostfix) { |
| 1294 !node.isPrefix) { | 1347 assert(originalValue != null); |
| 1295 assert(getter != null); | 1348 return originalValue; |
| 1296 return getter; | |
| 1297 } else { | |
| 1298 return result; | |
| 1299 } | |
| 1300 } else { | 1349 } else { |
| 1301 compiler.internalError(node, "Unknown assignment operator ${op.source}"); | 1350 return valueToStore; |
| 1302 return null; | |
| 1303 } | 1351 } |
| 1304 } | 1352 } |
| 1305 | 1353 |
| 1306 ir.Primitive visitNewExpression(ast.NewExpression node) { | 1354 ir.Primitive visitNewExpression(ast.NewExpression node) { |
| 1307 assert(isOpen); | 1355 assert(isOpen); |
| 1308 if (node.isConst) { | 1356 if (node.isConst) { |
| 1309 return translateConstant(node); | 1357 return translateConstant(node); |
| 1310 } | 1358 } |
| 1311 FunctionElement element = elements[node.send]; | 1359 FunctionElement element = elements[node.send]; |
| 1312 if (Elements.isUnresolved(element)) { | 1360 if (Elements.isUnresolved(element)) { |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1366 | 1414 |
| 1367 static final String ABORT_IRNODE_BUILDER = "IrNode builder aborted"; | 1415 static final String ABORT_IRNODE_BUILDER = "IrNode builder aborted"; |
| 1368 | 1416 |
| 1369 ir.Primitive giveup(ast.Node node, [String reason]) { | 1417 ir.Primitive giveup(ast.Node node, [String reason]) { |
| 1370 throw ABORT_IRNODE_BUILDER; | 1418 throw ABORT_IRNODE_BUILDER; |
| 1371 } | 1419 } |
| 1372 | 1420 |
| 1373 ir.FunctionDefinition nullIfGiveup(ir.FunctionDefinition action()) { | 1421 ir.FunctionDefinition nullIfGiveup(ir.FunctionDefinition action()) { |
| 1374 try { | 1422 try { |
| 1375 return action(); | 1423 return action(); |
| 1376 } catch(e) { | 1424 } catch(e, tr) { |
| 1377 if (e == ABORT_IRNODE_BUILDER) return null; | 1425 if (e == ABORT_IRNODE_BUILDER) { |
| 1426 return null; |
| 1427 } |
| 1378 rethrow; | 1428 rethrow; |
| 1379 } | 1429 } |
| 1380 } | 1430 } |
| 1381 | 1431 |
| 1382 void internalError(String reason, {ast.Node node}) { | 1432 void internalError(String reason, {ast.Node node}) { |
| 1383 giveup(node); | 1433 giveup(node); |
| 1384 } | 1434 } |
| 1385 } | 1435 } |
| 1386 | 1436 |
| 1387 /// Translates constant expressions from the AST to the [ConstExp] language. | 1437 /// 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) { | 1582 ConstExp visitConditional(ast.Conditional node) { |
| 1533 BoolConstant condition = computeConstant(node.condition); | 1583 BoolConstant condition = computeConstant(node.condition); |
| 1534 return visit(condition.isTrue ? node.thenExpression : node.elseExpression); | 1584 return visit(condition.isTrue ? node.thenExpression : node.elseExpression); |
| 1535 } | 1585 } |
| 1536 | 1586 |
| 1537 ConstExp visitNode(ast.Node node) { | 1587 ConstExp visitNode(ast.Node node) { |
| 1538 throw "Unexpected constant: $node"; | 1588 throw "Unexpected constant: $node"; |
| 1539 } | 1589 } |
| 1540 | 1590 |
| 1541 } | 1591 } |
| OLD | NEW |