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

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

Issue 9632018: Switch-implementation. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Address review 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 404 matching lines...) Expand 10 before | Expand all | Expand 10 after
415 class LabeledStatementLabelScope implements LabelScope { 415 class LabeledStatementLabelScope implements LabelScope {
416 final LabelScope outer; 416 final LabelScope outer;
417 final LabelElement label; 417 final LabelElement label;
418 LabeledStatementLabelScope(this.outer, this.label); 418 LabeledStatementLabelScope(this.outer, this.label);
419 LabelElement lookup(String labelName) { 419 LabelElement lookup(String labelName) {
420 if (this.label.labelName == labelName) return label; 420 if (this.label.labelName == labelName) return label;
421 return outer.lookup(labelName); 421 return outer.lookup(labelName);
422 } 422 }
423 } 423 }
424 424
425 class SwitchLabelScope implements LabelScope {
426 final LabelScope outer;
427 final Map<String, LabelElement> caseLabels;
428 SwitchLabelScope(this.outer, this.caseLabels);
429 LabelElement lookup(String labelName) {
430 LabelElement result = caseLabels[labelName];
431 if (result !== null) return result;
432 return outer.lookup(labelName);
433 }
434 }
435
425 class EmptyLabelScope implements LabelScope { 436 class EmptyLabelScope implements LabelScope {
426 const EmptyLabelScope(); 437 const EmptyLabelScope();
427 LabelElement lookup(String label) => null; 438 LabelElement lookup(String label) => null;
428 LabelScope get outer() { 439 LabelScope get outer() {
429 throw 'internal error: empty label scope has no outer'; 440 throw 'internal error: empty label scope has no outer';
430 } 441 }
431 } 442 }
432 443
433 class StatementScope { 444 class StatementScope {
434 LabelScope labels; 445 LabelScope labels;
435 Link<StatementElement> breakTargetStack; 446 Link<StatementElement> breakTargetStack;
436 Link<StatementElement> continueTargetStack; 447 Link<StatementElement> continueTargetStack;
448 int nestingLevel = 0;
437 449
438 StatementScope() 450 StatementScope()
439 : labels = const EmptyLabelScope(), 451 : labels = const EmptyLabelScope(),
440 breakTargetStack = const EmptyLink<StatementElement>(), 452 breakTargetStack = const EmptyLink<StatementElement>(),
441 continueTargetStack = const EmptyLink<StatementElement>(); 453 continueTargetStack = const EmptyLink<StatementElement>();
442 454
443 LabelElement lookupLabel(String label) => labels.lookup(label); 455 LabelElement lookupLabel(String label) =>
456 labels.lookup(label);
457
444 StatementElement currentBreakTarget() => 458 StatementElement currentBreakTarget() =>
445 breakTargetStack.isEmpty() ? null : breakTargetStack.head; 459 breakTargetStack.isEmpty() ? null : breakTargetStack.head;
460
446 StatementElement currentContinueTarget() => 461 StatementElement currentContinueTarget() =>
447 continueTargetStack.isEmpty() ? null : continueTargetStack.head; 462 continueTargetStack.isEmpty() ? null : continueTargetStack.head;
448 463
449 void enterLabelScope(LabelElement element) { 464 void enterLabelScope(LabelElement element) {
450 labels = new LabeledStatementLabelScope(labels, element); 465 labels = new LabeledStatementLabelScope(labels, element);
466 nestingLevel++;
451 } 467 }
468
452 void exitLabelScope() { 469 void exitLabelScope() {
470 nestingLevel--;
453 labels = labels.outer; 471 labels = labels.outer;
454 } 472 }
473
455 void enterLoop(StatementElement element) { 474 void enterLoop(StatementElement element) {
456 breakTargetStack = breakTargetStack.prepend(element); 475 breakTargetStack = breakTargetStack.prepend(element);
457 continueTargetStack = continueTargetStack.prepend(element); 476 continueTargetStack = continueTargetStack.prepend(element);
477 nestingLevel++;
458 } 478 }
479
459 void exitLoop() { 480 void exitLoop() {
481 nestingLevel--;
460 breakTargetStack = breakTargetStack.tail; 482 breakTargetStack = breakTargetStack.tail;
461 continueTargetStack = continueTargetStack.tail; 483 continueTargetStack = continueTargetStack.tail;
462 } 484 }
485
486 void enterSwitch(StatementElement breakElement,
487 Map<String, LabelElement> continueElements) {
488 breakTargetStack = breakTargetStack.prepend(breakElement);
489 labels = new SwitchLabelScope(labels, continueElements);
490 nestingLevel++;
491 }
492
493 void exitSwitch() {
494 nestingLevel--;
495 breakTargetStack = breakTargetStack.tail;
496 labels = labels.outer;
497 }
463 } 498 }
464 499
465
466 class ResolverVisitor extends CommonResolverVisitor<Element> { 500 class ResolverVisitor extends CommonResolverVisitor<Element> {
467 final TreeElementMapping mapping; 501 final TreeElementMapping mapping;
468 final Element enclosingElement; 502 final Element enclosingElement;
469 bool inInstanceContext; 503 bool inInstanceContext;
470 Scope context; 504 Scope context;
471 ClassElement currentClass; 505 ClassElement currentClass;
472 bool typeRequired = false; 506 bool typeRequired = false;
473 StatementScope statementScope; 507 StatementScope statementScope;
474 int allowedCategory = ElementCategory.VARIABLE | ElementCategory.FUNCTION; 508 int allowedCategory = ElementCategory.VARIABLE | ElementCategory.FUNCTION;
475 509
(...skipping 13 matching lines...) Expand all
489 Element result = context.lookup(name); 523 Element result = context.lookup(name);
490 if (!inInstanceContext && result != null && result.isInstanceMember()) { 524 if (!inInstanceContext && result != null && result.isInstanceMember()) {
491 error(node, MessageKind.NO_INSTANCE_AVAILABLE, [node]); 525 error(node, MessageKind.NO_INSTANCE_AVAILABLE, [node]);
492 } 526 }
493 return result; 527 return result;
494 } 528 }
495 529
496 // Create, or reuse an already created, statement element for a statement. 530 // Create, or reuse an already created, statement element for a statement.
497 StatementElement getOrCreateStatementElement(Node statement) { 531 StatementElement getOrCreateStatementElement(Node statement) {
498 StatementElement element = mapping[statement]; 532 StatementElement element = mapping[statement];
499 if (element !== null) return element; 533 if (element === null) {
500 element = new StatementElement(statement, enclosingElement); 534 element = new StatementElement(statement,
501 mapping[statement] = element; 535 statementScope.nestingLevel,
536 enclosingElement);
537 mapping[statement] = element;
538 }
502 return element; 539 return element;
503 } 540 }
504 541
505 inStaticContext(action()) { 542 inStaticContext(action()) {
506 bool wasInstanceContext = inInstanceContext; 543 bool wasInstanceContext = inInstanceContext;
507 inInstanceContext = false; 544 inInstanceContext = false;
508 action(); 545 action();
509 inInstanceContext = wasInstanceContext; 546 inInstanceContext = wasInstanceContext;
510 } 547 }
511 548
(...skipping 447 matching lines...) Expand 10 before | Expand all | Expand 10 after
959 } 996 }
960 target.isBreakTarget = true; 997 target.isBreakTarget = true;
961 } else { 998 } else {
962 String labelName = node.target.source.slowToString(); 999 String labelName = node.target.source.slowToString();
963 LabelElement label = statementScope.lookupLabel(labelName); 1000 LabelElement label = statementScope.lookupLabel(labelName);
964 if (label === null) { 1001 if (label === null) {
965 error(node.target, MessageKind.UNBOUND_LABEL, [labelName]); 1002 error(node.target, MessageKind.UNBOUND_LABEL, [labelName]);
966 return; 1003 return;
967 } 1004 }
968 target = label.target; 1005 target = label.target;
1006 if (!target.statement.isValidBreakTarget()) {
1007 error(node.target, MessageKind.INVALID_BREAK, [labelName]);
1008 return;
1009 }
969 label.setBreakTarget(); 1010 label.setBreakTarget();
970 mapping[node.target] = label; 1011 mapping[node.target] = label;
971 } 1012 }
972 mapping[node] = target; 1013 mapping[node] = target;
973 } 1014 }
974 1015
975 visitContinueStatement(ContinueStatement node) { 1016 visitContinueStatement(ContinueStatement node) {
976 StatementElement target; 1017 StatementElement target;
977 if (node.target === null) { 1018 if (node.target === null) {
978 target = statementScope.currentContinueTarget(); 1019 target = statementScope.currentContinueTarget();
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
1047 visitLiteralMapEntry(LiteralMapEntry node) { 1088 visitLiteralMapEntry(LiteralMapEntry node) {
1048 node.visitChildren(this); 1089 node.visitChildren(this);
1049 } 1090 }
1050 1091
1051 visitNamedArgument(NamedArgument node) { 1092 visitNamedArgument(NamedArgument node) {
1052 visit(node.expression); 1093 visit(node.expression);
1053 } 1094 }
1054 1095
1055 visitSwitchStatement(SwitchStatement node) { 1096 visitSwitchStatement(SwitchStatement node) {
1056 node.expression.accept(this); 1097 node.expression.accept(this);
1057 StatementElement element = getOrCreateStatementElement(node); 1098
1058 statementScope.enterLoop(element); 1099 StatementElement breakElement = getOrCreateStatementElement(node);
1100 Map<String, LabelElement> continueLabels = <LabelElement>{};
1101 Link<SwitchCase> cases = node.cases.nodes;
1102 while (!cases.isEmpty()) {
1103 SwitchCase switchCase = cases.head;
1104 if (switchCase.label !== null) {
1105 Identifier labelIdentifier = switchCase.label;
1106 String labelName = labelIdentifier.source.slowToString();
1107
1108 LabelElement existingElement = continueLabels[labelName];
1109 if (existingElement !== null) {
1110 // It's an error if the same label occurs twice in the same switch.
1111 warning(labelIdentifier, MessageKind.DUPLICATE_LABEL, [labelName]);
1112 error(existingElement.label, MessageKind.EXISTING_LABEL, [labelName]);
1113 } else {
1114 // It's only a warning if it shadows another label.
1115 existingElement = statementScope.lookupLabel(labelName);
1116 if (existingElement !== null) {
1117 warning(labelIdentifier, MessageKind.DUPLICATE_LABEL, [labelName]);
1118 warning(existingElement.label,
1119 MessageKind.EXISTING_LABEL, [labelName]);
1120 }
1121 }
1122
1123 StatementElement statementElement =
1124 new StatementElement(switchCase,
1125 statementScope.nestingLevel,
1126 enclosingElement);
1127 mapping[switchCase] = statementElement;
1128
1129 LabelElement label =
1130 new LabelElement(labelIdentifier, labelName,
1131 statementElement, enclosingElement);
1132 mapping[labelIdentifier] = label;
1133 continueLabels[labelName] = label;
1134 }
1135 cases = cases.tail;
1136 if (switchCase.defaultKeyword !== null && !cases.isEmpty()) {
1137 error(switchCase, MessageKind.INVALID_CASE_DEFAULT);
1138 }
1139 }
1140 statementScope.enterSwitch(breakElement, continueLabels);
1059 node.cases.accept(this); 1141 node.cases.accept(this);
1060 statementScope.exitLoop(); 1142 statementScope.exitSwitch();
1143
1144 // Clean-up unused labels
1145 continueLabels.forEach((String key, LabelElement label) {
1146 StatementElement statementElement = label.target;
1147 SwitchCase switchCase = statementElement.statement;
1148 if (!label.isContinueTarget) {
1149 mapping.remove(switchCase);
1150 mapping.remove(label.label);
1151 }
1152 });
1061 } 1153 }
1062 1154
1063 visitSwitchCase(SwitchCase node) { 1155 visitSwitchCase(SwitchCase node) {
1064 // TODO(ahe): What about the label? 1156 // The label was handled in [visitSwitchStatement(SwitchStatement)].
1065 node.expression.accept(this); 1157 node.expressions.accept(this);
1066 visitIn(node.statements, new BlockScope(context)); 1158 visitIn(node.statements, new BlockScope(context));
1067 } 1159 }
1068 1160
1069 visitDefaultCase(DefaultCase node) {
1070 // TODO(ahe): What about the label?
1071 visitIn(node.statements, new BlockScope(context));
1072 }
1073
1074 visitTryStatement(TryStatement node) { 1161 visitTryStatement(TryStatement node) {
1075 visit(node.tryBlock); 1162 visit(node.tryBlock);
1076 if (node.catchBlocks.isEmpty() && node.finallyBlock == null) { 1163 if (node.catchBlocks.isEmpty() && node.finallyBlock == null) {
1077 // TODO(ngeoffray): The precise location is 1164 // TODO(ngeoffray): The precise location is
1078 // node.getEndtoken.next. Adjust when issue #1581 is fixed. 1165 // node.getEndtoken.next. Adjust when issue #1581 is fixed.
1079 error(node, MessageKind.NO_CATCH_NOR_FINALLY); 1166 error(node, MessageKind.NO_CATCH_NOR_FINALLY);
1080 } 1167 }
1081 visit(node.catchBlocks); 1168 visit(node.catchBlocks);
1082 visit(node.finallyBlock); 1169 visit(node.finallyBlock);
1083 } 1170 }
(...skipping 477 matching lines...) Expand 10 before | Expand all | Expand 10 after
1561 class TopScope extends Scope { 1648 class TopScope extends Scope {
1562 LibraryElement get library() => element; 1649 LibraryElement get library() => element;
1563 1650
1564 TopScope(LibraryElement library) : super(null, library); 1651 TopScope(LibraryElement library) : super(null, library);
1565 Element lookup(SourceString name) => library.find(name); 1652 Element lookup(SourceString name) => library.find(name);
1566 1653
1567 Element add(Element element) { 1654 Element add(Element element) {
1568 throw "Cannot add an element in the top scope"; 1655 throw "Cannot add an element in the top scope";
1569 } 1656 }
1570 } 1657 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698