| OLD | NEW |
| 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, 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 /** A formal parameter to a [Method]. */ | 5 /** A formal parameter to a [Method]. */ |
| 6 class Parameter { | 6 class Parameter { |
| 7 FormalNode definition; | 7 FormalNode definition; |
| 8 Member method; | 8 Member method; |
| 9 | 9 |
| 10 String name; | 10 String name; |
| (...skipping 18 matching lines...) Expand all Loading... |
| 29 } | 29 } |
| 30 | 30 |
| 31 if (definition.value != null) { | 31 if (definition.value != null) { |
| 32 // To match VM, detect cases where value was not actually specified in | 32 // To match VM, detect cases where value was not actually specified in |
| 33 // code and don't signal errors. | 33 // code and don't signal errors. |
| 34 // TODO(jimhug): Clean up after issue #352 is resolved. | 34 // TODO(jimhug): Clean up after issue #352 is resolved. |
| 35 if (definition.value is NullExpression && | 35 if (definition.value is NullExpression && |
| 36 definition.value.span.start == definition.span.start) { | 36 definition.value.span.start == definition.span.start) { |
| 37 return; | 37 return; |
| 38 } | 38 } |
| 39 if (method.name == '\$call') { | 39 if (method.name == ':call') { |
| 40 // TODO(jimhug): Need simpler way to detect "true" function types vs. | 40 // TODO(jimhug): Need simpler way to detect "true" function types vs. |
| 41 // regular methods being used as function types for closures. | 41 // regular methods being used as function types for closures. |
| 42 if (method.definition.body == null) { | 42 if (method.definition.body == null) { |
| 43 world.error('default value not allowed on function type', | 43 world.error('default value not allowed on function type', |
| 44 definition.span); | 44 definition.span); |
| 45 } | 45 } |
| 46 } else if (method.isAbstract) { | 46 } else if (method.isAbstract) { |
| 47 world.error('default value not allowed on abstract methods', | 47 world.error('default value not allowed on abstract methods', |
| 48 definition.span); | 48 definition.span); |
| 49 } | 49 } |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 101 bool get isProperty() => false; | 101 bool get isProperty() => false; |
| 102 bool get isAbstract() => false; | 102 bool get isAbstract() => false; |
| 103 | 103 |
| 104 bool get isFinal() => false; | 104 bool get isFinal() => false; |
| 105 | 105 |
| 106 // TODO(jmesserly): these only makes sense on methods, but because of | 106 // TODO(jmesserly): these only makes sense on methods, but because of |
| 107 // ConcreteMember we need to support them on Member. | 107 // ConcreteMember we need to support them on Member. |
| 108 bool get isConst() => false; | 108 bool get isConst() => false; |
| 109 bool get isFactory() => false; | 109 bool get isFactory() => false; |
| 110 | 110 |
| 111 bool get isOperator() => name.startsWith('\$'); | 111 bool get isOperator() => name.startsWith(':'); |
| 112 bool get isCallMethod() => name == '\$call'; | 112 bool get isCallMethod() => name == ':call'; |
| 113 | 113 |
| 114 bool get prefersPropertySyntax() => true; | 114 bool get prefersPropertySyntax() => true; |
| 115 bool get requiresFieldSyntax() => false; | 115 bool get requiresFieldSyntax() => false; |
| 116 | 116 |
| 117 bool get isNative() => false; | 117 bool get isNative() => false; |
| 118 String get constructorName() { | 118 String get constructorName() { |
| 119 world.internalError('can not be a constructor', span); | 119 world.internalError('can not be a constructor', span); |
| 120 } | 120 } |
| 121 | 121 |
| 122 // Don't display an error here; we'll get a better error later. | 122 // Don't display an error here; we'll get a better error later. |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 155 // TODO(jmesserly): isDynamic isn't a great name for this, something better? | 155 // TODO(jmesserly): isDynamic isn't a great name for this, something better? |
| 156 abstract Value _get(MethodGenerator context, Node node, Value target, | 156 abstract Value _get(MethodGenerator context, Node node, Value target, |
| 157 [bool isDynamic]); | 157 [bool isDynamic]); |
| 158 | 158 |
| 159 abstract Value _set(MethodGenerator context, Node node, Value target, | 159 abstract Value _set(MethodGenerator context, Node node, Value target, |
| 160 Value value, [bool isDynamic]); | 160 Value value, [bool isDynamic]); |
| 161 | 161 |
| 162 bool canInvoke(MethodGenerator context, Arguments args) { | 162 bool canInvoke(MethodGenerator context, Arguments args) { |
| 163 // No source location needed because canInvoke may not produce errors. | 163 // No source location needed because canInvoke may not produce errors. |
| 164 return canGet && | 164 return canGet && |
| 165 new Value(returnType, null, null).canInvoke(context, '\$call', args); | 165 new Value(returnType, null, null).canInvoke(context, ':call', args); |
| 166 } | 166 } |
| 167 | 167 |
| 168 Value invoke(MethodGenerator context, Node node, Value target, Arguments args, | 168 Value invoke(MethodGenerator context, Node node, Value target, Arguments args, |
| 169 [bool isDynamic=false]) { | 169 [bool isDynamic=false]) { |
| 170 var newTarget = _get(context, node, target, isDynamic); | 170 var newTarget = _get(context, node, target, isDynamic); |
| 171 return newTarget.invoke(context, '\$call', node, args, isDynamic); | 171 return newTarget.invoke(context, ':call', node, args, isDynamic); |
| 172 } | 172 } |
| 173 | 173 |
| 174 bool override(Member other) { | 174 bool override(Member other) { |
| 175 if (isStatic) { | 175 if (isStatic) { |
| 176 world.error('static members can not hide parent members', | 176 world.error('static members can not hide parent members', |
| 177 span, other.span); | 177 span, other.span); |
| 178 return false; | 178 return false; |
| 179 } else if (other.isStatic) { | 179 } else if (other.isStatic) { |
| 180 world.error('can not override static member', span, other.span); | 180 world.error('can not override static member', span, other.span); |
| 181 return false; | 181 return false; |
| (...skipping 774 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 956 return new Value(inferredResult, | 956 return new Value(inferredResult, |
| 957 '${declaringType.jsname}.$jsname($argsString)', node.span); | 957 '${declaringType.jsname}.$jsname($argsString)', node.span); |
| 958 } | 958 } |
| 959 | 959 |
| 960 var code = '${target.code}.$jsname($argsString)'; | 960 var code = '${target.code}.$jsname($argsString)'; |
| 961 // optimize expressions which we know statically their value. | 961 // optimize expressions which we know statically their value. |
| 962 if (target.isConst) { | 962 if (target.isConst) { |
| 963 if (target is GlobalValue) { | 963 if (target is GlobalValue) { |
| 964 target = target.dynamic.exp; // TODO: an inline "cast" would be nice. | 964 target = target.dynamic.exp; // TODO: an inline "cast" would be nice. |
| 965 } | 965 } |
| 966 if (name == 'get\$length') { | 966 if (name == 'get:length') { |
| 967 if (target is ConstListValue || target is ConstMapValue) { | 967 if (target is ConstListValue || target is ConstMapValue) { |
| 968 code = '${target.dynamic.values.length}'; | 968 code = '${target.dynamic.values.length}'; |
| 969 } | 969 } |
| 970 } else if (name == 'isEmpty') { | 970 } else if (name == 'isEmpty') { |
| 971 if (target is ConstListValue || target is ConstMapValue) { | 971 if (target is ConstListValue || target is ConstMapValue) { |
| 972 code = '${target.dynamic.values.isEmpty()}'; | 972 code = '${target.dynamic.values.isEmpty()}'; |
| 973 } | 973 } |
| 974 } | 974 } |
| 975 } | 975 } |
| 976 | 976 |
| 977 // TODO(jmesserly): factor this better | 977 // TODO(jmesserly): factor this better |
| 978 if (name == 'get\$typeName' && declaringType.library == world.dom) { | 978 if (name == 'get:typeName' && declaringType.library == world.dom) { |
| 979 world.gen.corejs.ensureTypeNameOf(); | 979 world.gen.corejs.ensureTypeNameOf(); |
| 980 } | 980 } |
| 981 | 981 |
| 982 return new Value(inferredResult, code, node.span); | 982 return new Value(inferredResult, code, node.span); |
| 983 } | 983 } |
| 984 | 984 |
| 985 Value _invokeConstructor(MethodGenerator context, Node node, | 985 Value _invokeConstructor(MethodGenerator context, Node node, |
| 986 Value target, Arguments args, argsString) { | 986 Value target, Arguments args, argsString) { |
| 987 declaringType.markUsed(); | 987 declaringType.markUsed(); |
| 988 | 988 |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1113 Value _invokeBuiltin(MethodGenerator context, Node node, Value target, | 1113 Value _invokeBuiltin(MethodGenerator context, Node node, Value target, |
| 1114 Arguments args, argsCode, bool isDynamic) { | 1114 Arguments args, argsCode, bool isDynamic) { |
| 1115 var allConst = target.isConst && args.values.every((arg) => arg.isConst); | 1115 var allConst = target.isConst && args.values.every((arg) => arg.isConst); |
| 1116 | 1116 |
| 1117 // Handle some fast paths for Number, String, List and DOM. | 1117 // Handle some fast paths for Number, String, List and DOM. |
| 1118 if (declaringType.isNum) { | 1118 if (declaringType.isNum) { |
| 1119 // TODO(jimhug): This fails in bad ways when argsCode[1] is not num. | 1119 // TODO(jimhug): This fails in bad ways when argsCode[1] is not num. |
| 1120 // TODO(jimhug): What about null? | 1120 // TODO(jimhug): What about null? |
| 1121 if (!allConst) { | 1121 if (!allConst) { |
| 1122 var code; | 1122 var code; |
| 1123 if (name == '\$negate') { | 1123 if (name == ':negate') { |
| 1124 code = '-${target.code}'; | 1124 code = '-${target.code}'; |
| 1125 } else if (name == '\$bit_not') { | 1125 } else if (name == ':bit_not') { |
| 1126 code = '~${target.code}'; | 1126 code = '~${target.code}'; |
| 1127 } else if (name == '\$truncdiv' || name == '\$mod') { | 1127 } else if (name == ':truncdiv' || name == ':mod') { |
| 1128 world.gen.corejs.useOperator(name); | 1128 world.gen.corejs.useOperator(name); |
| 1129 code = '$name(${target.code}, ${argsCode[0]})'; | 1129 code = '$jsname(${target.code}, ${argsCode[0]})'; |
| 1130 } else { | 1130 } else { |
| 1131 var op = TokenKind.rawOperatorFromMethod(name); | 1131 var op = TokenKind.rawOperatorFromMethod(name); |
| 1132 code = '${target.code} $op ${argsCode[0]}'; | 1132 code = '${target.code} $op ${argsCode[0]}'; |
| 1133 } | 1133 } |
| 1134 | 1134 |
| 1135 return new Value(inferredResult, code, node.span); | 1135 return new Value(inferredResult, code, node.span); |
| 1136 } else { | 1136 } else { |
| 1137 var value; | 1137 var value; |
| 1138 num val0, val1, ival0, ival1; | 1138 num val0, val1, ival0, ival1; |
| 1139 val0 = target.dynamic.actualValue; | 1139 val0 = target.dynamic.actualValue; |
| 1140 ival0 = val0.toInt(); | 1140 ival0 = val0.toInt(); |
| 1141 if (args.values.length > 0) { | 1141 if (args.values.length > 0) { |
| 1142 val1 = args.values[0].dynamic.actualValue; | 1142 val1 = args.values[0].dynamic.actualValue; |
| 1143 ival1 = val1.toInt(); | 1143 ival1 = val1.toInt(); |
| 1144 } | 1144 } |
| 1145 switch (name) { | 1145 switch (name) { |
| 1146 case '\$negate': value = -val0; break; | 1146 case ':negate': value = -val0; break; |
| 1147 case '\$add': value = val0 + val1; break; | 1147 case ':add': value = val0 + val1; break; |
| 1148 case '\$sub': value = val0 - val1; break; | 1148 case ':sub': value = val0 - val1; break; |
| 1149 case '\$mul': value = val0 * val1; break; | 1149 case ':mul': value = val0 * val1; break; |
| 1150 case '\$div': value = val0 / val1; break; | 1150 case ':div': value = val0 / val1; break; |
| 1151 case '\$truncdiv': value = val0 ~/ val1; break; | 1151 case ':truncdiv': value = val0 ~/ val1; break; |
| 1152 case '\$mod': value = val0 % val1; break; | 1152 case ':mod': value = val0 % val1; break; |
| 1153 case '\$eq': value = val0 == val1; break; | 1153 case ':eq': value = val0 == val1; break; |
| 1154 case '\$lt': value = val0 < val1; break; | 1154 case ':lt': value = val0 < val1; break; |
| 1155 case '\$gt': value = val0 > val1; break; | 1155 case ':gt': value = val0 > val1; break; |
| 1156 case '\$lte': value = val0 <= val1; break; | 1156 case ':lte': value = val0 <= val1; break; |
| 1157 case '\$gte': value = val0 >= val1; break; | 1157 case ':gte': value = val0 >= val1; break; |
| 1158 case '\$ne': value = val0 != val1; break; | 1158 case ':ne': value = val0 != val1; break; |
| 1159 | 1159 |
| 1160 // Note: unfortunatelly bit operations fail on doubles in dartvm | 1160 // Note: unfortunatelly bit operations fail on doubles in dartvm |
| 1161 case '\$bit_not': value = (~ival0).toDouble(); break; | 1161 case ':bit_not': value = (~ival0).toDouble(); break; |
| 1162 case '\$bit_or': value = (ival0 | ival1).toDouble(); break; | 1162 case ':bit_or': value = (ival0 | ival1).toDouble(); break; |
| 1163 case '\$bit_xor': value = (ival0 ^ ival1).toDouble(); break; | 1163 case ':bit_xor': value = (ival0 ^ ival1).toDouble(); break; |
| 1164 case '\$bit_and': value = (ival0 & ival1).toDouble(); break; | 1164 case ':bit_and': value = (ival0 & ival1).toDouble(); break; |
| 1165 case '\$shl': value = (ival0 << ival1).toDouble(); break; | 1165 case ':shl': value = (ival0 << ival1).toDouble(); break; |
| 1166 case '\$sar': value = (ival0 >> ival1).toDouble(); break; | 1166 case ':sar': value = (ival0 >> ival1).toDouble(); break; |
| 1167 case '\$shr': value = (ival0 >>> ival1).toDouble(); break; | 1167 case ':shr': value = (ival0 >>> ival1).toDouble(); break; |
| 1168 } | 1168 } |
| 1169 return new EvaluatedValue(inferredResult, value, "$value", node.span); | 1169 return new EvaluatedValue(inferredResult, value, "$value", node.span); |
| 1170 } | 1170 } |
| 1171 } else if (declaringType.isString) { | 1171 } else if (declaringType.isString) { |
| 1172 if (name == '\$index') { | 1172 if (name == ':index') { |
| 1173 // Note: this could technically propagate constness, but that's not | 1173 // Note: this could technically propagate constness, but that's not |
| 1174 // specified explicitly and the VM doesn't do that. | 1174 // specified explicitly and the VM doesn't do that. |
| 1175 return new Value(declaringType, '${target.code}[${argsCode[0]}]', | 1175 return new Value(declaringType, '${target.code}[${argsCode[0]}]', |
| 1176 node.span); | 1176 node.span); |
| 1177 } else if (name == '\$add') { | 1177 } else if (name == ':add') { |
| 1178 if (allConst) { | 1178 if (allConst) { |
| 1179 final value = _normConcat(target, args.values[0]); | 1179 final value = _normConcat(target, args.values[0]); |
| 1180 return new EvaluatedValue(world.stringType, value, value, node.span); | 1180 return new EvaluatedValue(world.stringType, value, value, node.span); |
| 1181 } | 1181 } |
| 1182 | 1182 |
| 1183 // Ensure we generate toString on the right side | 1183 // Ensure we generate toString on the right side |
| 1184 return new Value(declaringType, '${target.code} + ${argsCode[0]}', | 1184 return new Value(declaringType, '${target.code} + ${argsCode[0]}', |
| 1185 node.span); | 1185 node.span); |
| 1186 } | 1186 } |
| 1187 } else if (declaringType.isNative) { | 1187 } else if (declaringType.isNative) { |
| 1188 if (name == '\$index') { | 1188 if (name == ':index') { |
| 1189 // Note: this could technically propagate constness, but that's not | 1189 // Note: this could technically propagate constness, but that's not |
| 1190 // specified explicitly and the VM doesn't do that. | 1190 // specified explicitly and the VM doesn't do that. |
| 1191 return new Value(returnType, '${target.code}[${argsCode[0]}]', node.span
); | 1191 return new Value(returnType, '${target.code}[${argsCode[0]}]', node.span
); |
| 1192 } else if (name == '\$setindex') { | 1192 } else if (name == ':setindex') { |
| 1193 return new Value(returnType, | 1193 return new Value(returnType, |
| 1194 '${target.code}[${argsCode[0]}] = ${argsCode[1]}', node.span); | 1194 '${target.code}[${argsCode[0]}] = ${argsCode[1]}', node.span); |
| 1195 } | 1195 } |
| 1196 } | 1196 } |
| 1197 | 1197 |
| 1198 // TODO(jimhug): Optimize null on lhs as well. | 1198 // TODO(jimhug): Optimize null on lhs as well. |
| 1199 if (name == '\$eq' || name == '\$ne') { | 1199 if (name == ':eq' || name == ':ne') { |
| 1200 final op = name == '\$eq' ? '==' : '!='; | 1200 final op = name == ':eq' ? '==' : '!='; |
| 1201 | 1201 |
| 1202 if (name == '\$ne') { | 1202 if (name == ':ne') { |
| 1203 // Ensure == is generated. | 1203 // Ensure == is generated. |
| 1204 target.invoke(context, '\$eq', node, args, isDynamic); | 1204 target.invoke(context, ':eq', node, args, isDynamic); |
| 1205 } | 1205 } |
| 1206 | 1206 |
| 1207 if (allConst) { | 1207 if (allConst) { |
| 1208 var val0 = target.dynamic.actualValue; | 1208 var val0 = target.dynamic.actualValue; |
| 1209 var val1 = args.values[0].dynamic.actualValue; | 1209 var val1 = args.values[0].dynamic.actualValue; |
| 1210 var newVal = name == '\$eq' ? val0 == val1 : val0 != val1; | 1210 var newVal = name == ':eq' ? val0 == val1 : val0 != val1; |
| 1211 return new EvaluatedValue(world.nonNullBool, | 1211 return new EvaluatedValue(world.nonNullBool, |
| 1212 newVal, "$newVal", node.span); | 1212 newVal, "$newVal", node.span); |
| 1213 } | 1213 } |
| 1214 // Optimize test when null is on the rhs. | 1214 // Optimize test when null is on the rhs. |
| 1215 if (argsCode[0] == 'null') { | 1215 if (argsCode[0] == 'null') { |
| 1216 return new Value(inferredResult, '${target.code} $op null', node.span); | 1216 return new Value(inferredResult, '${target.code} $op null', node.span); |
| 1217 } else if (target.type.isNum || target.type.isString) { | 1217 } else if (target.type.isNum || target.type.isString) { |
| 1218 // TODO(jimhug): Maybe check rhs. | 1218 // TODO(jimhug): Maybe check rhs. |
| 1219 return new Value(inferredResult, '${target.code} $op ${argsCode[0]}', | 1219 return new Value(inferredResult, '${target.code} $op ${argsCode[0]}', |
| 1220 node.span); | 1220 node.span); |
| 1221 } | 1221 } |
| 1222 world.gen.corejs.useOperator(name); | 1222 world.gen.corejs.useOperator(name); |
| 1223 return new Value(inferredResult, '$name(${target.code}, ${argsCode[0]})', | 1223 return new Value(inferredResult, |
| 1224 node.span); | 1224 '$jsname(${target.code}, ${argsCode[0]})', node.span); |
| 1225 } | 1225 } |
| 1226 | 1226 |
| 1227 if (isCallMethod) { | 1227 if (isCallMethod) { |
| 1228 declaringType.markUsed(); | 1228 declaringType.markUsed(); |
| 1229 return new Value(inferredResult, | 1229 return new Value(inferredResult, |
| 1230 '${target.code}(${Strings.join(argsCode, ", ")})', node.span); | 1230 '${target.code}(${Strings.join(argsCode, ", ")})', node.span); |
| 1231 } | 1231 } |
| 1232 | 1232 |
| 1233 if (name == '\$index') { | 1233 if (name == ':index') { |
| 1234 world.gen.corejs.useIndex = true; | 1234 world.gen.corejs.useIndex = true; |
| 1235 } else if (name == '\$setindex') { | 1235 } else if (name == ':setindex') { |
| 1236 world.gen.corejs.useSetIndex = true; | 1236 world.gen.corejs.useSetIndex = true; |
| 1237 } | 1237 } |
| 1238 | 1238 |
| 1239 // Fall back to normal method invocation. | 1239 // Fall back to normal method invocation. |
| 1240 var argsString = Strings.join(argsCode, ', '); | 1240 var argsString = Strings.join(argsCode, ', '); |
| 1241 return new Value(inferredResult, '${target.code}.$jsname($argsString)', | 1241 return new Value(inferredResult, '${target.code}.$jsname($argsString)', |
| 1242 node.span); | 1242 node.span); |
| 1243 } | 1243 } |
| 1244 | 1244 |
| 1245 /** | 1245 /** |
| (...skipping 286 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1532 // up with a bogus unused temp generated (usually "var $0"). We need a way | 1532 // up with a bogus unused temp generated (usually "var $0"). We need a way |
| 1533 // to throw away temps when we throw away the code. | 1533 // to throw away temps when we throw away the code. |
| 1534 returnValue = _tryUnion(returnValue, res, node); | 1534 returnValue = _tryUnion(returnValue, res, node); |
| 1535 } | 1535 } |
| 1536 | 1536 |
| 1537 if (returnValue == null) { | 1537 if (returnValue == null) { |
| 1538 return _makeError(node, target, 'method'); | 1538 return _makeError(node, target, 'method'); |
| 1539 } | 1539 } |
| 1540 | 1540 |
| 1541 if (returnValue.code == null) { | 1541 if (returnValue.code == null) { |
| 1542 if (name == '\$call') { | 1542 if (name == ':call') { |
| 1543 // TODO(jmesserly): reconcile this with similar code in Value | 1543 // TODO(jmesserly): reconcile this with similar code in Value |
| 1544 return target._varCall(context, args); | 1544 return target._varCall(context, args); |
| 1545 } else if (isOperator) { | 1545 } else if (isOperator) { |
| 1546 // TODO(jmesserly): make operators less special. | 1546 // TODO(jmesserly): make operators less special. |
| 1547 return target.invokeSpecial(name, args, returnValue.type); | 1547 return invokeSpecial(target, args, returnValue.type); |
| 1548 } else { | 1548 } else { |
| 1549 return invokeOnVar(context, node, target, args); | 1549 return invokeOnVar(context, node, target, args); |
| 1550 } | 1550 } |
| 1551 } | 1551 } |
| 1552 | 1552 |
| 1553 return returnValue; | 1553 return returnValue; |
| 1554 } | 1554 } |
| 1555 | 1555 |
| 1556 Value invokeSpecial(Value target, Arguments args, Type returnType) { |
| 1557 assert(name.startsWith(':')); |
| 1558 assert(!args.hasNames); |
| 1559 // TODO(jimhug): We need to do this a little bit more like get and set on |
| 1560 // properties. We should check the set of members for something |
| 1561 // like "requiresNativeIndexer" and "requiresDartIndexer" to |
| 1562 // decide on a strategy. |
| 1563 |
| 1564 var argsString = args.getCode(); |
| 1565 // Most operator calls need to be emitted as function calls, so we don't |
| 1566 // box numbers accidentally. Indexing is the exception. |
| 1567 if (name == ':index' || name == ':setindex') { |
| 1568 return new Value(returnType, '${target.code}.$jsname($argsString)', |
| 1569 target.span); |
| 1570 } else { |
| 1571 if (argsString.length > 0) argsString = ', $argsString'; |
| 1572 world.gen.corejs.useOperator(name); |
| 1573 return new Value(returnType, '$jsname(${target.code}$argsString)', |
| 1574 target.span); |
| 1575 } |
| 1576 } |
| 1577 |
| 1556 Value invokeOnVar(MethodGenerator context, Node node, Value target, | 1578 Value invokeOnVar(MethodGenerator context, Node node, Value target, |
| 1557 Arguments args) { | 1579 Arguments args) { |
| 1558 var member = getVarMember(context, node, args); | 1580 var member = getVarMember(context, node, args); |
| 1559 return member.invoke(context, node, target, args); | 1581 return member.invoke(context, node, target, args); |
| 1560 } | 1582 } |
| 1561 | 1583 |
| 1562 Value _union(Value x, Value y, Node node) { | 1584 Value _union(Value x, Value y, Node node) { |
| 1563 var result = _tryUnion(x, y, node); | 1585 var result = _tryUnion(x, y, node); |
| 1564 if (result.code == null) { | 1586 if (result.code == null) { |
| 1565 world.internalError('mismatched code for $name (${x.code}, ${y.code})', | 1587 world.internalError('mismatched code for $name (${x.code}, ${y.code})', |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1682 } | 1704 } |
| 1683 | 1705 |
| 1684 void forEach(void f(Member member)) { | 1706 void forEach(void f(Member member)) { |
| 1685 factories.forEach((_, Map constructors) { | 1707 factories.forEach((_, Map constructors) { |
| 1686 constructors.forEach((_, Member member) { | 1708 constructors.forEach((_, Member member) { |
| 1687 f(member); | 1709 f(member); |
| 1688 }); | 1710 }); |
| 1689 }); | 1711 }); |
| 1690 } | 1712 } |
| 1691 } | 1713 } |
| OLD | NEW |