// Copyright 2016 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.

#include "src/parsing/parsing.h"

#include <memory>

#include "src/ast/ast.h"
#include "src/base/v8-fallthrough.h"
#include "src/execution/vm-state-inl.h"
#include "src/handles/maybe-handles.h"
#include "src/objects/objects-inl.h"
#include "src/parsing/parse-info.h"
#include "src/parsing/parser.h"
#include "src/parsing/rewriter.h"
#include "src/parsing/scanner-character-streams.h"
#include "src/zone/zone-list-inl.h"  // crbug.com/v8/8816

namespace v8 {
namespace internal {
namespace parsing {

namespace {

void MaybeReportErrorsAndStatistics(ParseInfo* info, Handle<Script> script,
                                    Isolate* isolate, Parser* parser,
                                    ReportStatisticsMode mode) {
  switch (mode) {
    case ReportStatisticsMode::kYes:
      parser->UpdateStatistics(isolate, script);
      break;
    case ReportStatisticsMode::kNo:
      break;
  }
}

}  // namespace

bool ParseProgram(ParseInfo* info, Handle<Script> script,
                  MaybeHandle<ScopeInfo> maybe_outer_scope_info,
                  Isolate* isolate, ReportStatisticsMode mode) {
  DCHECK(info->flags().is_toplevel());
  DCHECK_NULL(info->literal());

  VMState<PARSER> state(isolate);

  // Create a character stream for the parser.
  Handle<String> source(String::cast(script->source()), isolate);
  isolate->counters()->total_parse_size()->Increment(source->length());
  std::unique_ptr<Utf16CharacterStream> stream(
      ScannerStream::For(isolate, source));
  info->set_character_stream(std::move(stream));

  Parser parser(info);

  // Ok to use Isolate here; this function is only called in the main thread.
  DCHECK(parser.parsing_on_main_thread_);
  parser.ParseProgram(isolate, script, info, maybe_outer_scope_info);
  MaybeReportErrorsAndStatistics(info, script, isolate, &parser, mode);
  return info->literal() != nullptr;
}

bool ParseProgram(ParseInfo* info, Handle<Script> script, Isolate* isolate,
                  ReportStatisticsMode mode) {
  return ParseProgram(info, script, kNullMaybeHandle, isolate, mode);
}

bool ParseFunction(ParseInfo* info, Handle<SharedFunctionInfo> shared_info,
                   Isolate* isolate, ReportStatisticsMode mode) {
  DCHECK(!info->flags().is_toplevel());
  DCHECK(!shared_info.is_null());
  DCHECK_NULL(info->literal());

  VMState<PARSER> state(isolate);

  // Create a character stream for the parser.
  Handle<Script> script(Script::cast(shared_info->script()), isolate);
  Handle<String> source(String::cast(script->source()), isolate);
  isolate->counters()->total_parse_size()->Increment(source->length());
  std::unique_ptr<Utf16CharacterStream> stream(
      ScannerStream::For(isolate, source, shared_info->StartPosition(),
                         shared_info->EndPosition()));
  info->set_character_stream(std::move(stream));

  Parser parser(info);

  // Ok to use Isolate here; this function is only called in the main thread.
  DCHECK(parser.parsing_on_main_thread_);
  parser.ParseFunction(isolate, info, shared_info);
  MaybeReportErrorsAndStatistics(info, script, isolate, &parser, mode);
  return info->literal() != nullptr;
}

bool ParseAny(ParseInfo* info, Handle<SharedFunctionInfo> shared_info,
              Isolate* isolate, ReportStatisticsMode mode) {
  DCHECK(!shared_info.is_null());
  if (info->flags().is_toplevel()) {
    MaybeHandle<ScopeInfo> maybe_outer_scope_info;
    if (shared_info->HasOuterScopeInfo()) {
      maybe_outer_scope_info =
          handle(shared_info->GetOuterScopeInfo(), isolate);
    }
    return ParseProgram(info,
                        handle(Script::cast(shared_info->script()), isolate),
                        maybe_outer_scope_info, isolate, mode);
  }
  return ParseFunction(info, shared_info, isolate, mode);
}

}  // namespace parsing
}  // namespace internal
}  // namespace v8
