// Copyright 2017 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef V8_CCTEST_SCOPE_TEST_HELPER_H_
#define V8_CCTEST_SCOPE_TEST_HELPER_H_

#include "src/ast/scopes.h"
#include "src/ast/variables.h"

namespace v8 {
namespace internal {

class ScopeTestHelper {
 public:
  static bool MustAllocateInContext(Variable* var) {
    return var->scope()->MustAllocateInContext(var);
  }

  static void AllocateWithoutVariableResolution(Scope* scope) {
    scope->AllocateVariablesRecursively();
  }

  static void CompareScopes(Scope* baseline, Scope* scope,
                            bool precise_maybe_assigned) {
    CHECK_EQ(baseline->scope_type(), scope->scope_type());
    CHECK_IMPLIES(baseline->is_declaration_scope(),
                  baseline->AsDeclarationScope()->function_kind() ==
                      scope->AsDeclarationScope()->function_kind());

    if (!ProducedPreParsedScopeData::ScopeNeedsData(baseline)) {
      return;
    }

    if (scope->is_declaration_scope() &&
        scope->AsDeclarationScope()->is_skipped_function()) {
      return;
    }

    if (baseline->scope_type() == ScopeType::FUNCTION_SCOPE) {
      Variable* function = baseline->AsDeclarationScope()->function_var();
      if (function != nullptr) {
        CompareVariables(function, scope->AsDeclarationScope()->function_var(),
                         precise_maybe_assigned);
      } else {
        CHECK_NULL(scope->AsDeclarationScope()->function_var());
      }
    }

    for (auto baseline_local = baseline->locals()->begin(),
              scope_local = scope->locals()->begin();
         baseline_local != baseline->locals()->end();
         ++baseline_local, ++scope_local) {
      if (scope_local->mode() == VAR || scope_local->mode() == LET ||
          scope_local->mode() == CONST) {
        CompareVariables(*baseline_local, *scope_local, precise_maybe_assigned);
      }
    }

    for (Scope *baseline_inner = baseline->inner_scope(),
               *scope_inner = scope->inner_scope();
         scope_inner != nullptr; scope_inner = scope_inner->sibling(),
               baseline_inner = baseline_inner->sibling()) {
      CompareScopes(baseline_inner, scope_inner, precise_maybe_assigned);
    }
  }

  static void CompareVariables(Variable* baseline_local, Variable* scope_local,
                               bool precise_maybe_assigned) {
    // Sanity check the variable name. If this fails, the variable order
    // is not deterministic.
    CHECK_EQ(scope_local->raw_name()->length(),
             baseline_local->raw_name()->length());
    for (int i = 0; i < scope_local->raw_name()->length(); ++i) {
      CHECK_EQ(scope_local->raw_name()->raw_data()[i],
               baseline_local->raw_name()->raw_data()[i]);
    }

    CHECK_EQ(scope_local->location(), baseline_local->location());
    if (precise_maybe_assigned) {
      CHECK_EQ(scope_local->maybe_assigned(), baseline_local->maybe_assigned());
    } else {
      STATIC_ASSERT(kMaybeAssigned > kNotAssigned);
      CHECK_GE(scope_local->maybe_assigned(), baseline_local->maybe_assigned());
    }
  }

  // Finds a scope given a start point and directions to it (which inner scope
  // to pick).
  static Scope* FindScope(Scope* scope, const std::vector<unsigned>& location) {
    for (auto n : location) {
      scope = scope->inner_scope();
      CHECK_NOT_NULL(scope);
      while (n-- > 0) {
        scope = scope->sibling();
        CHECK_NOT_NULL(scope);
      }
    }
    return scope;
  }

  static void MarkInnerFunctionsAsSkipped(Scope* scope) {
    for (Scope* inner = scope->inner_scope(); inner != nullptr;
         inner = inner->sibling()) {
      if (inner->scope_type() == ScopeType::FUNCTION_SCOPE &&
          !inner->AsDeclarationScope()->is_arrow_scope()) {
        inner->AsDeclarationScope()->set_is_skipped_function(true);
      }
      MarkInnerFunctionsAsSkipped(inner);
    }
  }
};
}  // namespace internal
}  // namespace v8

#endif  // V8_CCTEST_SCOPE_TEST_HELPER_H_
