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

Side by Side Diff: lib/compiler/implementation/resolver.dart

Issue 10854158: Make selector registration in the resolver and code generator more explicit. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Address review comments. Created 8 years, 4 months 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
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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 interface TreeElements { 5 interface TreeElements {
6 Element operator[](Node node); 6 Element operator[](Node node);
7 Selector getSelector(Send send); 7 Selector getSelector(Send send);
8 Type getType(TypeAnnotation annotation); 8 Type getType(TypeAnnotation annotation);
9 } 9 }
10 10
(...skipping 431 matching lines...) Expand 10 before | Expand all | Expand 10 after
442 error(selector, MessageKind.CANNOT_RESOLVE, [name]); 442 error(selector, MessageKind.CANNOT_RESOLVE, [name]);
443 } else if (target.kind != ElementKind.FIELD) { 443 } else if (target.kind != ElementKind.FIELD) {
444 error(selector, MessageKind.NOT_A_FIELD, [name]); 444 error(selector, MessageKind.NOT_A_FIELD, [name]);
445 } else if (!target.isInstanceMember()) { 445 } else if (!target.isInstanceMember()) {
446 error(selector, MessageKind.INIT_STATIC_FIELD, [name]); 446 error(selector, MessageKind.INIT_STATIC_FIELD, [name]);
447 } 447 }
448 } else { 448 } else {
449 error(init, MessageKind.INVALID_RECEIVER_IN_INITIALIZER); 449 error(init, MessageKind.INVALID_RECEIVER_IN_INITIALIZER);
450 } 450 }
451 visitor.useElement(init, target); 451 visitor.useElement(init, target);
452 visitor.world.registerStaticUse(target);
452 // Check for duplicate initializers. 453 // Check for duplicate initializers.
453 if (initialized.containsKey(name)) { 454 if (initialized.containsKey(name)) {
454 error(init, MessageKind.DUPLICATE_INITIALIZER, [name]); 455 error(init, MessageKind.DUPLICATE_INITIALIZER, [name]);
455 warning(initialized[name], MessageKind.ALREADY_INITIALIZED, [name]); 456 warning(initialized[name], MessageKind.ALREADY_INITIALIZED, [name]);
456 } 457 }
457 initialized[name] = init; 458 initialized[name] = init;
458 // Resolve initializing value. 459 // Resolve initializing value.
459 visitor.visitInStaticContext(init.arguments.head); 460 visitor.visitInStaticContext(init.arguments.head);
460 } 461 }
461 462
462 Element resolveSuperOrThisForSend(FunctionElement constructor, 463 Element resolveSuperOrThisForSend(FunctionElement constructor,
463 FunctionExpression functionNode, 464 FunctionExpression functionNode,
464 Send call) { 465 Send call) {
465 // Resolve the selector and the arguments. 466 // Resolve the selector and the arguments.
466 ResolverTask resolver = visitor.compiler.resolver; 467 ResolverTask resolver = visitor.compiler.resolver;
467 visitor.inStaticContext(() { 468 visitor.inStaticContext(() {
468 visitor.resolveSelector(call); 469 visitor.resolveSelector(call);
469 visitor.visitArguments(call.argumentsNode); 470 visitor.resolveArguments(call.argumentsNode);
470 }); 471 });
471 Selector selector = visitor.mapping.getSelector(call); 472 Selector selector = visitor.mapping.getSelector(call);
472 bool isSuperCall = Initializers.isSuperConstructorCall(call); 473 bool isSuperCall = Initializers.isSuperConstructorCall(call);
473 SourceString constructorName = resolver.getConstructorName(call); 474 SourceString constructorName = resolver.getConstructorName(call);
474 Element result = resolveSuperOrThis( 475 Element result = resolveSuperOrThis(
475 constructor, isSuperCall, false, constructorName, selector, call); 476 constructor, isSuperCall, false, constructorName, selector, call);
476 visitor.useElement(call, result); 477 visitor.useElement(call, result);
478 visitor.world.registerStaticUse(result);
477 return result; 479 return result;
478 } 480 }
479 481
480 void resolveImplicitSuperConstructorSend(FunctionElement constructor, 482 void resolveImplicitSuperConstructorSend(FunctionElement constructor,
481 FunctionExpression functionNode) { 483 FunctionExpression functionNode) {
482 // If the class has a super resolve the implicit super call. 484 // If the class has a super resolve the implicit super call.
483 ClassElement classElement = constructor.getEnclosingClass(); 485 ClassElement classElement = constructor.getEnclosingClass();
484 ClassElement superClass = classElement.superclass; 486 ClassElement superClass = classElement.superclass;
485 if (classElement != visitor.compiler.objectClass) { 487 if (classElement != visitor.compiler.objectClass) {
486 assert(superClass !== null); 488 assert(superClass !== null);
(...skipping 468 matching lines...) Expand 10 before | Expand all | Expand 10 after
955 Element existing = scope.add(element); 957 Element existing = scope.add(element);
956 if (existing != element) { 958 if (existing != element) {
957 error(node, MessageKind.DUPLICATE_DEFINITION, [node]); 959 error(node, MessageKind.DUPLICATE_DEFINITION, [node]);
958 } 960 }
959 } 961 }
960 return element; 962 return element;
961 } 963 }
962 964
963 Element useElement(Node node, Element element) { 965 Element useElement(Node node, Element element) {
964 if (element === null) return null; 966 if (element === null) return null;
965 mapping[node] = element; 967 return mapping[node] = element;
floitsch 2012/08/16 11:49:53 I would prefer the assignment in a separate line.
966 if (element.isTopLevel() || element.isMember()) {
967 if (element.isInstanceMember()) {
968 var send = node.asSend();
969 if (send !== null) {
970 Selector selector = mapping.getSelector(send);
971 if (selector !== null) {
972 world.registerDynamicInvocation(element.name, selector);
973 }
974 }
975 } else {
976 if (!element.isPrefix() &&
977 !element.isClass() &&
978 !element.isTypedef() &&
979 !element.isTypeVariable()) {
980 world.registerStaticUse(element);
981 }
982 }
983 }
984 return element;
985 } 968 }
986 969
987 Type useType(TypeAnnotation annotation, Type type) { 970 Type useType(TypeAnnotation annotation, Type type) {
988 if (type !== null) { 971 if (type !== null) {
989 mapping.setType(annotation, type); 972 mapping.setType(annotation, type);
990 useElement(annotation, type.element); 973 useElement(annotation, type.element);
991 } 974 }
992 return type; 975 return type;
993 } 976 }
994 977
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after
1178 if (node === null) { 1161 if (node === null) {
1179 // node is of the form !Type. 1162 // node is of the form !Type.
1180 node = argument.asSend().receiver.asTypeAnnotation(); 1163 node = argument.asSend().receiver.asTypeAnnotation();
1181 if (node === null) compiler.cancel("malformed send"); 1164 if (node === null) compiler.cancel("malformed send");
1182 } 1165 }
1183 return resolveTypeRequired(node); 1166 return resolveTypeRequired(node);
1184 } 1167 }
1185 1168
1186 static Selector computeSendSelector(Send node, LibraryElement library) { 1169 static Selector computeSendSelector(Send node, LibraryElement library) {
1187 // First determine if this is part of an assignment. 1170 // First determine if this is part of an assignment.
1188 bool isSet = node is SendSet; 1171 bool isSet = node.asSendSet() !== null;
1189 1172
1190 if (node.isIndex) { 1173 if (node.isIndex) {
1191 return isSet ? new Selector.indexSet() : new Selector.index(); 1174 return isSet ? new Selector.indexSet() : new Selector.index();
1192 } 1175 }
1193 1176
1194 if (node.isOperator) { 1177 if (node.isOperator) {
1195 SourceString source = node.selector.asOperator().source; 1178 SourceString source = node.selector.asOperator().source;
1196 switch (source.stringValue) { 1179 String string = source.stringValue;
1197 case '!' : case '&&' : case '||': 1180 if (string === '!' || string === '&&' || string == '||' ||
1198 case 'is' : case 'as' : 1181 string === 'is' || string === 'as' ||
1199 case '===': case '!==': 1182 string === '===' || string === '!==' ||
1200 case '>>>': 1183 string === '>>>') {
1201 return null; 1184 return null;
1202 } 1185 }
1203 return node.arguments.isEmpty() 1186 return node.arguments.isEmpty()
1204 ? new Selector.unaryOperator(source) 1187 ? new Selector.unaryOperator(source)
1205 : new Selector.binaryOperator(source); 1188 : new Selector.binaryOperator(source);
1206 } 1189 }
1207 1190
1208 Identifier identifier = node.selector.asIdentifier(); 1191 Identifier identifier = node.selector.asIdentifier();
1209 if (node.isPropertyAccess) { 1192 if (node.isPropertyAccess) {
1210 assert(!isSet); 1193 assert(!isSet);
1211 return new Selector.getter(identifier.source, library); 1194 return new Selector.getter(identifier.source, library);
1212 } else if (isSet) { 1195 } else if (isSet) {
1213 return new Selector.setter(identifier.source, library); 1196 return new Selector.setter(identifier.source, library);
1214 } 1197 }
1215 1198
1216 // Compute the arity and the list of named arguments. 1199 // Compute the arity and the list of named arguments.
1217 int arity = 0; 1200 int arity = 0;
1218 List<SourceString> named = <SourceString>[]; 1201 List<SourceString> named = <SourceString>[];
1219 for (Link<Node> link = node.argumentsNode.nodes; 1202 for (Link<Node> link = node.argumentsNode.nodes;
1220 !link.isEmpty(); 1203 !link.isEmpty();
1221 link = link.tail) { 1204 link = link.tail) {
1222 Expression argument = link.head; 1205 Expression argument = link.head;
1223 if (argument.asNamedArgument() != null) { 1206 NamedArgument namedArgument = argument.asNamedArgument();
1224 named.add((argument as NamedArgument).name.source); 1207 if (namedArgument !== null) {
1208 named.add(namedArgument.name.source);
1225 } 1209 }
1226 arity++; 1210 arity++;
1227 } 1211 }
1228 1212
1229 // If we're invoking a closure, we do not have an identifier. In 1213 // If we're invoking a closure, we do not have an identifier.
1230 // that case, we create a wildcard selector that can call any 1214 return (identifier === null)
1231 // method that may have been closurized. 1215 ? new Selector.callClosure(arity, named)
1232 return (identifier == null)
1233 ? new Selector.callAny(arity, named)
1234 : new Selector.call(identifier.source, library, arity, named); 1216 : new Selector.call(identifier.source, library, arity, named);
1235 } 1217 }
1236 1218
1237 Selector resolveSelector(Send node) { 1219 Selector resolveSelector(Send node) {
1238 LibraryElement library = enclosingElement.getLibrary(); 1220 LibraryElement library = enclosingElement.getLibrary();
1239 Selector selector = computeSendSelector(node, library); 1221 Selector selector = computeSendSelector(node, library);
1240 if (selector != null) mapping.setSelector(node, selector); 1222 if (selector != null) mapping.setSelector(node, selector);
1241 return selector; 1223 return selector;
1242 } 1224 }
1243 1225
1244 void visitArguments(NodeList list) { 1226 void resolveArguments(NodeList list) {
1227 if (list === null) return;
1245 bool seenNamedArgument = false; 1228 bool seenNamedArgument = false;
1246 for (Link<Node> link = list.nodes; !link.isEmpty(); link = link.tail) { 1229 for (Link<Node> link = list.nodes; !link.isEmpty(); link = link.tail) {
1247 Expression argument = link.head; 1230 Expression argument = link.head;
1248 visit(argument); 1231 visit(argument);
1249 if (argument.asNamedArgument() != null) { 1232 if (argument.asNamedArgument() != null) {
1250 seenNamedArgument = true; 1233 seenNamedArgument = true;
1251 } else if (seenNamedArgument) { 1234 } else if (seenNamedArgument) {
1252 error(argument, MessageKind.INVALID_ARGUMENT_AFTER_NAMED); 1235 error(argument, MessageKind.INVALID_ARGUMENT_AFTER_NAMED);
1253 } 1236 }
1254 } 1237 }
1255 } 1238 }
1256 1239
1257 visitSend(Send node) { 1240 visitSend(Send node) {
1258 Element target = resolveSend(node); 1241 Element target = resolveSend(node);
1259 if (node.isOperator) {
1260 Operator op = node.selector.asOperator();
1261 if (op.source.stringValue === 'is' || op.source.stringValue === 'as') {
1262 resolveTypeTest(node.arguments.head);
1263 assert(node.arguments.tail.isEmpty());
1264 } else if (node.arguments.isEmpty()) {
1265 assert(op.token.kind !== PLUS_TOKEN);
1266 } else {
1267 visit(node.argumentsNode);
1268 }
1269 } else if (node.isIndex) {
1270 visit(node.argumentsNode);
1271 assert(node.arguments.tail.isEmpty());
1272 } else if (node.isPropertyAccess) {
1273 // Nothing to do here.
1274 } else {
1275 visitArguments(node.argumentsNode);
1276 }
1277
1278 if (target != null && target.kind == ElementKind.ABSTRACT_FIELD) { 1242 if (target != null && target.kind == ElementKind.ABSTRACT_FIELD) {
1279 AbstractFieldElement field = target; 1243 AbstractFieldElement field = target;
1280 target = field.getter; 1244 target = field.getter;
1281 } 1245 }
1246
1247 bool resolvedArguments = false;
1248 if (node.isOperator) {
ahe 2012/08/16 12:09:54 You could write something like this: if (node.isO
1249 String operatorString = node.selector.asOperator().source.stringValue;
1250 if (operatorString === 'is' || operatorString === 'as') {
1251 assert(node.arguments.tail.isEmpty());
1252 resolveTypeTest(node.arguments.head);
1253 resolvedArguments = true;
1254 }
1255 }
1256
1257 if (!resolvedArguments) {
1258 resolveArguments(node.argumentsNode);
1259 }
1260
1261 // If the selector is null, it means that we will not be generating
1262 // code for this as a send.
1263 Selector selector = mapping.getSelector(node);
1264 if (selector === null) return;
1265
1266 // If we don't know what we're calling or if we are calling a getter,
1267 // we need to register that fact that we may be calling a closure
1268 // with the same arguments.
1282 if (node.isCall && 1269 if (node.isCall &&
1283 (target === null || 1270 (target === null ||
1284 target.isGetter() || 1271 target.isGetter() ||
1285 Elements.isClosureSend(node, target))) { 1272 Elements.isClosureSend(node, target))) {
1286 Selector selector = mapping.getSelector(node); 1273 Selector call = new Selector.callClosureFrom(selector);
1287 Selector call = new Selector.call( 1274 world.registerDynamicInvocation(call.name, call);
1288 compiler.namer.CLOSURE_INVOCATION_NAME,
1289 selector.library,
1290 selector.argumentCount,
1291 selector.namedArguments);
1292 world.registerDynamicInvocation(compiler.namer.CLOSURE_INVOCATION_NAME,
1293 call);
1294 } 1275 }
1276
1295 // TODO(ngeoffray): We should do the check in 1277 // TODO(ngeoffray): We should do the check in
1296 // visitExpressionStatement instead. 1278 // visitExpressionStatement instead.
1297 if (target === compiler.assertMethod && !node.isCall) { 1279 if (target === compiler.assertMethod && !node.isCall) {
1298 // We can only use assert by calling it. 1280 // We can only use assert by calling it.
1299 if (!inInstanceContext) { 1281 if (!inInstanceContext) {
1300 error(node, MessageKind.MISSING_ARGUMENTS_TO_ASSERT, [node]); 1282 error(node, MessageKind.MISSING_ARGUMENTS_TO_ASSERT, [node]);
1301 } 1283 }
1302 target = null; 1284 target = null;
1303 } 1285 }
1286
1304 // TODO(ngeoffray): Warn if target is null and the send is 1287 // TODO(ngeoffray): Warn if target is null and the send is
1305 // unqualified. 1288 // unqualified.
1306 useElement(node, target); 1289 useElement(node, target);
1307 if (target === null) registerDynamicSend(node); 1290 registerSend(selector, target);
1308 if (node.isPropertyAccess) return target; 1291 return node.isPropertyAccess ? target : null;
1309 } 1292 }
1310 1293
1311 visitSendSet(SendSet node) { 1294 visitSendSet(SendSet node) {
1312 Element target = resolveSend(node); 1295 Element target = resolveSend(node);
1313 Element setter = null; 1296 Element setter = target;
1314 Element getter = null; 1297 Element getter = target;
1315 if (target != null && target.kind == ElementKind.ABSTRACT_FIELD) { 1298 if (target != null && target.kind == ElementKind.ABSTRACT_FIELD) {
1316 AbstractFieldElement field = target; 1299 AbstractFieldElement field = target;
1317 setter = field.setter; 1300 setter = field.setter;
1318 getter = field.getter; 1301 getter = field.getter;
1319 } else {
1320 setter = target;
1321 getter = target;
1322 } 1302 }
1303
1304 visit(node.argumentsNode);
1305
1323 // TODO(ngeoffray): Check if the target can be assigned. 1306 // TODO(ngeoffray): Check if the target can be assigned.
1324 Identifier identifier = node.assignmentOperator;
1325 bool compoundAssignment = identifier.source.stringValue !== '=';
1326 if (compoundAssignment) {
1327 useElement(node.selector, getter);
1328 }
1329 visit(node.argumentsNode);
1330 // TODO(ngeoffray): Warn if target is null and the send is 1307 // TODO(ngeoffray): Warn if target is null and the send is
1331 // unqualified. 1308 // unqualified.
1332 registerDynamicSend(node); 1309
1310 Selector selector = mapping.getSelector(node);
1311 Identifier identifier = node.assignmentOperator;
1312 bool isCompound = identifier.source.stringValue !== '=';
ahe 2012/08/16 12:09:54 isCompound is not entirely correct as this also is
1313 if (isCompound) {
1314 if (selector.isSetter()) {
1315 useElement(node.selector, getter);
1316 registerSend(new Selector.getterFrom(selector), getter);
1317 } else {
1318 // TODO(kasperl): If [getter] is resolved, it will actually
1319 // refer to the []= operator which isn't the one we want to
1320 // register here. We should consider using some notation of
ahe 2012/08/16 12:09:54 Great idea.
1321 // abstract indexable element that we can resolve to so we can
1322 // distinguish the two.
1323 assert(selector.isIndexSet());
1324 registerSend(new Selector.index(), null);
1325 }
1326 }
1327
1328 registerSend(selector, setter);
1333 return useElement(node, setter); 1329 return useElement(node, setter);
1334 } 1330 }
1335 1331
1336 registerDynamicSend(Send node) { 1332 void registerSend(Selector selector, Element target) {
1337 Identifier id = node.selector.asIdentifier(); 1333 if (target === null || target.isInstanceMember()) {
1338 if (id === null) return; 1334 if (selector.isGetter()) {
1339 SourceString name = node.selector.asIdentifier().source; 1335 world.registerDynamicGetter(selector.name, selector);
1340 if (node.isIndex && node is SendSet) { 1336 } else if (selector.isSetter()) {
1341 name = Elements.constructOperatorName( 1337 world.registerDynamicSetter(selector.name, selector);
1342 const SourceString('operator'), 1338 } else {
1343 const SourceString('[]=')); 1339 world.registerDynamicInvocation(selector.name, selector);
1344 } else if (node.selector.asOperator() != null) {
1345 switch (name.stringValue) {
1346 case '===':
1347 case '!==':
1348 case '!':
1349 case '&&':
1350 case '||':
1351 case 'is':
1352 case 'as':
1353 case '>>>':
1354 return null;
1355 } 1340 }
1356 name = Elements.constructOperatorName( 1341 } else if (Elements.isStaticOrTopLevel(target)) {
1357 const SourceString('operator'), 1342 // TODO(kasperl): It seems like we're not supposed to register
1358 name, 1343 // the use of classes. Wouldn't it be simpler if we just did?
ahe 2012/08/16 12:09:54 I'm not so sure about that. There is a difference
1359 node.argumentsNode is Prefix); 1344 if (!target.isClass()) world.registerStaticUse(target);
1360 } 1345 }
1361 Selector selector = mapping.getSelector(node); 1346
1362 if (selector.isGetter()) { 1347 // TODO(kasperl): Pass the selector directly.
1363 world.registerDynamicGetter(name, selector);
1364 } else if (selector.isSetter()) {
1365 world.registerDynamicSetter(name, selector);
1366 // Also register the getter for compound assignments.
1367 LibraryElement library = enclosingElement.getLibrary();
1368 Selector getter = new Selector.getter(name, library);
1369 world.registerDynamicGetter(name, getter);
1370 } else {
1371 if (selector.isIndexSet()) {
1372 // Also register the index selector for compound assignments.
1373 Selector index = new Selector.index();
1374 world.registerDynamicInvocation(index.name, index);
1375 }
1376 world.registerDynamicInvocation(name, selector);
1377 }
1378 var interceptor = new Interceptors(compiler).getStaticInterceptor( 1348 var interceptor = new Interceptors(compiler).getStaticInterceptor(
1379 name, 1349 selector.name,
1380 node.argumentCount()); 1350 selector.argumentCount);
1381 if (interceptor !== null) { 1351 if (interceptor !== null) {
1382 world.registerStaticUse(interceptor); 1352 world.registerStaticUse(interceptor);
1383 } 1353 }
1384 } 1354 }
1385 1355
1386 visitLiteralInt(LiteralInt node) { 1356 visitLiteralInt(LiteralInt node) {
1387 } 1357 }
1388 1358
1389 visitLiteralDouble(LiteralDouble node) { 1359 visitLiteralDouble(LiteralDouble node) {
1390 } 1360 }
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
1435 1405
1436 visitParenthesizedExpression(ParenthesizedExpression node) { 1406 visitParenthesizedExpression(ParenthesizedExpression node) {
1437 visit(node.expression); 1407 visit(node.expression);
1438 } 1408 }
1439 1409
1440 visitNewExpression(NewExpression node) { 1410 visitNewExpression(NewExpression node) {
1441 Node selector = node.send.selector; 1411 Node selector = node.send.selector;
1442 1412
1443 FunctionElement constructor = resolveConstructor(node); 1413 FunctionElement constructor = resolveConstructor(node);
1444 resolveSelector(node.send); 1414 resolveSelector(node.send);
1445 visitArguments(node.send.argumentsNode); 1415 resolveArguments(node.send.argumentsNode);
1446 if (constructor === null) return null; 1416 if (constructor === null) return null;
1447 // TODO(karlklose): handle optional arguments. 1417 // TODO(karlklose): handle optional arguments.
1448 if (node.send.argumentCount() != constructor.parameterCount(compiler)) { 1418 if (node.send.argumentCount() != constructor.parameterCount(compiler)) {
1449 // TODO(ngeoffray): resolution error with wrong number of 1419 // TODO(ngeoffray): resolution error with wrong number of
1450 // parameters. We cannot do this rigth now because of the 1420 // parameters. We cannot do this rigth now because of the
1451 // List constructor. 1421 // List constructor.
1452 } 1422 }
1453 useElement(node.send, constructor); 1423 useElement(node.send, constructor);
1424 world.registerStaticUse(constructor);
1454 compiler.withCurrentElement(constructor, () { 1425 compiler.withCurrentElement(constructor, () {
1455 FunctionExpression tree = constructor.parseNode(compiler); 1426 FunctionExpression tree = constructor.parseNode(compiler);
1456 compiler.resolver.resolveConstructorImplementation(constructor, tree); 1427 compiler.resolver.resolveConstructorImplementation(constructor, tree);
1457 }); 1428 });
1458 world.registerStaticUse(constructor.defaultImplementation); 1429 world.registerStaticUse(constructor.defaultImplementation);
1459 ClassElement cls = constructor.defaultImplementation.getEnclosingClass(); 1430 ClassElement cls = constructor.defaultImplementation.getEnclosingClass();
1460 world.registerInstantiatedClass(cls); 1431 world.registerInstantiatedClass(cls);
1461 cls.forEachInstanceField( 1432 cls.forEachInstanceField(
1462 includeBackendMembers: false, 1433 includeBackendMembers: false,
1463 includeSuperMembers: true, 1434 includeSuperMembers: true,
(...skipping 995 matching lines...) Expand 10 before | Expand all | Expand 10 after
2459 TopScope(LibraryElement library) : super(null, library); 2430 TopScope(LibraryElement library) : super(null, library);
2460 Element lookup(SourceString name) { 2431 Element lookup(SourceString name) {
2461 return library.find(name); 2432 return library.find(name);
2462 } 2433 }
2463 2434
2464 Element add(Element newElement) { 2435 Element add(Element newElement) {
2465 throw "Cannot add an element in the top scope"; 2436 throw "Cannot add an element in the top scope";
2466 } 2437 }
2467 String toString() => '$element'; 2438 String toString() => '$element';
2468 } 2439 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698