| Index: pkg/compiler/lib/src/ssa/switch_continue_analysis.dart
|
| diff --git a/pkg/compiler/lib/src/ssa/switch_continue_analysis.dart b/pkg/compiler/lib/src/ssa/switch_continue_analysis.dart
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..fd67da6bb974d206530d19c45159a956164b5128
|
| --- /dev/null
|
| +++ b/pkg/compiler/lib/src/ssa/switch_continue_analysis.dart
|
| @@ -0,0 +1,113 @@
|
| +import 'package:kernel/ast.dart' as ir;
|
| +
|
| +/// Helper class that traverses a kernel AST subtree to see if it has any
|
| +/// continue statements in the body of any switch cases (having continue
|
| +/// statements results in a more complex generated code).
|
| +class SwitchContinueAnalysis extends ir.Visitor<bool> {
|
| +
|
| + SwitchContinueAnalysis._();
|
| +
|
| + static bool containsContinue(ir.Statement switchCaseBody) {
|
| + return switchCaseBody.accept(new SwitchContinueAnalysis._());
|
| + }
|
| +
|
| + bool visitContinueSwitchStatement(ir.ContinueSwitchStatement continueStmt) {
|
| + // TODO(efortuna): Check what the target of this continue statement actually
|
| + // IS, because depending on where the label points if we have a nested
|
| + // switch statement we might be able to output simpler code (not the complex
|
| + // switch statement).
|
| + return true;
|
| + }
|
| +
|
| + bool visitBlock(ir.Block block) {
|
| + for (ir.Statement statement in block.statements) {
|
| + if (statement.accept(this)) {
|
| + return true;
|
| + }
|
| + }
|
| + return false;
|
| + }
|
| +
|
| + bool visitLabeledStatement(ir.LabeledStatement statement) {
|
| + return statement.body.accept(this);
|
| + }
|
| +
|
| + bool visitDoStatement(ir.DoStatement doStatement) {
|
| + return doStatement.body.accept(this);
|
| + }
|
| +
|
| + bool visitForStatement(ir.ForStatement forStatement) {
|
| + return forStatement.body.accept(this);
|
| + }
|
| +
|
| + bool visitForInStatement(ir.ForInStatement forInStatement) {
|
| + return forInStatement.body.accept(this);
|
| + }
|
| +
|
| + bool visitSwitchStatement(ir.SwitchStatement switchStatement) {
|
| + for (var switchCase in switchStatement.cases) {
|
| + if (switchCase.accept(this)) {
|
| + return true;
|
| + }
|
| + }
|
| + return false;
|
| + }
|
| +
|
| + bool visitSwitchCase(ir.SwitchCase switchCase) {
|
| + return switchCase.body.accept(this);
|
| + }
|
| +
|
| + bool visitIfStatement(ir.IfStatement ifStatement) {
|
| + if (ifStatement.then.accept(this)) {
|
| + if (ifStatement.otherwise != null) {
|
| + return ifStatement.otherwise.accept(this);
|
| + }
|
| + }
|
| + return false;
|
| + }
|
| +
|
| + bool visitTryCatch(ir.TryCatch tryCatch) {
|
| + if (tryCatch.body.accept(this)) {
|
| + for (var catchStatement in tryCatch.catches) {
|
| + if (catchStatement.accept(this)) {
|
| + return true;
|
| + }
|
| + }
|
| + }
|
| + return false;
|
| + }
|
| +
|
| + bool visitWhileStatement(ir.WhileStatement statement) {
|
| + return statement.body.accept(this);
|
| + }
|
| +
|
| + bool visitCatch(ir.Catch catchStatement) {
|
| + return catchStatement.body.accept(this);
|
| + }
|
| +
|
| + bool visitTryFinally(ir.TryFinally tryFinally) {
|
| + return tryFinally.body.accept(this) &&
|
| + tryFinally.finalizer.accept(this);
|
| + }
|
| +
|
| + bool visitFunctionDeclaration(ir.FunctionDeclaration declaration) {
|
| + return declaration.function.accept(this);
|
| + }
|
| +
|
| + bool visitFunctionNode(ir.FunctionNode node) {
|
| + return node.body.accept(this);
|
| + }
|
| +
|
| + bool defaultStatement(ir.Statement node) {
|
| + if (node is ir.ExpressionStatement || node is ir.EmptyStatement ||
|
| + node is ir.InvalidStatement || node is ir.BreakStatement ||
|
| + node is ir.ReturnStatement || node is ir.AssertStatement ||
|
| + node is ir.YieldStatement || node is ir.VariableDeclaration) {
|
| + return false;
|
| + }
|
| + throw 'Statement type ${node.runtimeType} not handled in '
|
| + 'SwitchContinueAnalysis';
|
| + }
|
| +
|
| + bool defaultNode(ir.Node node) => false;
|
| +}
|
|
|