Chromium Code Reviews| 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 10 matching lines...) Expand all Loading... | |
| 21 name = name.substring(5); | 21 name = name.substring(5); |
| 22 isInitializer = true; | 22 isInitializer = true; |
| 23 } | 23 } |
| 24 | 24 |
| 25 type = method.resolveType(definition.type, false); | 25 type = method.resolveType(definition.type, false); |
| 26 | 26 |
| 27 if (definition.value != null) { | 27 if (definition.value != null) { |
| 28 // To match VM, detect cases where value was not actually specified in | 28 // To match VM, detect cases where value was not actually specified in |
| 29 // code and don't signal errors. | 29 // code and don't signal errors. |
| 30 // TODO(jimhug): Clean up after issue #352 is resolved. | 30 // TODO(jimhug): Clean up after issue #352 is resolved. |
| 31 if (!hasDefaultValue) return; | 31 if (definition.value.span.start == definition.span.start) { |
|
Jennifer Messerly
2012/01/09 20:16:26
I think I originally suggested the property to mak
jimhug
2012/01/09 21:19:05
I believe that Bob is going to undo this change, s
| |
| 32 return; | |
| 33 } | |
| 32 | 34 |
| 33 if (method.name == ':call') { | 35 if (method.name == ':call') { |
| 34 // TODO(jimhug): Need simpler way to detect "true" function types vs. | 36 // TODO(jimhug): Need simpler way to detect "true" function types vs. |
| 35 // regular methods being used as function types for closures. | 37 // regular methods being used as function types for closures. |
| 36 // TODO(sigmund): Disallow non-null default values for native calls? | 38 // TODO(sigmund): Disallow non-null default values for native calls? |
| 37 if (method.definition.body == null && !method.isNative) { | 39 if (method.definition.body == null && !method.isNative) { |
| 38 world.error('default value not allowed on function type', | 40 world.error('default value not allowed on function type', |
| 39 definition.span); | 41 definition.span); |
| 40 } | 42 } |
| 41 } else if (method.isAbstract) { | 43 } else if (method.isAbstract) { |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 63 | 65 |
| 64 Parameter copyWithNewType(Member newMethod, Type newType) { | 66 Parameter copyWithNewType(Member newMethod, Type newType) { |
| 65 var ret = new Parameter(definition, newMethod); | 67 var ret = new Parameter(definition, newMethod); |
| 66 ret.type = newType; | 68 ret.type = newType; |
| 67 ret.name = name; | 69 ret.name = name; |
| 68 ret.isInitializer = isInitializer; | 70 ret.isInitializer = isInitializer; |
| 69 return ret; | 71 return ret; |
| 70 } | 72 } |
| 71 | 73 |
| 72 bool get isOptional() => definition != null && definition.value != null; | 74 bool get isOptional() => definition != null && definition.value != null; |
| 73 | |
| 74 /** | |
| 75 * Gets whether this named parameter has an explicit default value or relies | |
| 76 * on the implicit `null`. | |
| 77 */ | |
| 78 bool get hasDefaultValue() => definition.value is! NullExpression || | |
| 79 (definition.value.span.start != definition.span.start); | |
| 80 } | 75 } |
| 81 | 76 |
| 82 | 77 |
| 83 class Member extends Element { | 78 class Member extends Element { |
| 84 final Type declaringType; | 79 final Type declaringType; |
| 85 | 80 |
| 86 bool isGenerated; | 81 bool isGenerated; |
| 87 MethodGenerator generator; | 82 MethodGenerator generator; |
| 88 | 83 |
| 89 Member(String name, Type declaringType) | 84 Member(String name, Type declaringType) |
| (...skipping 1162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1252 return new EvaluatedValue(inferredResult, value, "$value", node.span); | 1247 return new EvaluatedValue(inferredResult, value, "$value", node.span); |
| 1253 } | 1248 } |
| 1254 } else if (declaringType.isString) { | 1249 } else if (declaringType.isString) { |
| 1255 if (name == ':index') { | 1250 if (name == ':index') { |
| 1256 // Note: this could technically propagate constness, but that's not | 1251 // Note: this could technically propagate constness, but that's not |
| 1257 // specified explicitly and the VM doesn't do that. | 1252 // specified explicitly and the VM doesn't do that. |
| 1258 return new Value(declaringType, '${target.code}[${argsCode[0]}]', | 1253 return new Value(declaringType, '${target.code}[${argsCode[0]}]', |
| 1259 node.span); | 1254 node.span); |
| 1260 } else if (name == ':add') { | 1255 } else if (name == ':add') { |
| 1261 if (allConst) { | 1256 if (allConst) { |
| 1262 final value = _normConcat(target, args.values[0]); | 1257 final value = target.dynamic.actualValue + |
| 1263 return new EvaluatedValue(world.stringType, value, value, node.span); | 1258 args.values[0].dynamic.actualValue; |
| 1259 return Value.fromString(value, node.span); | |
| 1264 } | 1260 } |
| 1265 | 1261 |
| 1266 // Ensure we generate toString on the right side | |
| 1267 return new Value(declaringType, '${target.code} + ${argsCode[0]}', | 1262 return new Value(declaringType, '${target.code} + ${argsCode[0]}', |
| 1268 node.span); | 1263 node.span); |
| 1269 } | 1264 } |
| 1270 } else if (declaringType.isNative) { | 1265 } else if (declaringType.isNative) { |
| 1271 if (name == ':index') { | 1266 if (name == ':index') { |
| 1272 // Note: this could technically propagate constness, but that's not | 1267 // Note: this could technically propagate constness, but that's not |
| 1273 // specified explicitly and the VM doesn't do that. | 1268 // specified explicitly and the VM doesn't do that. |
| 1274 return | 1269 return |
| 1275 new Value(returnType, '${target.code}[${argsCode[0]}]', node.span); | 1270 new Value(returnType, '${target.code}[${argsCode[0]}]', node.span); |
| 1276 } else if (name == ':setindex') { | 1271 } else if (name == ':setindex') { |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1319 } else if (name == ':setindex') { | 1314 } else if (name == ':setindex') { |
| 1320 world.gen.corejs.useSetIndex = true; | 1315 world.gen.corejs.useSetIndex = true; |
| 1321 } | 1316 } |
| 1322 | 1317 |
| 1323 // Fall back to normal method invocation. | 1318 // Fall back to normal method invocation. |
| 1324 var argsString = Strings.join(argsCode, ', '); | 1319 var argsString = Strings.join(argsCode, ', '); |
| 1325 return new Value(inferredResult, '${target.code}.$jsname($argsString)', | 1320 return new Value(inferredResult, '${target.code}.$jsname($argsString)', |
| 1326 node.span); | 1321 node.span); |
| 1327 } | 1322 } |
| 1328 | 1323 |
| 1329 /** | |
| 1330 * Return the string concatenation of two values, which is normalized to use | |
| 1331 * double-quotes if any of the input strings used double-quotes. | |
| 1332 */ | |
| 1333 String _normConcat(Value a, Value b) { | |
|
Jennifer Messerly
2012/01/09 20:16:26
yay
| |
| 1334 assert(b.type.isString); | |
| 1335 var val0 = a.dynamic.actualValue; | |
| 1336 var quote0 = val0[0]; | |
| 1337 val0 = val0.substring(1, val0.length - 1); | |
| 1338 var val1 = b.dynamic.actualValue; | |
| 1339 var quote1 = null; | |
| 1340 if (b.type.isString) { | |
| 1341 quote1 = val1[0]; | |
| 1342 val1 = val1.substring(1, val1.length - 1); | |
| 1343 } | |
| 1344 var value; | |
| 1345 if (quote0 == quote1 || quote1 == null) { | |
| 1346 // If both strings use the same quote, then keep using it. | |
| 1347 value = '$quote0${val0}${val1}$quote0'; | |
| 1348 } else if (quote0 == '"') { | |
| 1349 // If they are different, escape the single-quote to be double-quote | |
| 1350 // the choice of single vs double is arbitrary, but choosing one | |
| 1351 // ensures that we only do this escaping once on a string portion. | |
| 1352 assert(quote1 == "'"); | |
| 1353 value = '$quote0${val0}${toDoubleQuote(val1)}$quote0'; | |
| 1354 } else { | |
| 1355 assert(quote1 == '"'); | |
| 1356 value = '$quote1${toDoubleQuote(val0)}${val1}$quote1'; | |
| 1357 } | |
| 1358 return value; | |
| 1359 } | |
| 1360 | |
| 1361 resolve() { | 1324 resolve() { |
| 1362 // TODO(jimhug): cut-and-paste-and-edit from Field.resolve | 1325 // TODO(jimhug): cut-and-paste-and-edit from Field.resolve |
| 1363 isStatic = declaringType.isTop; | 1326 isStatic = declaringType.isTop; |
| 1364 isConst = false; | 1327 isConst = false; |
| 1365 isFactory = false; | 1328 isFactory = false; |
| 1366 isAbstract = !declaringType.isClass; | 1329 isAbstract = !declaringType.isClass; |
| 1367 if (definition.modifiers != null) { | 1330 if (definition.modifiers != null) { |
| 1368 for (var mod in definition.modifiers) { | 1331 for (var mod in definition.modifiers) { |
| 1369 if (mod.kind == TokenKind.STATIC) { | 1332 if (mod.kind == TokenKind.STATIC) { |
| 1370 if (isStatic) { | 1333 if (isStatic) { |
| (...skipping 406 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1777 } | 1740 } |
| 1778 | 1741 |
| 1779 void forEach(void f(Member member)) { | 1742 void forEach(void f(Member member)) { |
| 1780 factories.forEach((_, Map constructors) { | 1743 factories.forEach((_, Map constructors) { |
| 1781 constructors.forEach((_, Member member) { | 1744 constructors.forEach((_, Member member) { |
| 1782 f(member); | 1745 f(member); |
| 1783 }); | 1746 }); |
| 1784 }); | 1747 }); |
| 1785 } | 1748 } |
| 1786 } | 1749 } |
| OLD | NEW |