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

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: 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 460 matching lines...) Expand 10 before | Expand all | Expand 10 after
471 471
472 interface LabelScope { 472 interface LabelScope {
473 LabelScope get outer(); 473 LabelScope get outer();
474 LabelElement lookup(String label); 474 LabelElement lookup(String label);
475 } 475 }
476 476
477 class LabeledStatementLabelScope implements LabelScope { 477 class LabeledStatementLabelScope implements LabelScope {
478 final LabelScope outer; 478 final LabelScope outer;
479 final LabelElement label; 479 final LabelElement label;
480 LabeledStatementLabelScope(this.outer, this.label); 480 LabeledStatementLabelScope(this.outer, this.label);
481 LabelElement lookup(String labelName) { 481 LabelElement lookupBreak(String labelName) {
482 if (this.label.labelName == labelName) return label; 482 if (this.label.labelName == labelName) return label;
483 return outer.lookup(labelName); 483 return outer.lookupBreak(labelName);
484 }
485 LabelElement lookupContinue(String labelName) {
486 if (this.label.labelName == labelName) return label;
487 return outer.lookupContinue(labelName);
484 } 488 }
485 } 489 }
486 490
491
492 class SwitchLabelScope implements LabelScope {
493 final LabelScope outer;
494 final Map<String, LabelElement> caseLabels;
495 SwitchLabelScope(this.outer, this.caseLabels);
496 LabelElement lookupBreak(String labelName) {
497 return outer.lookupBreak(labelName);
498 }
499 LabelElement lookupContinue(String labelName) {
500 LabelElement result = caseLabels[labelName];
501 if (result !== null) return result;
502 return outer.lookupContinue(labelName);
503 }
504 }
505
506
487 class EmptyLabelScope implements LabelScope { 507 class EmptyLabelScope implements LabelScope {
488 const EmptyLabelScope(); 508 const EmptyLabelScope();
489 LabelElement lookup(String label) => null; 509 LabelElement lookupBreak(String label) => null;
510 LabelElement lookupContinue(String label) => null;
490 LabelScope get outer() { 511 LabelScope get outer() {
491 throw 'internal error: empty label scope has no outer'; 512 throw 'internal error: empty label scope has no outer';
492 } 513 }
493 } 514 }
494 515
495 class StatementScope { 516 class StatementScope {
496 LabelScope labels; 517 LabelScope labels;
497 Link<StatementElement> breakTargetStack; 518 Link<StatementElement> breakTargetStack;
floitsch 2012/03/08 16:35:14 These (the break and the continueTargetStack) are
Lasse Reichstein Nielsen 2012/03/08 18:35:40 Yes. Will add comment.
498 Link<StatementElement> continueTargetStack; 519 Link<StatementElement> continueTargetStack;
499 520
500 StatementScope() 521 StatementScope()
501 : labels = const EmptyLabelScope(), 522 : labels = const EmptyLabelScope(),
502 breakTargetStack = const EmptyLink<StatementElement>(), 523 breakTargetStack = const EmptyLink<StatementElement>(),
503 continueTargetStack = const EmptyLink<StatementElement>(); 524 continueTargetStack = const EmptyLink<StatementElement>();
504 525
505 LabelElement lookupLabel(String label) => labels.lookup(label); 526 LabelElement lookupBreakLabel(String label) =>
527 labels.lookupBreak(label);
528
529 LabelElement lookupContinueLabel(String label) =>
530 labels.lookupContinue(label);
531
506 StatementElement currentBreakTarget() => 532 StatementElement currentBreakTarget() =>
507 breakTargetStack.isEmpty() ? null : breakTargetStack.head; 533 breakTargetStack.isEmpty() ? null : breakTargetStack.head;
534
508 StatementElement currentContinueTarget() => 535 StatementElement currentContinueTarget() =>
509 continueTargetStack.isEmpty() ? null : continueTargetStack.head; 536 continueTargetStack.isEmpty() ? null : continueTargetStack.head;
510 537
511 void enterLabelScope(LabelElement element) { 538 void enterLabelScope(LabelElement element) {
512 labels = new LabeledStatementLabelScope(labels, element); 539 labels = new LabeledStatementLabelScope(labels, element);
513 } 540 }
541
514 void exitLabelScope() { 542 void exitLabelScope() {
515 labels = labels.outer; 543 labels = labels.outer;
516 } 544 }
545
517 void enterLoop(StatementElement element) { 546 void enterLoop(StatementElement element) {
518 breakTargetStack = breakTargetStack.prepend(element); 547 breakTargetStack = breakTargetStack.prepend(element);
519 continueTargetStack = continueTargetStack.prepend(element); 548 continueTargetStack = continueTargetStack.prepend(element);
520 } 549 }
550
521 void exitLoop() { 551 void exitLoop() {
522 breakTargetStack = breakTargetStack.tail; 552 breakTargetStack = breakTargetStack.tail;
523 continueTargetStack = continueTargetStack.tail; 553 continueTargetStack = continueTargetStack.tail;
524 } 554 }
555
556 void enterSwitch(StatementElement breakElement,
557 Map<String, LabelElement> continueElements) {
558 breakTargetStack = breakTargetStack.prepend(breakElement);
559 labels = new SwitchLabelScope(labels, continueElements);
560 }
561
562 void exitSwitch() {
563 breakTargetStack = breakTargetStack.tail;
564 labels = labels.outer;
565 }
525 } 566 }
526 567
527 568
528 class ResolverVisitor extends CommonResolverVisitor<Element> { 569 class ResolverVisitor extends CommonResolverVisitor<Element> {
529 final TreeElementMapping mapping; 570 final TreeElementMapping mapping;
530 final Element enclosingElement; 571 final Element enclosingElement;
531 bool inInstanceContext; 572 bool inInstanceContext;
532 Scope context; 573 Scope context;
533 ClassElement currentClass; 574 ClassElement currentClass;
534 bool typeRequired = false; 575 bool typeRequired = false;
(...skipping 507 matching lines...) Expand 10 before | Expand all | Expand 10 after
1042 StatementElement target; 1083 StatementElement target;
1043 if (node.target === null) { 1084 if (node.target === null) {
1044 target = statementScope.currentBreakTarget(); 1085 target = statementScope.currentBreakTarget();
1045 if (target === null) { 1086 if (target === null) {
1046 error(node, MessageKind.NO_BREAK_TARGET); 1087 error(node, MessageKind.NO_BREAK_TARGET);
1047 return; 1088 return;
1048 } 1089 }
1049 target.isBreakTarget = true; 1090 target.isBreakTarget = true;
1050 } else { 1091 } else {
1051 String labelName = node.target.source.slowToString(); 1092 String labelName = node.target.source.slowToString();
1052 LabelElement label = statementScope.lookupLabel(labelName); 1093 LabelElement label = statementScope.lookupBreakLabel(labelName);
1053 if (label === null) { 1094 if (label === null) {
1054 error(node.target, MessageKind.UNBOUND_LABEL, [labelName]); 1095 error(node.target, MessageKind.UNBOUND_LABEL, [labelName]);
1055 return; 1096 return;
1056 } 1097 }
1057 target = label.target; 1098 target = label.target;
1058 label.setBreakTarget(); 1099 label.setBreakTarget();
1059 mapping[node.target] = label; 1100 mapping[node.target] = label;
1060 } 1101 }
1061 mapping[node] = target; 1102 mapping[node] = target;
1062 } 1103 }
1063 1104
1064 visitContinueStatement(ContinueStatement node) { 1105 visitContinueStatement(ContinueStatement node) {
1065 StatementElement target; 1106 StatementElement target;
1066 if (node.target === null) { 1107 if (node.target === null) {
1067 target = statementScope.currentContinueTarget(); 1108 target = statementScope.currentContinueTarget();
1068 if (target === null) { 1109 if (target === null) {
1069 error(node, MessageKind.NO_CONTINUE_TARGET); 1110 error(node, MessageKind.NO_CONTINUE_TARGET);
1070 return; 1111 return;
1071 } 1112 }
1072 } else { 1113 } else {
1073 String labelName = node.target.source.slowToString(); 1114 String labelName = node.target.source.slowToString();
1074 LabelElement label = statementScope.lookupLabel(labelName); 1115 LabelElement label = statementScope.lookupContinueLabel(labelName);
1075 if (label === null) { 1116 if (label === null) {
1076 error(node.target, MessageKind.UNBOUND_LABEL, [labelName]); 1117 error(node.target, MessageKind.UNBOUND_LABEL, [labelName]);
1077 return; 1118 return;
1078 } 1119 }
1079 target = label.target; 1120 target = label.target;
1080 if (!target.statement.isValidContinueTarget()) { 1121 if (!target.statement.isValidContinueTarget()) {
1081 error(node.target, MessageKind.INVALID_CONTINUE, [labelName]); 1122 error(node.target, MessageKind.INVALID_CONTINUE, [labelName]);
1082 } 1123 }
1083 } 1124 }
1084 target.isContinueTarget = true; 1125 target.isContinueTarget = true;
(...skipping 13 matching lines...) Expand all
1098 !declaration.asVariableDefinitions().definitions.nodes.tail.isEmpty())) 1139 !declaration.asVariableDefinitions().definitions.nodes.tail.isEmpty()))
1099 { 1140 {
1100 // The variable declaration is either not an identifier, not a 1141 // The variable declaration is either not an identifier, not a
1101 // declaration, or it's declaring more than one variable. 1142 // declaration, or it's declaring more than one variable.
1102 error(node.declaredIdentifier, MessageKind.INVALID_FOR_IN, []); 1143 error(node.declaredIdentifier, MessageKind.INVALID_FOR_IN, []);
1103 } 1144 }
1104 } 1145 }
1105 1146
1106 visitLabelledStatement(LabelledStatement node) { 1147 visitLabelledStatement(LabelledStatement node) {
1107 String labelName = node.label.source.slowToString(); 1148 String labelName = node.label.source.slowToString();
1108 LabelElement existingElement = statementScope.lookupLabel(labelName); 1149 LabelElement existingElement = statementScope.lookupBreakLabel(labelName);
1109 if (existingElement !== null) { 1150 if (existingElement !== null) {
1110 warning(node.label, MessageKind.DUPLICATE_LABEL, [labelName]); 1151 warning(node.label, MessageKind.DUPLICATE_LABEL, [labelName]);
1111 warning(existingElement.label, MessageKind.EXISTING_LABEL, [labelName]); 1152 warning(existingElement.label, MessageKind.EXISTING_LABEL, [labelName]);
1112 } 1153 }
1113 Node body = node.getBody(); 1154 Node body = node.getBody();
1114 StatementElement statementElement = getOrCreateStatementElement(body); 1155 StatementElement statementElement = getOrCreateStatementElement(body);
1115 1156
1116 LabelElement element = statementElement.addLabel(node.label, labelName); 1157 LabelElement element = statementElement.addLabel(node.label, labelName);
1117 statementScope.enterLabelScope(element); 1158 statementScope.enterLabelScope(element);
1118 visit(node.statement); 1159 visit(node.statement);
(...skipping 17 matching lines...) Expand all
1136 visitLiteralMapEntry(LiteralMapEntry node) { 1177 visitLiteralMapEntry(LiteralMapEntry node) {
1137 node.visitChildren(this); 1178 node.visitChildren(this);
1138 } 1179 }
1139 1180
1140 visitNamedArgument(NamedArgument node) { 1181 visitNamedArgument(NamedArgument node) {
1141 visit(node.expression); 1182 visit(node.expression);
1142 } 1183 }
1143 1184
1144 visitSwitchStatement(SwitchStatement node) { 1185 visitSwitchStatement(SwitchStatement node) {
1145 node.expression.accept(this); 1186 node.expression.accept(this);
1146 StatementElement element = getOrCreateStatementElement(node); 1187
1147 statementScope.enterLoop(element); 1188 StatementElement breakElement = getOrCreateStatementElement(node);
1189 Map<String, LabelElement> continueLabels = <LabelElement>{};
1190 for (SwitchCase switchCase in node.cases) {
1191 if (switchCase.label !== null) {
1192 Identifier labelIdentifier = switchCase.label;
1193 String labelName = labelIdentifier.source.slowToString();
1194
1195 LabelElement existingElement = continueLabels[labelName];
1196 if (existingElement !== null) {
1197 // It's an error if the same label occurs twice in the same switch.
1198 warning(labelIdentifier, MessageKind.DUPLICATE_LABEL, [labelName]);
1199 error(existingElement.label, MessageKind.EXISTING_LABEL, [labelName]);
1200 } else {
1201 // It's only a warning if it shadows another label.
1202 existingElement = statementScope.lookupContinue(labelName);
1203 if (existingElement !== null) {
1204 warning(labelIdentifier, MessageKind.DUPLICATE_LABEL, [labelName]);
1205 warning(existingElement.label,
1206 MessageKind.EXISTING_LABEL, [labelName]);
1207 }
1208 }
1209
1210 StatementElement statementElement =
1211 new StatementElement(switchCase, enclosingElement);
1212 elements[switchCase] = statementElement;
1213
1214 LabelElement label =
1215 new LabelElement(currentLabel, labelName,
1216 statementElement, enclosingElement);
1217 elements[labelIdentifier] = label;
1218 continueLabels[labelName] = label;
1219
1220 currentLabel = null;
1221 }
1222 }
1223 statementScope.enterSwitch(breakElement, continueLabels);
1148 node.cases.accept(this); 1224 node.cases.accept(this);
1149 statementScope.exitLoop(); 1225 statementScope.exitSwitch();
1226
1227 // Clean-up unused labels
1228 continueLabels.forEach((String key, LabelElement label) {
1229 StatementElement statementElement = label.target;
1230 SwitchCase switchCase = statementElement.statement;
1231 if (!label.isContinueTarget) {
1232 elements.remove(switchCase);
1233 elements.remove(label.identifier);
1234 }
1235 });
1150 } 1236 }
1151 1237
1152 visitSwitchCase(SwitchCase node) { 1238 visitSwitchCase(SwitchCase node) {
1153 // TODO(ahe): What about the label? 1239 // The label was handled in [visitSwitchStatement(SwitchStatement)].
1154 node.expression.accept(this); 1240 node.expressions.accept(this);
1155 node.statements.accept(this); 1241 node.statements.accept(this);
1156 } 1242 }
1157 1243
1158 visitDefaultCase(DefaultCase node) {
1159 // TODO(ahe): What about the label?
1160 node.statements.accept(this);
1161 }
1162
1163 visitTryStatement(TryStatement node) { 1244 visitTryStatement(TryStatement node) {
1164 visit(node.tryBlock); 1245 visit(node.tryBlock);
1165 if (node.catchBlocks.isEmpty() && node.finallyBlock == null) { 1246 if (node.catchBlocks.isEmpty() && node.finallyBlock == null) {
1166 // TODO(ngeoffray): The precise location is 1247 // TODO(ngeoffray): The precise location is
1167 // node.getEndtoken.next. Adjust when issue #1581 is fixed. 1248 // node.getEndtoken.next. Adjust when issue #1581 is fixed.
1168 error(node, MessageKind.NO_CATCH_NOR_FINALLY); 1249 error(node, MessageKind.NO_CATCH_NOR_FINALLY);
1169 } 1250 }
1170 visit(node.catchBlocks); 1251 visit(node.catchBlocks);
1171 visit(node.finallyBlock); 1252 visit(node.finallyBlock);
1172 } 1253 }
(...skipping 308 matching lines...) Expand 10 before | Expand all | Expand 10 after
1481 class TopScope extends Scope { 1562 class TopScope extends Scope {
1482 LibraryElement get library() => element; 1563 LibraryElement get library() => element;
1483 1564
1484 TopScope(LibraryElement library) : super(null, library); 1565 TopScope(LibraryElement library) : super(null, library);
1485 Element lookup(SourceString name) => library.find(name); 1566 Element lookup(SourceString name) => library.find(name);
1486 1567
1487 Element add(Element element) { 1568 Element add(Element element) {
1488 throw "Cannot add an element in the top scope"; 1569 throw "Cannot add an element in the top scope";
1489 } 1570 }
1490 } 1571 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698