Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 } | 8 } |
| 9 | 9 |
| 10 class TreeElementMapping implements TreeElements { | 10 class TreeElementMapping implements TreeElements { |
| (...skipping 392 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 403 compiler.internalError(message, node: node); | 403 compiler.internalError(message, node: node); |
| 404 } | 404 } |
| 405 | 405 |
| 406 void unimplemented(Node node, String message) { | 406 void unimplemented(Node node, String message) { |
| 407 compiler.unimplemented(message, node: node); | 407 compiler.unimplemented(message, node: node); |
| 408 } | 408 } |
| 409 } | 409 } |
| 410 | 410 |
| 411 interface LabelScope { | 411 interface LabelScope { |
| 412 LabelScope get outer(); | 412 LabelScope get outer(); |
| 413 LabelElement lookup(String label); | 413 LabelElement lookup(String label, [bool inStaticContext]); |
|
ngeoffray
2012/03/15 11:47:40
Why would labels care about a static context?
karlklose
2012/03/16 14:58:47
Done, removed all the static context booleans.
| |
| 414 } | 414 } |
| 415 | 415 |
| 416 class LabeledStatementLabelScope implements LabelScope { | 416 class LabeledStatementLabelScope implements LabelScope { |
| 417 final LabelScope outer; | 417 final LabelScope outer; |
| 418 final LabelElement label; | 418 final LabelElement label; |
| 419 LabeledStatementLabelScope(this.outer, this.label); | 419 LabeledStatementLabelScope(this.outer, this.label); |
| 420 LabelElement lookup(String labelName) { | 420 LabelElement lookup(String labelName, [bool inStaticContext = false]) { |
| 421 if (this.label.labelName == labelName) return label; | 421 if (this.label.labelName == labelName) return label; |
| 422 return outer.lookup(labelName); | 422 return outer.lookup(labelName, inStaticContext); |
| 423 } | 423 } |
| 424 } | 424 } |
| 425 | 425 |
| 426 class SwitchLabelScope implements LabelScope { | 426 class SwitchLabelScope implements LabelScope { |
| 427 final LabelScope outer; | 427 final LabelScope outer; |
| 428 final Map<String, LabelElement> caseLabels; | 428 final Map<String, LabelElement> caseLabels; |
| 429 | 429 |
| 430 SwitchLabelScope(this.outer, this.caseLabels); | 430 SwitchLabelScope(this.outer, this.caseLabels); |
| 431 | 431 |
| 432 LabelElement lookup(String labelName) { | 432 LabelElement lookup(String labelName, [bool inStaticContext = false]) { |
| 433 LabelElement result = caseLabels[labelName]; | 433 LabelElement result = caseLabels[labelName]; |
| 434 if (result !== null) return result; | 434 if (result !== null) return result; |
| 435 return outer.lookup(labelName); | 435 return outer.lookup(labelName, inStaticContext); |
| 436 } | 436 } |
| 437 } | 437 } |
| 438 | 438 |
| 439 class EmptyLabelScope implements LabelScope { | 439 class EmptyLabelScope implements LabelScope { |
| 440 const EmptyLabelScope(); | 440 const EmptyLabelScope(); |
| 441 LabelElement lookup(String label) => null; | 441 LabelElement lookup(String label, [bool inStaticContext = false]) => null; |
| 442 LabelScope get outer() { | 442 LabelScope get outer() { |
| 443 throw 'internal error: empty label scope has no outer'; | 443 throw 'internal error: empty label scope has no outer'; |
| 444 } | 444 } |
| 445 } | 445 } |
| 446 | 446 |
| 447 class StatementScope { | 447 class StatementScope { |
| 448 LabelScope labels; | 448 LabelScope labels; |
| 449 Link<TargetElement> breakTargetStack; | 449 Link<TargetElement> breakTargetStack; |
| 450 Link<TargetElement> continueTargetStack; | 450 Link<TargetElement> continueTargetStack; |
| 451 // Used to provide different numbers to statements if one is inside the other. | 451 // Used to provide different numbers to statements if one is inside the other. |
| 452 // Can be used to make otherwise duplicate labels unique. | 452 // Can be used to make otherwise duplicate labels unique. |
| 453 int nestingLevel = 0; | 453 int nestingLevel = 0; |
| 454 | 454 |
| 455 StatementScope() | 455 StatementScope() |
| 456 : labels = const EmptyLabelScope(), | 456 : labels = const EmptyLabelScope(), |
| 457 breakTargetStack = const EmptyLink<TargetElement>(), | 457 breakTargetStack = const EmptyLink<TargetElement>(), |
| 458 continueTargetStack = const EmptyLink<TargetElement>(); | 458 continueTargetStack = const EmptyLink<TargetElement>(); |
| 459 | 459 |
| 460 LabelElement lookupLabel(String label) => | 460 LabelElement lookupLabel(String label, [bool inStaticContext = false]) { |
| 461 labels.lookup(label); | 461 return labels.lookup(label, inStaticContext); |
| 462 | 462 } |
| 463 TargetElement currentBreakTarget() => | 463 TargetElement currentBreakTarget() => |
| 464 breakTargetStack.isEmpty() ? null : breakTargetStack.head; | 464 breakTargetStack.isEmpty() ? null : breakTargetStack.head; |
| 465 | 465 |
| 466 TargetElement currentContinueTarget() => | 466 TargetElement currentContinueTarget() => |
| 467 continueTargetStack.isEmpty() ? null : continueTargetStack.head; | 467 continueTargetStack.isEmpty() ? null : continueTargetStack.head; |
| 468 | 468 |
| 469 void enterLabelScope(LabelElement element) { | 469 void enterLabelScope(LabelElement element) { |
| 470 labels = new LabeledStatementLabelScope(labels, element); | 470 labels = new LabeledStatementLabelScope(labels, element); |
| 471 nestingLevel++; | 471 nestingLevel++; |
| 472 } | 472 } |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 518 inInstanceContext = element.isInstanceMember() | 518 inInstanceContext = element.isInstanceMember() |
| 519 || element.isGenerativeConstructor(), | 519 || element.isGenerativeConstructor(), |
| 520 this.context = element.isMember() | 520 this.context = element.isMember() |
| 521 ? new ClassScope(element.enclosingElement, element.getLibrary()) | 521 ? new ClassScope(element.enclosingElement, element.getLibrary()) |
| 522 : new TopScope(element.getLibrary()), | 522 : new TopScope(element.getLibrary()), |
| 523 this.currentClass = element.isMember() ? element.enclosingElement : null, | 523 this.currentClass = element.isMember() ? element.enclosingElement : null, |
| 524 this.statementScope = new StatementScope(), | 524 this.statementScope = new StatementScope(), |
| 525 super(compiler); | 525 super(compiler); |
| 526 | 526 |
| 527 Element lookup(Node node, SourceString name) { | 527 Element lookup(Node node, SourceString name) { |
| 528 Element result = context.lookup(name); | 528 Element result = context.lookup(name, !inInstanceContext); |
| 529 if (!inInstanceContext && result != null && result.isInstanceMember()) { | 529 if (!inInstanceContext && result != null && result.isInstanceMember()) { |
| 530 error(node, MessageKind.NO_INSTANCE_AVAILABLE, [node]); | 530 error(node, MessageKind.NO_INSTANCE_AVAILABLE, [node]); |
| 531 } | 531 } |
| 532 return result; | 532 return result; |
| 533 } | 533 } |
| 534 | 534 |
| 535 // Create, or reuse an already created, statement element for a statement. | 535 // Create, or reuse an already created, statement element for a statement. |
| 536 TargetElement getOrCreateTargetElement(Node statement) { | 536 TargetElement getOrCreateTargetElement(Node statement) { |
| 537 TargetElement element = mapping[statement]; | 537 TargetElement element = mapping[statement]; |
| 538 if (element === null) { | 538 if (element === null) { |
| 539 element = new TargetElement(statement, | 539 element = new TargetElement(statement, |
| 540 statementScope.nestingLevel, | 540 statementScope.nestingLevel, |
| 541 enclosingElement); | 541 enclosingElement); |
| 542 mapping[statement] = element; | 542 mapping[statement] = element; |
| 543 } | 543 } |
| 544 return element; | 544 return element; |
| 545 } | 545 } |
| 546 | 546 |
| 547 inStaticContext(action()) { | 547 inStaticContext(action()) { |
| 548 bool wasInstanceContext = inInstanceContext; | 548 bool wasInstanceContext = inInstanceContext; |
| 549 inInstanceContext = false; | 549 inInstanceContext = false; |
| 550 action(); | 550 var result = action(); |
| 551 inInstanceContext = wasInstanceContext; | 551 inInstanceContext = wasInstanceContext; |
| 552 return result; | |
| 552 } | 553 } |
| 553 | 554 |
| 554 visitInStaticContext(Node node) { | 555 visitInStaticContext(Node node) { |
| 555 inStaticContext(() => visit(node)); | 556 inStaticContext(() => visit(node)); |
| 556 } | 557 } |
| 557 | 558 |
| 558 Element visitIdentifier(Identifier node) { | 559 Element visitIdentifier(Identifier node) { |
| 559 if (node.isThis()) { | 560 if (node.isThis()) { |
| 560 if (!inInstanceContext) { | 561 if (!inInstanceContext) { |
| 561 error(node, MessageKind.NO_INSTANCE_AVAILABLE, [node]); | 562 error(node, MessageKind.NO_INSTANCE_AVAILABLE, [node]); |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 586 if (node.typeName.asSend() !== null) { | 587 if (node.typeName.asSend() !== null) { |
| 587 // In new and const expressions, the type name can be a Send to | 588 // In new and const expressions, the type name can be a Send to |
| 588 // denote named constructors or library prefixes. | 589 // denote named constructors or library prefixes. |
| 589 Send send = node.typeName.asSend(); | 590 Send send = node.typeName.asSend(); |
| 590 className = send.receiver.asIdentifier().source; | 591 className = send.receiver.asIdentifier().source; |
| 591 } else { | 592 } else { |
| 592 className = node.typeName.asIdentifier().source; | 593 className = node.typeName.asIdentifier().source; |
| 593 } | 594 } |
| 594 if (className == const SourceString('var')) return null; | 595 if (className == const SourceString('var')) return null; |
| 595 if (className == const SourceString('void')) return null; | 596 if (className == const SourceString('void')) return null; |
| 596 Element element = context.lookup(className); | 597 Element element = context.lookup(className, !inInstanceContext); |
| 597 if (element === null) { | 598 if (element === null) { |
| 598 if (typeRequired) { | 599 if (typeRequired) { |
| 599 error(node, MessageKind.CANNOT_RESOLVE_TYPE, [className]); | 600 error(node, MessageKind.CANNOT_RESOLVE_TYPE, [className]); |
| 600 } else { | 601 } else { |
| 601 warning(node, MessageKind.CANNOT_RESOLVE_TYPE, [className]); | 602 warning(node, MessageKind.CANNOT_RESOLVE_TYPE, [className]); |
| 602 } | 603 } |
| 603 } else if (!element.impliesType()) { | 604 } else if (!element.impliesType()) { |
| 604 if (typeRequired) { | 605 if (typeRequired) { |
| 605 error(node, MessageKind.NOT_A_TYPE, [className]); | 606 error(node, MessageKind.NOT_A_TYPE, [className]); |
| 606 } else { | 607 } else { |
| (...skipping 342 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 949 // TODO(ngeoffray): resolution error with wrong number of | 950 // TODO(ngeoffray): resolution error with wrong number of |
| 950 // parameters. We cannot do this rigth now because of the | 951 // parameters. We cannot do this rigth now because of the |
| 951 // List constructor. | 952 // List constructor. |
| 952 } | 953 } |
| 953 useElement(node.send, constructor); | 954 useElement(node.send, constructor); |
| 954 return null; | 955 return null; |
| 955 } | 956 } |
| 956 | 957 |
| 957 FunctionElement resolveConstructor(NewExpression node) { | 958 FunctionElement resolveConstructor(NewExpression node) { |
| 958 FunctionElement constructor = | 959 FunctionElement constructor = |
| 959 node.accept(new ConstructorResolver(compiler, this)); | 960 node.accept(new ConstructorResolver(compiler, this)); |
| 960 if (constructor === null) { | 961 if (constructor === null) { |
| 961 error(node.send, MessageKind.CANNOT_FIND_CONSTRUCTOR, [node.send]); | 962 Element resolved = resolveTypeRequired(node.send.selector); |
| 963 if (resolved !== null && resolved.kind === ElementKind.TYPE_VARIABLE) { | |
| 964 error(node, WarningKind.TYPE_VARIABLE_AS_CONSTRUCTOR); | |
| 965 return null; | |
| 966 } else { | |
| 967 error(node.send, MessageKind.CANNOT_FIND_CONSTRUCTOR, [node.send]); | |
| 968 } | |
| 962 } | 969 } |
| 963 return constructor; | 970 return constructor; |
| 964 } | 971 } |
| 965 | 972 |
| 966 Element resolveTypeRequired(Node node) { | 973 Element resolveTypeRequired(Node node) { |
| 967 bool old = typeRequired; | 974 bool old = typeRequired; |
| 968 typeRequired = true; | 975 typeRequired = true; |
| 969 Element element = visit(node); | 976 Element element = visit(node); |
| 970 typeRequired = old; | 977 typeRequired = old; |
| 971 return element; | 978 return element; |
| (...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1189 visitIn(node.block, scope); | 1196 visitIn(node.block, scope); |
| 1190 } | 1197 } |
| 1191 | 1198 |
| 1192 visitTypedef(Typedef node) { | 1199 visitTypedef(Typedef node) { |
| 1193 unimplemented(node, 'typedef'); | 1200 unimplemented(node, 'typedef'); |
| 1194 } | 1201 } |
| 1195 } | 1202 } |
| 1196 | 1203 |
| 1197 class ClassResolverVisitor extends CommonResolverVisitor<Type> { | 1204 class ClassResolverVisitor extends CommonResolverVisitor<Type> { |
| 1198 Scope context; | 1205 Scope context; |
| 1206 ClassElement classElement; | |
| 1199 | 1207 |
| 1200 ClassResolverVisitor(Compiler compiler, LibraryElement library) | 1208 ClassResolverVisitor(Compiler compiler, LibraryElement library) |
| 1201 : context = new TopScope(library), | 1209 : context = new TopScope(library), |
| 1202 super(compiler); | 1210 super(compiler); |
| 1203 | 1211 |
| 1204 Type visitClassNode(ClassNode node) { | 1212 Type visitClassNode(ClassNode node) { |
| 1205 ClassElement element = context.lookup(node.name.source); | 1213 classElement = context.lookup(node.name.source); |
| 1206 compiler.ensure(element !== null); | 1214 compiler.ensure(classElement !== null); |
| 1207 compiler.ensure(!element.isResolved); | 1215 compiler.ensure(!classElement.isResolved); |
| 1208 element.supertype = visit(node.superclass); | 1216 final Link<TypeVariable> parameters = |
| 1209 if (element.name != Types.OBJECT && element.supertype === null) { | 1217 node.typeParameters !== null ? node.typeParameters.nodes |
| 1218 : const EmptyLink<TypeVariable>(); | |
| 1219 // Create types and elements for type variable. | |
| 1220 for (Link<TypeVariable> link = parameters; | |
| 1221 !link.isEmpty(); | |
| 1222 link = link.tail) { | |
| 1223 TypeVariable typeNode = link.head; | |
| 1224 SourceString variableName = typeNode.name.source; | |
| 1225 TypeVariableType variableType = new TypeVariableType(variableName); | |
| 1226 TypeVariableElement variableElement = | |
| 1227 new TypeVariableElement(variableName, classElement, node, | |
| 1228 variableType); | |
| 1229 variableType.element = variableElement; | |
| 1230 classElement.typeParameters[variableName] = variableElement; | |
| 1231 context = new TypeVariableScope(context, variableElement); | |
| 1232 } | |
| 1233 // Resolve the bounds of type variables. | |
| 1234 for (Link<TypeVariable> link = parameters; | |
| 1235 !link.isEmpty(); | |
| 1236 link = link.tail) { | |
| 1237 TypeVariable typeNode = link.head; | |
| 1238 SourceString variableName = typeNode.name.source; | |
| 1239 TypeVariableElement variableElement = | |
| 1240 classElement.typeParameters[variableName]; | |
| 1241 if (typeNode.bound !== null) { | |
| 1242 Type boundType = visit(typeNode.bound); | |
| 1243 if (boundType !== null && boundType.element == variableElement) { | |
| 1244 warning(node, MessageKind.CYCLIC_TYPE_VARIABLE, | |
| 1245 [variableElement.name]); | |
| 1246 } else if (boundType !== null) { | |
| 1247 variableElement.bound = boundType; | |
| 1248 } else { | |
| 1249 variableElement.bound = compiler.objectClass.computeType(compiler); | |
| 1250 } | |
| 1251 } | |
| 1252 } | |
| 1253 // Find super type. | |
| 1254 Type supertype = visit(node.superclass); | |
| 1255 if (supertype !== null && supertype.element.impliesType()) { | |
| 1256 classElement.supertype = supertype; | |
| 1257 } else if (supertype !== null) { | |
| 1258 error(node.superclass, MessageKind.TYPE_NAME_EXPECTED); | |
| 1259 } | |
| 1260 if (classElement.name != Types.OBJECT && classElement.supertype === null) { | |
| 1210 ClassElement objectElement = context.lookup(Types.OBJECT); | 1261 ClassElement objectElement = context.lookup(Types.OBJECT); |
| 1211 if (objectElement !== null && !objectElement.isResolved) { | 1262 if (objectElement !== null && !objectElement.isResolved) { |
| 1212 compiler.resolver.toResolve.add(objectElement); | 1263 compiler.resolver.toResolve.add(objectElement); |
| 1213 } else if (objectElement === null){ | 1264 } else if (objectElement === null){ |
| 1214 error(node, MessageKind.CANNOT_RESOLVE_TYPE, [Types.OBJECT]); | 1265 error(node, MessageKind.CANNOT_RESOLVE_TYPE, [Types.OBJECT]); |
| 1215 } | 1266 } |
| 1216 element.supertype = new SimpleType(Types.OBJECT, objectElement); | 1267 classElement.supertype = new SimpleType(Types.OBJECT, objectElement); |
| 1217 } | 1268 } |
| 1218 if (node.defaultClause !== null) { | 1269 if (node.defaultClause !== null) { |
| 1219 element.defaultClass = visit(node.defaultClause.nodes.head); | 1270 classElement.defaultClass = visit(node.defaultClause); |
| 1220 } | 1271 } |
| 1221 for (Link<Node> link = node.interfaces.nodes; | 1272 for (Link<Node> link = node.interfaces.nodes; |
| 1222 !link.isEmpty(); | 1273 !link.isEmpty(); |
| 1223 link = link.tail) { | 1274 link = link.tail) { |
| 1224 element.interfaces = element.interfaces.prepend(visit(link.head)); | 1275 Type interfaceType = visit(link.head); |
| 1276 if (interfaceType !== null && interfaceType.element.impliesType()) { | |
|
ngeoffray
2012/03/15 11:47:40
IMO interfaceType.element.impliesType should alway
karlklose
2012/03/16 14:58:47
It could be a type variable, which is illegal.
| |
| 1277 classElement.interfaces = | |
| 1278 classElement.interfaces.prepend(interfaceType); | |
| 1279 } else { | |
| 1280 error(link.head, MessageKind.TYPE_NAME_EXPECTED); | |
| 1281 } | |
| 1225 } | 1282 } |
| 1226 calculateAllSupertypes(element, new Set<ClassElement>()); | 1283 calculateAllSupertypes(classElement, new Set<ClassElement>()); |
| 1227 addDefaultConstructorIfNeeded(element); | 1284 addDefaultConstructorIfNeeded(classElement); |
| 1228 return element.computeType(compiler); | 1285 return classElement.computeType(compiler); |
| 1229 } | 1286 } |
| 1230 | 1287 |
| 1231 Type visitTypeAnnotation(TypeAnnotation node) { | 1288 Type visitTypeAnnotation(TypeAnnotation node) { |
| 1232 return visit(node.typeName); | 1289 return visit(node.typeName); |
| 1233 } | 1290 } |
| 1234 | 1291 |
| 1292 Type visitTypeVariable(TypeVariable node) { | |
|
ngeoffray
2012/03/15 11:47:40
Is that really necessary? And it's not obvious tha
karlklose
2012/03/16 14:58:47
Done, removed.
| |
| 1293 if (node.bound === null) { | |
| 1294 return compiler.objectClass; | |
| 1295 } | |
| 1296 return visit(node.bound); | |
| 1297 } | |
| 1298 | |
| 1235 Type visitIdentifier(Identifier node) { | 1299 Type visitIdentifier(Identifier node) { |
| 1236 Element element = context.lookup(node.source); | 1300 Element element = context.lookup(node.source); |
| 1237 if (element === null) { | 1301 if (element === null) { |
| 1238 error(node, MessageKind.CANNOT_RESOLVE_TYPE, [node]); | 1302 error(node, MessageKind.CANNOT_RESOLVE_TYPE, [node]); |
| 1239 } else if (!element.impliesType()) { | 1303 return null; |
| 1304 } else if (!element.impliesType() && !element.isTypeVariable()) { | |
| 1240 error(node, MessageKind.NOT_A_TYPE, [node]); | 1305 error(node, MessageKind.NOT_A_TYPE, [node]); |
| 1306 return null; | |
| 1241 } else { | 1307 } else { |
| 1242 if (element.isClass()) { | 1308 if (element.isClass()) { |
| 1243 compiler.resolver.toResolve.add(element); | 1309 compiler.resolver.toResolve.add(element); |
| 1244 } | 1310 } |
| 1245 // TODO(ngeoffray): Use type variables. | 1311 if (element.isTypeVariable()) { |
| 1246 return element.computeType(compiler); | 1312 TypeVariableElement variableElement = element; |
| 1313 return variableElement.type; | |
| 1314 } else if (element.isTypedef()) { | |
| 1315 compiler.unimplemented('visitIdentifier for typedefs'); | |
| 1316 } else { | |
| 1317 // TODO(ngeoffray): Use type variables. | |
|
ngeoffray
2012/03/15 11:47:40
I believe you can remove this TODO now.
karlklose
2012/03/16 14:58:47
Done.
| |
| 1318 return element.computeType(compiler); | |
| 1319 } | |
| 1247 } | 1320 } |
| 1248 return null; | 1321 return null; |
| 1249 } | 1322 } |
| 1250 | 1323 |
| 1251 Type visitSend(Send node) { | 1324 Type visitSend(Send node) { |
| 1252 Identifier prefix = node.receiver.asIdentifier(); | 1325 Identifier prefix = node.receiver.asIdentifier(); |
| 1253 if (prefix === null) { | 1326 if (prefix === null) { |
| 1254 error(node.receiver, MessageKind.NOT_A_PREFIX, [node.receiver]); | 1327 error(node.receiver, MessageKind.NOT_A_PREFIX, [node.receiver]); |
| 1255 return null; | 1328 return null; |
| 1256 } | 1329 } |
| (...skipping 348 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1605 | 1678 |
| 1606 class Scope { | 1679 class Scope { |
| 1607 final Element element; | 1680 final Element element; |
| 1608 final Scope parent; | 1681 final Scope parent; |
| 1609 | 1682 |
| 1610 Scope(this.parent, this.element); | 1683 Scope(this.parent, this.element); |
| 1611 abstract Element add(Element element); | 1684 abstract Element add(Element element); |
| 1612 abstract Element lookup(SourceString name); | 1685 abstract Element lookup(SourceString name); |
| 1613 } | 1686 } |
| 1614 | 1687 |
| 1688 class TypeVariableScope extends Scope { | |
| 1689 TypeVariableScope(parent, element) : super(parent, element); | |
| 1690 Element add(Element element) { | |
| 1691 throw "Cannot add element to TypeVariableScope"; | |
| 1692 } | |
| 1693 Element lookup(SourceString name, [bool inStaticContext = false]) { | |
| 1694 if (!inStaticContext && name == element.name) { | |
|
ahe
2012/03/15 11:17:33
I don't believe this is correct. The scope should
karlklose
2012/03/16 14:58:47
Done, removed.
| |
| 1695 return element; | |
| 1696 } | |
| 1697 if (parent !== null) return parent.lookup(name); | |
| 1698 } | |
| 1699 } | |
| 1700 | |
| 1615 class MethodScope extends Scope { | 1701 class MethodScope extends Scope { |
| 1616 final Map<SourceString, Element> elements; | 1702 final Map<SourceString, Element> elements; |
| 1617 | 1703 |
| 1618 MethodScope(Scope parent, Element element) | 1704 MethodScope(Scope parent, Element element) |
| 1619 : super(parent, element), this.elements = new Map<SourceString, Element>(); | 1705 : super(parent, element), this.elements = new Map<SourceString, Element>(); |
| 1620 | 1706 |
| 1621 Element lookup(SourceString name) { | 1707 Element lookup(SourceString name, [bool inStaticContext = false]) { |
| 1622 Element element = elements[name]; | 1708 Element element = elements[name]; |
| 1623 if (element !== null) return element; | 1709 if (element !== null) return element; |
| 1624 return parent.lookup(name); | 1710 return parent.lookup(name, inStaticContext); |
| 1625 } | 1711 } |
| 1626 | 1712 |
| 1627 Element add(Element element) { | 1713 Element add(Element element) { |
| 1628 if (elements.containsKey(element.name)) return elements[element.name]; | 1714 if (elements.containsKey(element.name)) return elements[element.name]; |
| 1629 elements[element.name] = element; | 1715 elements[element.name] = element; |
| 1630 return element; | 1716 return element; |
| 1631 } | 1717 } |
| 1632 } | 1718 } |
| 1633 | 1719 |
| 1634 class BlockScope extends MethodScope { | 1720 class BlockScope extends MethodScope { |
| 1635 BlockScope(Scope parent) : super(parent, parent.element); | 1721 BlockScope(Scope parent) : super(parent, parent.element); |
| 1636 } | 1722 } |
| 1637 | 1723 |
| 1638 class ClassScope extends Scope { | 1724 class ClassScope extends Scope { |
| 1639 ClassScope(ClassElement element, LibraryElement library) | 1725 ClassScope(ClassElement element, LibraryElement library) |
| 1640 : super(new TopScope(library), element); | 1726 : super(new TopScope(library), element); |
| 1641 | 1727 |
| 1642 Element lookup(SourceString name) { | 1728 Element lookup(SourceString name, [bool inStaticContext = false]) { |
| 1643 ClassElement cls = element; | 1729 ClassElement cls = element; |
| 1644 Element memberElement = cls.lookupLocalMember(name); | 1730 Element result = cls.lookupLocalMember(name); |
| 1645 if (memberElement != null) return memberElement; | 1731 if (result !== null) return result; |
| 1646 memberElement = parent.lookup(name); | 1732 if (!inStaticContext) { |
| 1647 if (memberElement != null) return memberElement; | 1733 result = cls.lookupTypeParameter(name); |
| 1734 } | |
| 1735 result = parent.lookup(name); | |
| 1736 if (result != null) return result; | |
| 1648 return cls.lookupSuperMember(name); | 1737 return cls.lookupSuperMember(name); |
| 1649 } | 1738 } |
| 1650 | 1739 |
| 1651 Element add(Element element) { | 1740 Element add(Element element) { |
| 1652 throw "Cannot add an element in a class scope"; | 1741 throw "Cannot add an element in a class scope"; |
| 1653 } | 1742 } |
| 1654 } | 1743 } |
| 1655 | 1744 |
| 1656 class TopScope extends Scope { | 1745 class TopScope extends Scope { |
| 1657 LibraryElement get library() => element; | 1746 LibraryElement get library() => element; |
| 1658 | 1747 |
| 1659 TopScope(LibraryElement library) : super(null, library); | 1748 TopScope(LibraryElement library) : super(null, library); |
| 1660 Element lookup(SourceString name) => library.find(name); | 1749 Element lookup(SourceString name, [bool inStaticContext = false]) { |
| 1750 return library.find(name); | |
| 1751 } | |
| 1661 | 1752 |
| 1662 Element add(Element element) { | 1753 Element add(Element element) { |
| 1663 throw "Cannot add an element in the top scope"; | 1754 throw "Cannot add an element in the top scope"; |
| 1664 } | 1755 } |
| 1665 } | 1756 } |
| OLD | NEW |