// 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/objects-inl.h"
#include "src/parsing/parse-info.h"
#include "src/parsing/parser.h"
#include "src/parsing/scanner-character-streams.h"
#include "src/vm-state-inl.h"

namespace v8 {
namespace internal {
namespace parsing {

bool ParseProgram(ParseInfo* info, Isolate* isolate) {
  DCHECK(info->is_toplevel());
  DCHECK_NULL(info->literal());

  VMState<PARSER> state(isolate);

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

  Parser parser(info);

  FunctionLiteral* result = nullptr;
  // Ok to use Isolate here; this function is only called in the main thread.
  DCHECK(parser.parsing_on_main_thread_);

  parser.SetCachedData(info);
  result = parser.ParseProgram(isolate, info);
  info->set_literal(result);
  if (result == nullptr) {
    info->pending_error_handler()->ReportErrors(isolate, info->script(),
                                                info->ast_value_factory());
  } else {
    result->scope()->AttachOuterScopeInfo(info, isolate);
    info->set_language_mode(info->literal()->language_mode());
  }
  parser.UpdateStatistics(isolate, info->script());
  return (result != nullptr);
}

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

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

  VMState<PARSER> state(isolate);

  Parser parser(info);

  FunctionLiteral* result = nullptr;
  // Ok to use Isolate here; this function is only called in the main thread.
  DCHECK(parser.parsing_on_main_thread_);

  result = parser.ParseFunction(isolate, info, shared_info);
  info->set_literal(result);
  if (result == nullptr) {
    info->pending_error_handler()->ReportErrors(isolate, info->script(),
                                                info->ast_value_factory());
  } else {
    result->scope()->AttachOuterScopeInfo(info, isolate);
  }
  parser.UpdateStatistics(isolate, info->script());
  return (result != nullptr);
}

bool ParseAny(ParseInfo* info, Handle<SharedFunctionInfo> shared_info,
              Isolate* isolate) {
  DCHECK(!shared_info.is_null());
  return info->is_toplevel() ? ParseProgram(info, isolate)
                             : ParseFunction(info, shared_info, isolate);
}

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