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

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

Issue 10915083: Change assert implementation to not depend on a top-level function called 'assert'. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Moved assert detection further down. Now demetered. Created 8 years, 3 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 DartType getType(TypeAnnotation annotation); 8 DartType getType(TypeAnnotation annotation);
9 bool isParameterChecked(Element element); 9 bool isParameterChecked(Element element);
10 } 10 }
(...skipping 936 matching lines...) Expand 10 before | Expand all | Expand 10 after
947 } 947 }
948 } 948 }
949 949
950 class ResolverVisitor extends CommonResolverVisitor<Element> { 950 class ResolverVisitor extends CommonResolverVisitor<Element> {
951 final TreeElementMapping mapping; 951 final TreeElementMapping mapping;
952 final Element enclosingElement; 952 final Element enclosingElement;
953 final TypeResolver typeResolver; 953 final TypeResolver typeResolver;
954 bool inInstanceContext; 954 bool inInstanceContext;
955 Scope scope; 955 Scope scope;
956 ClassElement currentClass; 956 ClassElement currentClass;
957 ExpressionStatement currentExpressionStatement;
957 bool typeRequired = false; 958 bool typeRequired = false;
958 StatementScope statementScope; 959 StatementScope statementScope;
959 int allowedCategory = ElementCategory.VARIABLE | ElementCategory.FUNCTION; 960 int allowedCategory = ElementCategory.VARIABLE | ElementCategory.FUNCTION;
960 961
961 ResolverVisitor(Compiler compiler, Element element) 962 ResolverVisitor(Compiler compiler, Element element)
962 : this.mapping = new TreeElementMapping(), 963 : this.mapping = new TreeElementMapping(),
963 this.enclosingElement = element, 964 this.enclosingElement = element,
964 // When the element is a field, we are actually resolving its 965 // When the element is a field, we are actually resolving its
965 // initial value, which should not have access to instance 966 // initial value, which should not have access to instance
966 // fields. 967 // fields.
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after
1131 } 1132 }
1132 1133
1133 visitDoWhile(DoWhile node) { 1134 visitDoWhile(DoWhile node) {
1134 visitLoopBodyIn(node, node.body, new BlockScope(scope)); 1135 visitLoopBodyIn(node, node.body, new BlockScope(scope));
1135 visit(node.condition); 1136 visit(node.condition);
1136 } 1137 }
1137 1138
1138 visitEmptyStatement(EmptyStatement node) { } 1139 visitEmptyStatement(EmptyStatement node) { }
1139 1140
1140 visitExpressionStatement(ExpressionStatement node) { 1141 visitExpressionStatement(ExpressionStatement node) {
1142 ExpressionStatement oldExpressionStatement = currentExpressionStatement;
1143 currentExpressionStatement = node;
1141 visit(node.expression); 1144 visit(node.expression);
1145 currentExpressionStatement = oldExpressionStatement;
1142 } 1146 }
1143 1147
1144 visitFor(For node) { 1148 visitFor(For node) {
1145 Scope blockScope = new BlockScope(scope); 1149 Scope blockScope = new BlockScope(scope);
1146 visitIn(node.initializer, blockScope); 1150 visitIn(node.initializer, blockScope);
1147 visitIn(node.condition, blockScope); 1151 visitIn(node.condition, blockScope);
1148 visitIn(node.update, blockScope); 1152 visitIn(node.update, blockScope);
1149 visitLoopBodyIn(node, node.body, blockScope); 1153 visitLoopBodyIn(node, node.body, blockScope);
1150 } 1154 }
1151 1155
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
1185 visit(node.condition); 1189 visit(node.condition);
1186 visit(node.thenPart); 1190 visit(node.thenPart);
1187 visit(node.elsePart); 1191 visit(node.elsePart);
1188 } 1192 }
1189 1193
1190 static bool isLogicalOperator(Identifier op) { 1194 static bool isLogicalOperator(Identifier op) {
1191 String str = op.source.stringValue; 1195 String str = op.source.stringValue;
1192 return (str === '&&' || str == '||' || str == '!'); 1196 return (str === '&&' || str == '||' || str == '!');
1193 } 1197 }
1194 1198
1199 /**
1200 * Check the lexical scope chain for a declaration with the name "assert".
1201 *
1202 * This is used to detect whether "assert(x)" is actually an assertion or
1203 * just a call expression.
1204 * It does not check fields inherited from a superclass.
1205 * This does not find setters, since their name would be "assert=".
ngeoffray 2012/09/06 09:37:31 what is this assert=? We don't create new names to
Lasse Reichstein Nielsen 2012/09/06 11:16:14 That's from the specification. The name of the dec
1206 *
1207 */
1208 bool isAssertInLexicalScope() {
1209 for (Scope scope = this.scope; scope !== null; scope = scope.parent) {
ahe 2012/09/06 08:50:42 Could we make this an operation on the scope inste
Lasse Reichstein Nielsen 2012/09/06 09:12:36 How about for (Scope.scope in this.scope.chain) {
1210 Element local = scope.localLookup(const SourceString("assert"));
1211 if (local !== null) {
1212 if (local.isAbstractField()) {
ahe 2012/09/06 08:50:42 I don't believe this implementation is correct: a
Lasse Reichstein Nielsen 2012/09/06 09:12:36 I queried Gilad, and this interpretation of the sp
1213 AbstractFieldElement field = local;
1214 if (field.getter === null) continue;
1215 }
1216 return true;
1217 }
1218 }
1219 return false;
1220 }
1221
1222 /** Check whether [node] is the body of the current expression statement. */
1223 bool isExpressionStatementBody(Node node) {
1224 return currentExpressionStatement !== null &&
1225 currentExpressionStatement.expression === node;
1226 }
1227
1195 Element resolveSend(Send node) { 1228 Element resolveSend(Send node) {
1196 Selector selector = resolveSelector(node); 1229 Selector selector = resolveSelector(node);
1197 1230
1198 if (node.receiver === null) { 1231 if (node.receiver === null) {
1232 // If this send is the body of an expression statement, and is on the
1233 // form "assert(expr);", and there is no declaration with name "assert"
1234 // in the lexical scope, then this is actually an assertion.
1235 if (isExpressionStatementBody(node) &&
1236 selector.isAssertSyntax() &&
1237 !isAssertInLexicalScope()) {
1238 return compiler.assertMethod;
1239 }
1199 return node.selector.accept(this); 1240 return node.selector.accept(this);
1200 } 1241 }
1201 1242
1202 var oldCategory = allowedCategory; 1243 var oldCategory = allowedCategory;
1203 allowedCategory |= 1244 allowedCategory |=
1204 ElementCategory.CLASS | ElementCategory.PREFIX | ElementCategory.SUPER; 1245 ElementCategory.CLASS | ElementCategory.PREFIX | ElementCategory.SUPER;
1205 Element resolvedReceiver = visit(node.receiver); 1246 Element resolvedReceiver = visit(node.receiver);
1206 allowedCategory = oldCategory; 1247 allowedCategory = oldCategory;
1207 1248
1208 Element target; 1249 Element target;
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after
1372 // we need to register that fact that we may be calling a closure 1413 // we need to register that fact that we may be calling a closure
1373 // with the same arguments. 1414 // with the same arguments.
1374 if (node.isCall && 1415 if (node.isCall &&
1375 (Element.isInvalid(target) || 1416 (Element.isInvalid(target) ||
1376 target.isGetter() || 1417 target.isGetter() ||
1377 Elements.isClosureSend(node, target))) { 1418 Elements.isClosureSend(node, target))) {
1378 Selector call = new Selector.callClosureFrom(selector); 1419 Selector call = new Selector.callClosureFrom(selector);
1379 world.registerDynamicInvocation(call.name, call); 1420 world.registerDynamicInvocation(call.name, call);
1380 } 1421 }
1381 1422
1382 // TODO(ngeoffray): We should do the check in
1383 // visitExpressionStatement instead.
1384 if (target === compiler.assertMethod && !node.isCall) {
1385 // We can only use assert by calling it.
1386 if (!inInstanceContext) {
1387 error(node, MessageKind.MISSING_ARGUMENTS_TO_ASSERT, [node]);
1388 }
1389 target = null;
1390 }
1391
1392 // TODO(ngeoffray): Warn if target is null and the send is 1423 // TODO(ngeoffray): Warn if target is null and the send is
1393 // unqualified. 1424 // unqualified.
1394 useElement(node, target); 1425 useElement(node, target);
1395 registerSend(selector, target); 1426 registerSend(selector, target);
1396 return node.isPropertyAccess ? target : null; 1427 return node.isPropertyAccess ? target : null;
1397 } 1428 }
1398 1429
1399 visitSendSet(SendSet node) { 1430 visitSendSet(SendSet node) {
1400 Element target = resolveSend(node); 1431 Element target = resolveSend(node);
1401 Element setter = target; 1432 Element setter = target;
(...skipping 1148 matching lines...) Expand 10 before | Expand all | Expand 10 after
2550 return e; 2581 return e;
2551 } 2582 }
2552 } 2583 }
2553 2584
2554 class Scope { 2585 class Scope {
2555 final Element element; 2586 final Element element;
2556 final Scope parent; 2587 final Scope parent;
2557 2588
2558 Scope(this.parent, this.element); 2589 Scope(this.parent, this.element);
2559 abstract Element add(Element element); 2590 abstract Element add(Element element);
2560 abstract Element lookup(SourceString name); 2591
2592 Element lookup(SourceString name) {
2593 Element result = localLookup(name);
2594 if (result != null) return result;
2595 return parent.lookup(name);
2596 }
2597
2598 abstract Element localLookup(SourceString name);
2561 } 2599 }
2562 2600
2563 /** 2601 /**
2564 * [TypeDeclarationScope] defines the outer scope of a type declaration in 2602 * [TypeDeclarationScope] defines the outer scope of a type declaration in
2565 * which the declared type variables and the entities in the enclosing scope are 2603 * which the declared type variables and the entities in the enclosing scope are
2566 * available but where declared and inherited members are not available. This 2604 * available but where declared and inherited members are not available. This
2567 * scope is only used for class/interface declarations during resolution of the 2605 * scope is only used for class/interface declarations during resolution of the
2568 * class hierarchy. In all other cases [ClassScope] is used. 2606 * class hierarchy. In all other cases [ClassScope] is used.
2569 */ 2607 */
2570 class TypeDeclarationScope extends Scope { 2608 class TypeDeclarationScope extends Scope {
2571 TypeDeclarationElement get element => super.element; 2609 TypeDeclarationElement get element => super.element;
2572 2610
2573 TypeDeclarationScope(parent, TypeDeclarationElement element) 2611 TypeDeclarationScope(parent, TypeDeclarationElement element)
2574 : super(parent, element) { 2612 : super(parent, element) {
2575 assert(parent !== null); 2613 assert(parent !== null);
2576 } 2614 }
2577 2615
2578 Element add(Element newElement) { 2616 Element add(Element newElement) {
2579 throw "Cannot add element to TypeDeclarationScope"; 2617 throw "Cannot add element to TypeDeclarationScope";
2580 } 2618 }
2581 2619
2582 /** 2620 /**
2583 * Looks up [name] within the type variables declared in [element]. 2621 * Looks up [name] within the type variables declared in [element].
2584 */ 2622 */
2585 Element lookupTypeVariable(SourceString name) { 2623 Element lookupTypeVariable(SourceString name) {
2586 return null; 2624 return null;
2587 } 2625 }
2588 2626
2589 Element lookup(SourceString name) { 2627 Element localLookup(SourceString name) {
2590 Link<DartType> typeVariableLink = element.typeVariables; 2628 Link<DartType> typeVariableLink = element.typeVariables;
2591 while (!typeVariableLink.isEmpty()) { 2629 while (!typeVariableLink.isEmpty()) {
2592 TypeVariableType typeVariable = typeVariableLink.head; 2630 TypeVariableType typeVariable = typeVariableLink.head;
2593 if (typeVariable.name == name) { 2631 if (typeVariable.name == name) {
2594 return typeVariable.element; 2632 return typeVariable.element;
2595 } 2633 }
2596 typeVariableLink = typeVariableLink.tail; 2634 typeVariableLink = typeVariableLink.tail;
2597 } 2635 }
2598 2636 return null;
2599 return parent.lookup(name);
2600 } 2637 }
2601 2638
2602 String toString() => 2639 String toString() =>
2603 '$element${element.typeVariables} > $parent'; 2640 '$element${element.typeVariables} > $parent';
2604 } 2641 }
2605 2642
2606 class MethodScope extends Scope { 2643 class MethodScope extends Scope {
2607 final Map<SourceString, Element> elements; 2644 final Map<SourceString, Element> elements;
2608 2645
2609 MethodScope(Scope parent, Element element) 2646 MethodScope(Scope parent, Element element)
2610 : super(parent, element), 2647 : super(parent, element),
2611 this.elements = new Map<SourceString, Element>() { 2648 this.elements = new Map<SourceString, Element>() {
2612 assert(parent !== null); 2649 assert(parent !== null);
2613 } 2650 }
2614 2651
2615 Element lookup(SourceString name) { 2652 Element localLookup(SourceString name) => elements[name];
2616 Element found = elements[name];
2617 if (found !== null) return found;
2618 return parent.lookup(name);
2619 }
2620 2653
2621 Element add(Element newElement) { 2654 Element add(Element newElement) {
2622 if (elements.containsKey(newElement.name)) { 2655 if (elements.containsKey(newElement.name)) {
2623 return elements[newElement.name]; 2656 return elements[newElement.name];
2624 } 2657 }
2625 elements[newElement.name] = newElement; 2658 elements[newElement.name] = newElement;
2626 return newElement; 2659 return newElement;
2627 } 2660 }
2628 2661
2629 String toString() => '$element${elements.getKeys()} > $parent'; 2662 String toString() => '$element${elements.getKeys()} > $parent';
2630 } 2663 }
2631 2664
2632 class BlockScope extends MethodScope { 2665 class BlockScope extends MethodScope {
2633 BlockScope(Scope parent) : super(parent, parent.element); 2666 BlockScope(Scope parent) : super(parent, parent.element);
2634 2667
2635 String toString() => 'block${elements.getKeys()} > $parent'; 2668 String toString() => 'block${elements.getKeys()} > $parent';
2636 } 2669 }
2637 2670
2638 /** 2671 /**
2639 * [ClassScope] defines the inner scope of a class/interface declaration in 2672 * [ClassScope] defines the inner scope of a class/interface declaration in
2640 * which declared members, declared type variables, entities in the enclosing 2673 * which declared members, declared type variables, entities in the enclosing
2641 * scope and inherited members are available, in the given order. 2674 * scope and inherited members are available, in the given order.
2642 */ 2675 */
2643 class ClassScope extends TypeDeclarationScope { 2676 class ClassScope extends TypeDeclarationScope {
2644 ClassScope(Scope parentScope, ClassElement element) 2677 ClassScope(Scope parentScope, ClassElement element)
2645 : super(parentScope, element); 2678 : super(parentScope, element);
2646 2679
2647 Element lookup(SourceString name) { 2680 Element localLookup(SourceString name) {
2648 ClassElement cls = element; 2681 ClassElement cls = element;
2649 Element result = cls.lookupLocalMember(name); 2682 Element result = cls.lookupLocalMember(name);
2650 if (result !== null) return result; 2683 if (result !== null) return result;
2651 result = super.lookup(name); 2684 return super.localLookup(name);
2652 if (result != null) return result; 2685 }
2686
2687 Element lookup(SourceString name) {
2688 Element result = super.lookup(name);
2689 if (result !== null) return result;
2690 ClassElement cls = element;
2653 return cls.lookupSuperMember(name); 2691 return cls.lookupSuperMember(name);
2654 } 2692 }
2655 2693
2656 Element add(Element newElement) { 2694 Element add(Element newElement) {
2657 throw "Cannot add an element in a class scope"; 2695 throw "Cannot add an element in a class scope";
2658 } 2696 }
2659 2697
2660 String toString() => '$element > $parent'; 2698 String toString() => '$element > $parent';
2661 } 2699 }
2662 2700
2663 class TopScope extends Scope { 2701 class TopScope extends Scope {
2664 LibraryElement get library => element; 2702 LibraryElement get library => element;
2665 2703
2666 TopScope(LibraryElement library) : super(null, library); 2704 TopScope(LibraryElement library) : super(null, library);
2667 Element lookup(SourceString name) { 2705
2668 return library.find(name); 2706 Element localLookup(SourceString name) => library.find(name);
2669 } 2707 Element lookup(SourceString name) => localLookup(name);
2670 2708
2671 Element add(Element newElement) { 2709 Element add(Element newElement) {
2672 throw "Cannot add an element in the top scope"; 2710 throw "Cannot add an element in the top scope";
2673 } 2711 }
2674 String toString() => '$element'; 2712 String toString() => '$element';
2675 } 2713 }
OLDNEW
« no previous file with comments | « lib/compiler/implementation/lib/mock.dart ('k') | lib/compiler/implementation/scanner/keyword.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698