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 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 193 visitor.visit(send.arguments.head); | 193 visitor.visit(send.arguments.head); |
| 194 } | 194 } |
| 195 return visitor.mapping; | 195 return visitor.mapping; |
| 196 } | 196 } |
| 197 | 197 |
| 198 Type resolveType(ClassElement element) { | 198 Type resolveType(ClassElement element) { |
| 199 if (element.isResolved) return element.type; | 199 if (element.isResolved) return element.type; |
| 200 return measure(() { | 200 return measure(() { |
| 201 ClassNode tree = element.parseNode(compiler); | 201 ClassNode tree = element.parseNode(compiler); |
| 202 ClassResolverVisitor visitor = | 202 ClassResolverVisitor visitor = |
| 203 new ClassResolverVisitor(compiler, element.getLibrary()); | 203 new ClassResolverVisitor(compiler, element.getLibrary(), element); |
| 204 visitor.visit(tree); | 204 visitor.visit(tree); |
| 205 element.isResolved = true; | 205 element.isResolved = true; |
| 206 return element.type; | 206 return element.type; |
| 207 }); | 207 }); |
| 208 } | 208 } |
| 209 | 209 |
| 210 FunctionParameters resolveSignature(FunctionElement element) { | 210 FunctionParameters resolveSignature(FunctionElement element) { |
| 211 return measure(() => SignatureResolver.analyze(compiler, element)); | 211 return measure(() => SignatureResolver.analyze(compiler, element)); |
| 212 } | 212 } |
| 213 | 213 |
| (...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 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) { |
| 461 labels.lookup(label); | 461 return labels.lookup(label); |
|
ngeoffray
2012/03/18 13:40:57
Why this change?
| |
| 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 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 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 387 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, |
| 1209 ClassElement this.classElement) | |
| 1201 : context = new TopScope(library), | 1210 : context = new TopScope(library), |
| 1202 super(compiler); | 1211 super(compiler); |
| 1203 | 1212 |
| 1204 Type visitClassNode(ClassNode node) { | 1213 Type visitClassNode(ClassNode node) { |
| 1205 ClassElement element = context.lookup(node.name.source); | 1214 compiler.ensure(classElement !== null); |
| 1206 compiler.ensure(element !== null); | 1215 compiler.ensure(!classElement.isResolved); |
| 1207 compiler.ensure(!element.isResolved); | 1216 final Link<TypeVariable> parameters = |
| 1208 element.supertype = visit(node.superclass); | 1217 node.typeParameters !== null ? node.typeParameters.nodes |
| 1209 if (element.name != Types.OBJECT && element.supertype === null) { | 1218 : const EmptyLink<TypeVariable>(); |
| 1219 // Create types and elements for type variable. | |
|
ngeoffray
2012/03/18 13:40:57
Please explain why you are doing two loops instead
| |
| 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 TypeVariablesScope(context, classElement); | |
|
ahe
2012/03/16 15:29:21
Move out of loop.
| |
| 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); |
|
ahe
2012/03/16 15:29:21
I would like if this was objectElement.type.
| |
| 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/18 13:40:57
A type parameter should imply a type. I think Pete
| |
| 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 |
| 1235 Type visitIdentifier(Identifier node) { | 1292 Type visitIdentifier(Identifier node) { |
| 1236 Element element = context.lookup(node.source); | 1293 Element element = context.lookup(node.source); |
| 1237 if (element === null) { | 1294 if (element === null) { |
| 1238 error(node, MessageKind.CANNOT_RESOLVE_TYPE, [node]); | 1295 error(node, MessageKind.CANNOT_RESOLVE_TYPE, [node]); |
| 1239 } else if (!element.impliesType()) { | 1296 return null; |
| 1297 } else if (!element.impliesType() && !element.isTypeVariable()) { | |
| 1240 error(node, MessageKind.NOT_A_TYPE, [node]); | 1298 error(node, MessageKind.NOT_A_TYPE, [node]); |
| 1299 return null; | |
| 1241 } else { | 1300 } else { |
| 1242 if (element.isClass()) { | 1301 if (element.isClass()) { |
| 1243 compiler.resolver.toResolve.add(element); | 1302 compiler.resolver.toResolve.add(element); |
| 1244 } | 1303 } |
| 1245 // TODO(ngeoffray): Use type variables. | 1304 if (element.isTypeVariable()) { |
| 1246 return element.computeType(compiler); | 1305 TypeVariableElement variableElement = element; |
| 1306 return variableElement.type; | |
| 1307 } else if (element.isTypedef()) { | |
| 1308 compiler.unimplemented('visitIdentifier for typedefs'); | |
| 1309 } else { | |
| 1310 // TODO(ngeoffray): Use type variables. | |
| 1311 return element.computeType(compiler); | |
| 1312 } | |
| 1247 } | 1313 } |
| 1248 return null; | 1314 return null; |
| 1249 } | 1315 } |
| 1250 | 1316 |
| 1251 Type visitSend(Send node) { | 1317 Type visitSend(Send node) { |
| 1252 Identifier prefix = node.receiver.asIdentifier(); | 1318 Identifier prefix = node.receiver.asIdentifier(); |
| 1253 if (prefix === null) { | 1319 if (prefix === null) { |
| 1254 error(node.receiver, MessageKind.NOT_A_PREFIX, [node.receiver]); | 1320 error(node.receiver, MessageKind.NOT_A_PREFIX, [node.receiver]); |
| 1255 return null; | 1321 return null; |
| 1256 } | 1322 } |
| (...skipping 348 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1605 | 1671 |
| 1606 class Scope { | 1672 class Scope { |
| 1607 final Element element; | 1673 final Element element; |
| 1608 final Scope parent; | 1674 final Scope parent; |
| 1609 | 1675 |
| 1610 Scope(this.parent, this.element); | 1676 Scope(this.parent, this.element); |
| 1611 abstract Element add(Element element); | 1677 abstract Element add(Element element); |
| 1612 abstract Element lookup(SourceString name); | 1678 abstract Element lookup(SourceString name); |
| 1613 } | 1679 } |
| 1614 | 1680 |
| 1681 class TypeVariablesScope extends Scope { | |
|
ngeoffray
2012/03/18 13:40:57
I'm not sure why you need to create a special scop
| |
| 1682 TypeVariablesScope(parent, ClassElement element) : super(parent, element); | |
|
ngeoffray
2012/03/18 13:40:57
Scope parent
| |
| 1683 Element add(Element element) { | |
| 1684 throw "Cannot add element to TypeVariableScope"; | |
| 1685 } | |
| 1686 Element lookup(SourceString name) { | |
| 1687 ClassElement cls = element; | |
| 1688 Element result = cls.lookupTypeParameter(name); | |
| 1689 if (result !== null) return result; | |
| 1690 if (parent !== null) return parent.lookup(name); | |
| 1691 } | |
| 1692 } | |
| 1693 | |
| 1615 class MethodScope extends Scope { | 1694 class MethodScope extends Scope { |
| 1616 final Map<SourceString, Element> elements; | 1695 final Map<SourceString, Element> elements; |
| 1617 | 1696 |
| 1618 MethodScope(Scope parent, Element element) | 1697 MethodScope(Scope parent, Element element) |
| 1619 : super(parent, element), this.elements = new Map<SourceString, Element>(); | 1698 : super(parent, element), this.elements = new Map<SourceString, Element>(); |
| 1620 | 1699 |
| 1621 Element lookup(SourceString name) { | 1700 Element lookup(SourceString name) { |
| 1622 Element element = elements[name]; | 1701 Element element = elements[name]; |
| 1623 if (element !== null) return element; | 1702 if (element !== null) return element; |
| 1624 return parent.lookup(name); | 1703 return parent.lookup(name); |
| 1625 } | 1704 } |
| 1626 | 1705 |
| 1627 Element add(Element element) { | 1706 Element add(Element element) { |
| 1628 if (elements.containsKey(element.name)) return elements[element.name]; | 1707 if (elements.containsKey(element.name)) return elements[element.name]; |
| 1629 elements[element.name] = element; | 1708 elements[element.name] = element; |
| 1630 return element; | 1709 return element; |
| 1631 } | 1710 } |
| 1632 } | 1711 } |
| 1633 | 1712 |
| 1634 class BlockScope extends MethodScope { | 1713 class BlockScope extends MethodScope { |
| 1635 BlockScope(Scope parent) : super(parent, parent.element); | 1714 BlockScope(Scope parent) : super(parent, parent.element); |
| 1636 } | 1715 } |
| 1637 | 1716 |
| 1638 class ClassScope extends Scope { | 1717 class ClassScope extends Scope { |
| 1639 ClassScope(ClassElement element, LibraryElement library) | 1718 ClassScope(ClassElement element, LibraryElement library) |
| 1640 : super(new TopScope(library), element); | 1719 : super(new TopScope(library), element); |
| 1641 | 1720 |
| 1642 Element lookup(SourceString name) { | 1721 Element lookup(SourceString name) { |
| 1643 ClassElement cls = element; | 1722 ClassElement cls = element; |
| 1644 Element memberElement = cls.lookupLocalMember(name); | 1723 Element result = cls.lookupLocalMember(name); |
| 1645 if (memberElement != null) return memberElement; | 1724 if (result !== null) return result; |
| 1646 memberElement = parent.lookup(name); | 1725 result = cls.lookupTypeParameter(name); |
| 1647 if (memberElement != null) return memberElement; | 1726 if (result !== null) return result; |
| 1727 result = parent.lookup(name); | |
| 1728 if (result != null) return result; | |
| 1648 return cls.lookupSuperMember(name); | 1729 return cls.lookupSuperMember(name); |
| 1649 } | 1730 } |
| 1650 | 1731 |
| 1651 Element add(Element element) { | 1732 Element add(Element element) { |
| 1652 throw "Cannot add an element in a class scope"; | 1733 throw "Cannot add an element in a class scope"; |
| 1653 } | 1734 } |
| 1654 } | 1735 } |
| 1655 | 1736 |
| 1656 class TopScope extends Scope { | 1737 class TopScope extends Scope { |
| 1657 LibraryElement get library() => element; | 1738 LibraryElement get library() => element; |
| 1658 | 1739 |
| 1659 TopScope(LibraryElement library) : super(null, library); | 1740 TopScope(LibraryElement library) : super(null, library); |
| 1660 Element lookup(SourceString name) => library.find(name); | 1741 Element lookup(SourceString name) { |
| 1742 return library.find(name); | |
|
ngeoffray
2012/03/18 13:40:57
Why this change?
| |
| 1743 } | |
| 1661 | 1744 |
| 1662 Element add(Element element) { | 1745 Element add(Element element) { |
| 1663 throw "Cannot add an element in the top scope"; | 1746 throw "Cannot add an element in the top scope"; |
| 1664 } | 1747 } |
| 1665 } | 1748 } |
| OLD | NEW |