Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(152)

Side by Side Diff: frog/member.dart

Issue 8540030: Fix dispatch on MemberSets to always go dynamic if needed. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 9 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « frog/frogsh ('k') | frog/type.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 8
9 String name; 9 String name;
10 Type type; 10 Type type;
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
113 bool get isField() => false; 113 bool get isField() => false;
114 bool get isMethod() => false; 114 bool get isMethod() => false;
115 bool get isProperty() => false; 115 bool get isProperty() => false;
116 bool get isAbstract() => false; 116 bool get isAbstract() => false;
117 117
118 // TODO(jmesserly): these only makes sense on methods, but because of 118 // TODO(jmesserly): these only makes sense on methods, but because of
119 // ConcreteMember we need to support them on Member. 119 // ConcreteMember we need to support them on Member.
120 bool get isConst() => false; 120 bool get isConst() => false;
121 bool get isFactory() => false; 121 bool get isFactory() => false;
122 122
123 bool get isOperator() => name.startsWith('\$');
124 bool get isCallMethod() => name == '\$call';
125
123 bool get prefersPropertySyntax() => true; 126 bool get prefersPropertySyntax() => true;
124 bool get requiresFieldSyntax() => false; 127 bool get requiresFieldSyntax() => false;
125 128
126 bool get isNative() => false; 129 bool get isNative() => false;
127 String get constructorName() { 130 String get constructorName() {
128 world.internalError('can not be a constructor', span); 131 world.internalError('can not be a constructor', span);
129 } 132 }
130 133
131 void provideFieldSyntax() => world.internalError('can not be field', span); 134 void provideFieldSyntax() => world.internalError('can not be field', span);
132 void providePropertySyntax() => 135 void providePropertySyntax() =>
(...skipping 787 matching lines...) Expand 10 before | Expand all | Expand 10 after
920 return _invokeConstructor(context, node, target, args, argsString); 923 return _invokeConstructor(context, node, target, args, argsString);
921 } 924 }
922 925
923 // TODO(jimhug): target really shouldn't ever be null... 926 // TODO(jimhug): target really shouldn't ever be null...
924 if (target != null && target.isSuper) { 927 if (target != null && target.isSuper) {
925 return new Value(inferredResult, 928 return new Value(inferredResult,
926 '${declaringType.jsname}.prototype.$jsname.call($argsString)', 929 '${declaringType.jsname}.prototype.$jsname.call($argsString)',
927 node.span); 930 node.span);
928 } 931 }
929 932
930 if (name.startsWith('\$')) { 933 if (isOperator) {
931 return _invokeBuiltin(context, node, target, args, argsCode, isDynamic); 934 return _invokeBuiltin(context, node, target, args, argsCode, isDynamic);
932 } 935 }
933 936
934 if (isFactory) { 937 if (isFactory) {
935 return new Value(inferredResult, '$generatedFactoryName($argsString)', 938 return new Value(inferredResult, '$generatedFactoryName($argsString)',
936 node.span); 939 node.span);
937 } 940 }
938 941
939 if (isStatic) { 942 if (isStatic) {
940 if (declaringType.isTop) { 943 if (declaringType.isTop) {
(...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after
1212 } else if (target.type.isNum || target.type.isString) { 1215 } else if (target.type.isNum || target.type.isString) {
1213 // TODO(jimhug): Maybe check rhs. 1216 // TODO(jimhug): Maybe check rhs.
1214 return new Value(inferredResult, '${target.code} $op ${argsCode[0]}', 1217 return new Value(inferredResult, '${target.code} $op ${argsCode[0]}',
1215 node.span); 1218 node.span);
1216 } 1219 }
1217 world.gen.corejs.useOperator(name); 1220 world.gen.corejs.useOperator(name);
1218 return new Value(inferredResult, '$name(${target.code}, ${argsCode[0]})', 1221 return new Value(inferredResult, '$name(${target.code}, ${argsCode[0]})',
1219 node.span); 1222 node.span);
1220 } 1223 }
1221 1224
1222 if (name == '\$call') { 1225 if (isCallMethod) {
1223 declaringType.markUsed(); 1226 declaringType.markUsed();
1224 return new Value(inferredResult, 1227 return new Value(inferredResult,
1225 '${target.code}(${Strings.join(argsCode, ", ")})', node.span); 1228 '${target.code}(${Strings.join(argsCode, ", ")})', node.span);
1226 } 1229 }
1227 1230
1228 if (name == '\$index') { 1231 if (name == '\$index') {
1229 world.gen.corejs.useIndex = true; 1232 world.gen.corejs.useIndex = true;
1230 } else if (name == '\$setindex') { 1233 } else if (name == '\$setindex') {
1231 world.gen.corejs.useSetIndex = true; 1234 world.gen.corejs.useSetIndex = true;
1232 } 1235 }
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
1275 world.error('${mod} modifier not allowed on method', mod.span); 1278 world.error('${mod} modifier not allowed on method', mod.span);
1276 } 1279 }
1277 } 1280 }
1278 } 1281 }
1279 1282
1280 if (isFactory) { 1283 if (isFactory) {
1281 isStatic = true; 1284 isStatic = true;
1282 } 1285 }
1283 1286
1284 // TODO(jimhug): need a better annotation for being an operator method 1287 // TODO(jimhug): need a better annotation for being an operator method
1285 if (name.startsWith('\$') && !name.startsWith('\$call') && isStatic) { 1288 if (isOperator && isStatic && !isCallMethod) {
1286 world.error('operator method may not be static "${name}"', span); 1289 world.error('operator method may not be static "${name}"', span);
1287 } 1290 }
1288 1291
1289 if (isAbstract) { 1292 if (isAbstract) {
1290 if (definition.body != null && 1293 if (definition.body != null &&
1291 declaringType.definition is! FunctionTypeDefinition) { 1294 declaringType.definition is! FunctionTypeDefinition) {
1292 // TODO(jimhug): Creating function types for concrete methods is 1295 // TODO(jimhug): Creating function types for concrete methods is
1293 // steadily feeling uglier... 1296 // steadily feeling uglier...
1294 world.error('abstract method can not have a body', span); 1297 world.error('abstract method can not have a body', span);
1295 } 1298 }
(...skipping 30 matching lines...) Expand all
1326 library._addMember(this); 1329 library._addMember(this);
1327 } 1330 }
1328 } 1331 }
1329 } 1332 }
1330 1333
1331 1334
1332 class MemberSet { 1335 class MemberSet {
1333 final String name; 1336 final String name;
1334 final List<Member> members; 1337 final List<Member> members;
1335 final String jsname; 1338 final String jsname;
1339 final bool isVar;
1336 1340
1337 MemberSet(Member member): 1341 MemberSet(Member member, [bool isVar=false]):
nweiz 2011/11/14 21:28:15 Does isVar also need to be set for the library-loc
1338 name = member.name, members = [member], jsname = member.jsname; 1342 name = member.name, members = [member], jsname = member.jsname,
1343 isVar = isVar;
1339 1344
1340 toString() => '$name:${members.length}'; 1345 toString() => '$name:${members.length}';
1341 1346
1342 // TODO(jimhug): Still working towards the right logic for conflicts... 1347 // TODO(jimhug): Still working towards the right logic for conflicts...
1343 bool get containsProperties() => members.some((m) => m is PropertyMember); 1348 bool get containsProperties() => members.some((m) => m is PropertyMember);
1344 bool get containsMethods() => members.some((m) => m is MethodMember); 1349 bool get containsMethods() => members.some((m) => m is MethodMember);
1345 1350
1351
1346 void add(Member member) => members.add(member); 1352 void add(Member member) => members.add(member);
1347 1353
1348 // TODO(jimhug): Always false, or is this needed? 1354 // TODO(jimhug): Always false, or is this needed?
1349 bool get isStatic() => members.length == 1 && members[0].isStatic; 1355 bool get isStatic() => members.length == 1 && members[0].isStatic;
1356 bool get isOperator() => members[0].isOperator;
1350 1357
1351 bool canInvoke(MethodGenerator context, Arguments args) => 1358 bool canInvoke(MethodGenerator context, Arguments args) =>
1352 members.some((m) => m.canInvoke(context, args)); 1359 members.some((m) => m.canInvoke(context, args));
1353 1360
1354 Value _makeError(Node node, Value target, String action) { 1361 Value _makeError(Node node, Value target, String action) {
1355 if (!target.type.isVar) { 1362 if (!target.type.isVar) {
1356 world.warning('could not find applicable $action for "$name"', node.span); 1363 world.warning('could not find applicable $action for "$name"', node.span);
1357 } 1364 }
1358 return new Value(world.varType, 1365 return new Value(world.varType,
1359 '${target.code}.$jsname() /*no applicable $action*/', node.span); 1366 '${target.code}.$jsname() /*no applicable $action*/', node.span);
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
1438 } else { 1445 } else {
1439 return new Value(returnValue.type, 1446 return new Value(returnValue.type,
1440 '${target.code}.set\$$jsname(${value.code})', node.span); 1447 '${target.code}.set\$$jsname(${value.code})', node.span);
1441 } 1448 }
1442 } 1449 }
1443 return returnValue; 1450 return returnValue;
1444 } 1451 }
1445 1452
1446 Value invoke(MethodGenerator context, Node node, Value target, 1453 Value invoke(MethodGenerator context, Node node, Value target,
1447 Arguments args, [bool isDynamic=false]) { 1454 Arguments args, [bool isDynamic=false]) {
1455 // If this is the global MemberSet from world, always bind dynamically.
1456 // Note: we need this for proper noSuchMethod and REPL behavior.
1457 if (isVar && !isOperator) {
1458 return invokeOnVar(context, node, target, args);
1459 }
1460
1448 if (members.length == 1) { 1461 if (members.length == 1) {
1449 return members[0].invoke(context, node, target, args, isDynamic); 1462 return members[0].invoke(context, node, target, args, isDynamic);
1450 } 1463 }
1451 final targets = members.filter((m) => m.canInvoke(context, args)); 1464 final targets = members.filter((m) => m.canInvoke(context, args));
1452 if (targets.length == 1) { 1465 if (targets.length == 1) {
1453 return targets[0].invoke(context, node, target, args, isDynamic); 1466 return targets[0].invoke(context, node, target, args, isDynamic);
1454 } 1467 }
1455 1468
1456 Value returnValue = null; 1469 Value returnValue = null;
1457 for (var member in targets) { 1470 for (var member in targets) {
1458 final res = member.invoke(context, node, target, args, isDynamic:true); 1471 final res = member.invoke(context, node, target, args, isDynamic:true);
1459 returnValue = _tryUnion(returnValue, res, node); 1472 returnValue = _tryUnion(returnValue, res, node);
1460 } 1473 }
1461 1474
1462 if (returnValue == null) { 1475 if (returnValue == null) {
1463 return _makeError(node, target, 'method'); 1476 return _makeError(node, target, 'method');
1464 } 1477 }
1465 1478
1466 // If we fail to unify the resulting code, implement as a var call.
1467 if (returnValue.code == null) { 1479 if (returnValue.code == null) {
1468 if (name.startsWith('\$')) { 1480 // TODO(jmesserly): make operators less special.
1481 if (isOperator) {
1469 return target.invokeSpecial(name, args, returnValue.type); 1482 return target.invokeSpecial(name, args, returnValue.type);
1470 } else { 1483 } else {
1471 return invokeOnVar(context, node, target, args); 1484 return invokeOnVar(context, node, target, args);
1472 } 1485 }
1473 } 1486 }
1474 1487
1475 return returnValue; 1488 return returnValue;
1476 } 1489 }
1477 1490
1478 Value invokeOnVar(MethodGenerator context, Node node, Value target, 1491 Value invokeOnVar(MethodGenerator context, Node node, Value target,
1479 Arguments args) { 1492 Arguments args) {
1480 return getVarMember(context, node, args).invoke(context, node, target, args) ; 1493 var member = getVarMember(context, node, args);
1494 return member.invoke(context, node, target, args);
1481 } 1495 }
1482 1496
1483 Value _union(Value x, Value y, Node node) { 1497 Value _union(Value x, Value y, Node node) {
1484 var result = _tryUnion(x, y, node); 1498 var result = _tryUnion(x, y, node);
1485 if (result.code == null) { 1499 if (result.code == null) {
1486 world.internalError('mismatched code for $name (${x.code}, ${y.code})', 1500 world.internalError('mismatched code for $name (${x.code}, ${y.code})',
1487 node.span); 1501 node.span);
1488 } 1502 }
1489 return result; 1503 return result;
1490 } 1504 }
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
1601 } 1615 }
1602 1616
1603 void forEach(void f(Member member)) { 1617 void forEach(void f(Member member)) {
1604 factories.forEach((_, Map constructors) { 1618 factories.forEach((_, Map constructors) {
1605 constructors.forEach((_, Member member) { 1619 constructors.forEach((_, Member member) {
1606 f(member); 1620 f(member);
1607 }); 1621 });
1608 }); 1622 });
1609 } 1623 }
1610 } 1624 }
OLDNEW
« no previous file with comments | « frog/frogsh ('k') | frog/type.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698