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

Unified Diff: frog/leg/resolver.dart

Issue 9632018: Switch-implementation. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Finished implementation 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 db1a755a6da2ba991350c1ddcbccdb723e8d0f04..b58c510cd7b80fe8aced274f7ea3ffbee6239e5c 100644
--- a/frog/leg/resolver.dart
+++ b/frog/leg/resolver.dart
@@ -488,6 +488,19 @@ class LabeledStatementLabelScope implements LabelScope {
}
}
ahe 2012/03/09 13:58:32 Remove extra line
Lasse Reichstein Nielsen 2012/03/12 13:05:23 Done.
+
+class SwitchLabelScope implements LabelScope {
+ final LabelScope outer;
+ final Map<String, LabelElement> caseLabels;
+ SwitchLabelScope(this.outer, this.caseLabels);
+ LabelElement lookup(String labelName) {
+ LabelElement result = caseLabels[labelName];
+ if (result !== null) return result;
+ return outer.lookup(labelName);
+ }
+}
+
ahe 2012/03/09 13:58:32 Extra line.
Lasse Reichstein Nielsen 2012/03/12 13:05:23 Done.
+
class EmptyLabelScope implements LabelScope {
const EmptyLabelScope();
LabelElement lookup(String label) => null;
@@ -506,26 +519,43 @@ class StatementScope {
breakTargetStack = const EmptyLink<StatementElement>(),
continueTargetStack = const EmptyLink<StatementElement>();
- LabelElement lookupLabel(String label) => labels.lookup(label);
+ LabelElement lookupLabel(String label) =>
+ labels.lookup(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;
+ }
}
@@ -538,6 +568,8 @@ class ResolverVisitor extends CommonResolverVisitor<Element> {
bool typeRequired = false;
StatementScope statementScope;
int allowedCategory = ElementCategory.VARIABLE | ElementCategory.FUNCTION;
+ // For generating locally unique ids.
+ int sequence = 0;
ResolverVisitor(Compiler compiler, Element element)
: this.mapping = new TreeElementMapping(),
@@ -563,7 +595,13 @@ class ResolverVisitor extends CommonResolverVisitor<Element> {
StatementElement getOrCreateStatementElement(Node statement) {
StatementElement element = mapping[statement];
if (element !== null) return element;
- element = new StatementElement(statement, enclosingElement);
+ if (statement is SwitchStatement) {
ahe 2012/03/09 13:58:32 statement.asSwitchStatement() !== null
Lasse Reichstein Nielsen 2012/03/12 13:05:23 Why use something that's harder to read and is pos
Lasse Reichstein Nielsen 2012/03/12 13:21:28 But I rewrote it anyway :)
+ element = new SwitchStatementElement(statement,
+ enclosingElement,
+ sequence++);
+ } else {
+ element = new StatementElement(statement, enclosingElement);
+ }
mapping[statement] = element;
return element;
}
@@ -1037,6 +1075,10 @@ class ResolverVisitor extends CommonResolverVisitor<Element> {
return;
}
target = label.target;
+ if (!target.statement.isValidBreakTarget()) {
+ error(node.target, MessageKind.INVALID_BREAK, [labelName]);
+ return;
+ }
label.setBreakTarget();
mapping[node.target] = label;
}
@@ -1125,20 +1167,58 @@ 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.lookupLabel(labelName);
+ if (existingElement !== null) {
+ warning(labelIdentifier, MessageKind.DUPLICATE_LABEL, [labelName]);
+ warning(existingElement.label,
+ MessageKind.EXISTING_LABEL, [labelName]);
+ }
+ }
+
+ StatementElement statementElement =
+ new StatementElement(switchCase, enclosingElement);
+ mapping[switchCase] = statementElement;
+
+ LabelElement label =
+ new LabelElement(labelIdentifier, labelName,
+ statementElement, enclosingElement);
+ mapping[labelIdentifier] = label;
+ continueLabels[labelName] = label;
+ }
+ }
+ 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) {
+ mapping.remove(switchCase);
+ mapping.remove(label.label);
+ }
+ });
}
visitSwitchCase(SwitchCase node) {
- // TODO(ahe): What about the label?
- node.expression.accept(this);
- visitIn(node.statements, new BlockScope(context));
- }
-
- visitDefaultCase(DefaultCase node) {
- // TODO(ahe): What about the label?
+ // The label was handled in [visitSwitchStatement(SwitchStatement)].
+ node.expressions.accept(this);
visitIn(node.statements, new BlockScope(context));
}

Powered by Google App Engine
This is Rietveld 408576698