scope-test-helper.h 4.23 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
// 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);
  }

20 21
  static void CompareScopes(Scope* baseline, Scope* scope,
                            bool precise_maybe_assigned) {
22 23 24 25
    CHECK_EQ(baseline->scope_type(), scope->scope_type());
    CHECK_IMPLIES(baseline->is_declaration_scope(),
                  baseline->AsDeclarationScope()->function_kind() ==
                      scope->AsDeclarationScope()->function_kind());
26

27
    if (!PreparseDataBuilder::ScopeNeedsData(baseline)) return;
28 29 30

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

34
    if (baseline->is_function_scope()) {
35 36 37 38 39 40 41 42 43
      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());
      }
    }

44 45 46 47
    for (auto baseline_local = baseline->locals()->begin(),
              scope_local = scope->locals()->begin();
         baseline_local != baseline->locals()->end();
         ++baseline_local, ++scope_local) {
48 49 50
      if (scope_local->mode() == VariableMode::kVar ||
          scope_local->mode() == VariableMode::kLet ||
          scope_local->mode() == VariableMode::kConst) {
51
        CompareVariables(*baseline_local, *scope_local, precise_maybe_assigned);
52 53 54
      }
    }

55 56 57 58 59
    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);
60 61
    }
  }
62

63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
  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 {
78
      static_assert(kMaybeAssigned > kNotAssigned);
79 80 81 82
      CHECK_GE(scope_local->maybe_assigned(), baseline_local->maybe_assigned());
    }
  }

83 84 85 86 87 88 89 90 91 92 93 94 95
  // 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;
  }
96 97 98 99

  static void MarkInnerFunctionsAsSkipped(Scope* scope) {
    for (Scope* inner = scope->inner_scope(); inner != nullptr;
         inner = inner->sibling()) {
100
      if (inner->is_function_scope() &&
101 102 103 104 105 106
          !inner->AsDeclarationScope()->is_arrow_scope()) {
        inner->AsDeclarationScope()->set_is_skipped_function(true);
      }
      MarkInnerFunctionsAsSkipped(inner);
    }
  }
107 108

  static bool HasSkippedFunctionInside(Scope* scope) {
109
    if (scope->is_function_scope() &&
110 111 112 113 114
        scope->AsDeclarationScope()->is_skipped_function()) {
      return true;
    }
    for (Scope* inner = scope->inner_scope(); inner != nullptr;
         inner = inner->sibling()) {
115
      if (HasSkippedFunctionInside(inner)) return true;
116 117 118
    }
    return false;
  }
119 120 121 122 123
};
}  // namespace internal
}  // namespace v8

#endif  // V8_CCTEST_SCOPE_TEST_HELPER_H_