// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

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>
    with ir.VisitorDefaultValueMixin<bool> {
  SwitchContinueAnalysis._();

  static bool containsContinue(ir.Statement switchCaseBody) {
    return switchCaseBody.accept(SwitchContinueAnalysis._());
  }

  @override
  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;
  }

  @override
  bool visitBlock(ir.Block block) {
    for (ir.Statement statement in block.statements) {
      if (statement.accept(this)) {
        return true;
      }
    }
    return false;
  }

  @override
  bool visitLabeledStatement(ir.LabeledStatement statement) {
    return statement.body.accept(this);
  }

  @override
  bool visitDoStatement(ir.DoStatement doStatement) {
    return doStatement.body.accept(this);
  }

  @override
  bool visitForStatement(ir.ForStatement forStatement) {
    return forStatement.body.accept(this);
  }

  @override
  bool visitForInStatement(ir.ForInStatement forInStatement) {
    return forInStatement.body.accept(this);
  }

  @override
  bool visitSwitchStatement(ir.SwitchStatement switchStatement) {
    for (var switchCase in switchStatement.cases) {
      if (switchCase.accept(this)) {
        return true;
      }
    }
    return false;
  }

  @override
  bool visitSwitchCase(ir.SwitchCase switchCase) {
    return switchCase.body.accept(this);
  }

  @override
  bool visitIfStatement(ir.IfStatement ifStatement) {
    return ifStatement.then.accept(this) ||
        (ifStatement.otherwise != null && ifStatement.otherwise!.accept(this));
  }

  @override
  bool visitTryCatch(ir.TryCatch tryCatch) {
    if (tryCatch.body.accept(this)) {
      for (var catchStatement in tryCatch.catches) {
        if (catchStatement.accept(this)) {
          return true;
        }
      }
    }
    return false;
  }

  @override
  bool visitWhileStatement(ir.WhileStatement statement) {
    return statement.body.accept(this);
  }

  @override
  bool visitCatch(ir.Catch catchStatement) {
    return catchStatement.body.accept(this);
  }

  @override
  bool visitTryFinally(ir.TryFinally tryFinally) {
    return tryFinally.body.accept(this) && tryFinally.finalizer.accept(this);
  }

  @override
  bool visitFunctionDeclaration(ir.FunctionDeclaration declaration) {
    return declaration.function.accept(this);
  }

  @override
  bool visitFunctionNode(ir.FunctionNode node) {
    return node.body!.accept(this);
  }

  @override
  bool defaultStatement(ir.Statement node) {
    if (node is ir.ExpressionStatement ||
        node is ir.EmptyStatement ||
        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';
  }

  @override
  bool get defaultValue => false;
}
