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

Unified 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 side-by-side diff with in-line comments
Download patch
Index: frog/leg/resolver.dart
diff --git a/frog/leg/resolver.dart b/frog/leg/resolver.dart
index 545af307ab37063b7993a520a3fddc42d7909ef2..e0ad4f1402dc82ba0d87e06728c98ba41aa43241 100644
--- a/frog/leg/resolver.dart
+++ b/frog/leg/resolver.dart
@@ -478,15 +478,36 @@ class LabeledStatementLabelScope implements LabelScope {
final LabelScope outer;
final LabelElement label;
LabeledStatementLabelScope(this.outer, this.label);
- LabelElement lookup(String labelName) {
+ LabelElement lookupBreak(String labelName) {
if (this.label.labelName == labelName) return label;
- return outer.lookup(labelName);
+ return outer.lookupBreak(labelName);
+ }
+ LabelElement lookupContinue(String labelName) {
+ if (this.label.labelName == labelName) return label;
+ return outer.lookupContinue(labelName);
+ }
+}
+
+
+class SwitchLabelScope implements LabelScope {
+ final LabelScope outer;
+ final Map<String, LabelElement> caseLabels;
+ SwitchLabelScope(this.outer, this.caseLabels);
+ LabelElement lookupBreak(String labelName) {
+ return outer.lookupBreak(labelName);
+ }
+ LabelElement lookupContinue(String labelName) {
+ LabelElement result = caseLabels[labelName];
+ if (result !== null) return result;
+ return outer.lookupContinue(labelName);
}
}
+
class EmptyLabelScope implements LabelScope {
const EmptyLabelScope();
- LabelElement lookup(String label) => null;
+ LabelElement lookupBreak(String label) => null;
+ LabelElement lookupContinue(String label) => null;
LabelScope get outer() {
throw 'internal error: empty label scope has no outer';
}
@@ -502,26 +523,46 @@ class StatementScope {
breakTargetStack = const EmptyLink<StatementElement>(),
continueTargetStack = const EmptyLink<StatementElement>();
- LabelElement lookupLabel(String label) => labels.lookup(label);
+ LabelElement lookupBreakLabel(String label) =>
+ labels.lookupBreak(label);
+
+ LabelElement lookupContinueLabel(String label) =>
+ labels.lookupContinue(label);
+
StatementElement currentBreakTarget() =>
breakTargetStack.isEmpty() ? null : breakTargetStack.head;
+
StatementElement currentContinueTarget() =>
continueTargetStack.isEmpty() ? null : continueTargetStack.head;
void enterLabelScope(LabelElement element) {
labels = new LabeledStatementLabelScope(labels, element);
}
+
void exitLabelScope() {
labels = labels.outer;
}
+
void enterLoop(StatementElement element) {
breakTargetStack = breakTargetStack.prepend(element);
continueTargetStack = continueTargetStack.prepend(element);
}
+
void exitLoop() {
breakTargetStack = breakTargetStack.tail;
continueTargetStack = continueTargetStack.tail;
}
+
+ void enterSwitch(StatementElement breakElement,
+ Map<String, LabelElement> continueElements) {
+ breakTargetStack = breakTargetStack.prepend(breakElement);
+ labels = new SwitchLabelScope(labels, continueElements);
+ }
+
+ void exitSwitch() {
+ breakTargetStack = breakTargetStack.tail;
+ labels = labels.outer;
+ }
}
@@ -1049,7 +1090,7 @@ class ResolverVisitor extends CommonResolverVisitor<Element> {
target.isBreakTarget = true;
} else {
String labelName = node.target.source.slowToString();
- LabelElement label = statementScope.lookupLabel(labelName);
+ LabelElement label = statementScope.lookupBreakLabel(labelName);
if (label === null) {
error(node.target, MessageKind.UNBOUND_LABEL, [labelName]);
return;
@@ -1071,7 +1112,7 @@ class ResolverVisitor extends CommonResolverVisitor<Element> {
}
} else {
String labelName = node.target.source.slowToString();
- LabelElement label = statementScope.lookupLabel(labelName);
+ LabelElement label = statementScope.lookupContinueLabel(labelName);
if (label === null) {
error(node.target, MessageKind.UNBOUND_LABEL, [labelName]);
return;
@@ -1105,7 +1146,7 @@ class ResolverVisitor extends CommonResolverVisitor<Element> {
visitLabelledStatement(LabelledStatement node) {
String labelName = node.label.source.slowToString();
- LabelElement existingElement = statementScope.lookupLabel(labelName);
+ LabelElement existingElement = statementScope.lookupBreakLabel(labelName);
if (existingElement !== null) {
warning(node.label, MessageKind.DUPLICATE_LABEL, [labelName]);
warning(existingElement.label, MessageKind.EXISTING_LABEL, [labelName]);
@@ -1143,20 +1184,60 @@ class ResolverVisitor extends CommonResolverVisitor<Element> {
visitSwitchStatement(SwitchStatement node) {
node.expression.accept(this);
- StatementElement element = getOrCreateStatementElement(node);
- statementScope.enterLoop(element);
+
+ StatementElement breakElement = getOrCreateStatementElement(node);
+ Map<String, LabelElement> continueLabels = <LabelElement>{};
+ for (SwitchCase switchCase in node.cases) {
+ if (switchCase.label !== null) {
+ Identifier labelIdentifier = switchCase.label;
+ String labelName = labelIdentifier.source.slowToString();
+
+ LabelElement existingElement = continueLabels[labelName];
+ if (existingElement !== null) {
+ // It's an error if the same label occurs twice in the same switch.
+ warning(labelIdentifier, MessageKind.DUPLICATE_LABEL, [labelName]);
+ error(existingElement.label, MessageKind.EXISTING_LABEL, [labelName]);
+ } else {
+ // It's only a warning if it shadows another label.
+ existingElement = statementScope.lookupContinue(labelName);
+ if (existingElement !== null) {
+ warning(labelIdentifier, MessageKind.DUPLICATE_LABEL, [labelName]);
+ warning(existingElement.label,
+ MessageKind.EXISTING_LABEL, [labelName]);
+ }
+ }
+
+ StatementElement statementElement =
+ new StatementElement(switchCase, enclosingElement);
+ elements[switchCase] = statementElement;
+
+ LabelElement label =
+ new LabelElement(currentLabel, labelName,
+ statementElement, enclosingElement);
+ elements[labelIdentifier] = label;
+ continueLabels[labelName] = label;
+
+ currentLabel = null;
+ }
+ }
+ statementScope.enterSwitch(breakElement, continueLabels);
node.cases.accept(this);
- statementScope.exitLoop();
+ statementScope.exitSwitch();
+
+ // Clean-up unused labels
+ continueLabels.forEach((String key, LabelElement label) {
+ StatementElement statementElement = label.target;
+ SwitchCase switchCase = statementElement.statement;
+ if (!label.isContinueTarget) {
+ elements.remove(switchCase);
+ elements.remove(label.identifier);
+ }
+ });
}
visitSwitchCase(SwitchCase node) {
- // TODO(ahe): What about the label?
- node.expression.accept(this);
- node.statements.accept(this);
- }
-
- visitDefaultCase(DefaultCase node) {
- // TODO(ahe): What about the label?
+ // The label was handled in [visitSwitchStatement(SwitchStatement)].
+ node.expressions.accept(this);
node.statements.accept(this);
}

Powered by Google App Engine
This is Rietveld 408576698