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

Side by Side Diff: frog/leg/resolver.dart

Issue 9616058: Implement parsing and resolving of type-variables. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Address comments. Created 8 years, 9 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 } 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
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
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
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
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
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698