// Copyright (c) 2012, 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.

#include "vm/bootstrap.h"

#include "include/dart_api.h"

#include "vm/bootstrap_natives.h"
#include "vm/class_finalizer.h"
#include "vm/compiler.h"
#include "vm/dart_api_impl.h"
#include "vm/object.h"
#include "vm/object_store.h"
#include "vm/symbols.h"

namespace dart {


struct BootstrapLibProps {
  ObjectStore::BootstrapLibraryId index;
  const char* uri;
  const char** source_paths;
  const char* patch_uri;
  const char** patch_paths;
};


enum {
  kPathsUriOffset = 0,
  kPathsFileOffset = 1,
  kPathsSourceOffset = 2,
  kPathsEntryLength = 3
};


const char** Bootstrap::profiler_patch_paths_ = NULL;
const char** Bootstrap::typed_data_patch_paths_ = NULL;


#define MAKE_PROPERTIES(CamelName, name)                                       \
  {ObjectStore::k##CamelName, "dart:" #name, Bootstrap::name##_source_paths_,  \
   "dart:" #name "-patch", Bootstrap::name##_patch_paths_},

static const BootstrapLibProps bootstrap_libraries[] = {
    FOR_EACH_BOOTSTRAP_LIBRARY(MAKE_PROPERTIES)};

#undef MAKE_PROPERTIES


static const intptr_t kBootstrapLibraryCount = ARRAY_SIZE(bootstrap_libraries);


static RawString* GetLibrarySourceByIndex(intptr_t index,
                                          const String& uri,
                                          bool patch) {
  ASSERT(index >= 0 && index < kBootstrapLibraryCount);

  // Try to read the source using the path specified for the uri.
  const char** source_paths = patch ? bootstrap_libraries[index].patch_paths
                                    : bootstrap_libraries[index].source_paths;
  if (source_paths == NULL) {
    return String::null();  // No path mapping information exists for library.
  }
  const char* source_path = NULL;
  const char* source_data = NULL;
  for (intptr_t i = 0; source_paths[i] != NULL; i += kPathsEntryLength) {
    if (uri.Equals(source_paths[i + kPathsUriOffset])) {
      source_path = source_paths[i + kPathsFileOffset];
      source_data = source_paths[i + kPathsSourceOffset];
      break;
    }
  }
  if ((source_path == NULL) && (source_data == NULL)) {
    return String::null();  // Uri does not exist in path mapping information.
  }

  const uint8_t* utf8_array = NULL;
  intptr_t file_length = -1;

  Dart_FileOpenCallback file_open = Dart::file_open_callback();
  Dart_FileReadCallback file_read = Dart::file_read_callback();
  Dart_FileCloseCallback file_close = Dart::file_close_callback();
  if ((file_open != NULL) && (file_read != NULL) && (file_close != NULL)) {
    // Try to open and read the file.
    void* stream = (*file_open)(source_path, false);
    if (stream != NULL) {
      (*file_read)(&utf8_array, &file_length, stream);
      (*file_close)(stream);
    }
  }
  if (file_length == -1) {
    if (source_data != NULL) {
      file_length = strlen(source_data);
      utf8_array = reinterpret_cast<const uint8_t*>(source_data);
    } else {
      return String::null();
    }
  }
  ASSERT(utf8_array != NULL);
  ASSERT(file_length >= 0);
  return String::FromUTF8(utf8_array, file_length);
}


static RawString* GetLibrarySource(const Library& lib,
                                   const String& uri,
                                   bool patch) {
  // First check if this is a valid bootstrap library and find its index in
  // the 'bootstrap_libraries' table above.
  intptr_t index;
  const String& lib_uri = String::Handle(lib.url());
  for (index = 0; index < kBootstrapLibraryCount; ++index) {
    if (lib_uri.Equals(bootstrap_libraries[index].uri)) {
      break;
    }
  }
  if (index == kBootstrapLibraryCount) {
    return String::null();  // The library is not a bootstrap library.
  }

  return GetLibrarySourceByIndex(index, uri, patch);
}


static RawError* Compile(const Library& library, const Script& script) {
  bool update_lib_status = (script.kind() == RawScript::kScriptTag ||
                            script.kind() == RawScript::kLibraryTag);
  if (update_lib_status) {
    library.SetLoadInProgress();
  }
  const Error& error = Error::Handle(Compiler::Compile(library, script));
  if (update_lib_status) {
    if (error.IsNull()) {
      library.SetLoaded();
    } else {
      // Compilation errors are not Dart instances, so just mark the library
      // as having failed to load without providing an error instance.
      library.SetLoadError(Object::null_instance());
    }
  }
  return error.raw();
}


static Dart_Handle LoadPartSource(Thread* thread,
                                  const Library& lib,
                                  const String& uri) {
  Zone* zone = thread->zone();
  const String& part_source =
      String::Handle(zone, GetLibrarySource(lib, uri, false));
  const String& lib_uri = String::Handle(zone, lib.url());
  if (part_source.IsNull()) {
    return Api::NewError("Unable to read part file '%s' of library '%s'",
                         uri.ToCString(), lib_uri.ToCString());
  }

  // Prepend the library URI to form a unique script URI for the part.
  const Array& strings = Array::Handle(zone, Array::New(3));
  strings.SetAt(0, lib_uri);
  strings.SetAt(1, Symbols::Slash());
  strings.SetAt(2, uri);
  const String& part_uri = String::Handle(zone, String::ConcatAll(strings));

  // Create a script object and compile the part.
  const Script& part_script = Script::Handle(
      zone, Script::New(part_uri, part_source, RawScript::kSourceTag));
  const Error& error = Error::Handle(zone, Compile(lib, part_script));
  return Api::NewHandle(thread, error.raw());
}


static Dart_Handle BootstrapLibraryTagHandler(Dart_LibraryTag tag,
                                              Dart_Handle library,
                                              Dart_Handle uri) {
  Thread* thread = Thread::Current();
  Zone* zone = thread->zone();
  // This handler calls into the VM directly and does not use the Dart
  // API so we transition back to VM.
  TransitionNativeToVM transition(thread);
  if (!Dart_IsLibrary(library)) {
    return Api::NewError("not a library");
  }
  if (!Dart_IsString(uri)) {
    return Api::NewError("uri is not a string");
  }
  if (tag == Dart_kCanonicalizeUrl) {
    // In the bootstrap loader we do not try and do any canonicalization.
    return uri;
  }
  const String& uri_str = Api::UnwrapStringHandle(zone, uri);
  ASSERT(!uri_str.IsNull());
  if (tag == Dart_kImportTag) {
    // We expect the core bootstrap libraries to only import other
    // core bootstrap libraries.
    // We have precreated all the bootstrap library objects hence
    // we do not expect to be called back with the tag set to kImportTag.
    // The bootstrap process explicitly loads all the libraries one by one.
    return Api::NewError("Invalid import of '%s' in a bootstrap library",
                         uri_str.ToCString());
  }
  ASSERT(tag == Dart_kSourceTag);
  const Library& lib = Api::UnwrapLibraryHandle(zone, library);
  ASSERT(!lib.IsNull());
  return LoadPartSource(thread, lib, uri_str);
}


static RawError* LoadPatchFiles(Thread* thread,
                                const Library& lib,
                                intptr_t index) {
  const char** patch_files = bootstrap_libraries[index].patch_paths;
  if (patch_files == NULL) return Error::null();

  Zone* zone = thread->zone();
  String& patch_uri = String::Handle(
      zone, Symbols::New(thread, bootstrap_libraries[index].patch_uri));
  String& patch_file_uri = String::Handle(zone);
  String& source = String::Handle(zone);
  Script& script = Script::Handle(zone);
  Error& error = Error::Handle(zone);
  const Array& strings = Array::Handle(zone, Array::New(3));
  strings.SetAt(0, patch_uri);
  strings.SetAt(1, Symbols::Slash());
  for (intptr_t j = 0; patch_files[j] != NULL; j += kPathsEntryLength) {
    patch_file_uri = String::New(patch_files[j + kPathsUriOffset]);
    source = GetLibrarySourceByIndex(index, patch_file_uri, true);
    if (source.IsNull()) {
      const String& message = String::Handle(
          String::NewFormatted("Unable to find dart patch source for %s",
                               patch_file_uri.ToCString()));
      return ApiError::New(message);
    }
    // Prepend the patch library URI to form a unique script URI for the patch.
    strings.SetAt(2, patch_file_uri);
    patch_file_uri = String::ConcatAll(strings);
    script = Script::New(patch_file_uri, source, RawScript::kPatchTag);
    error = lib.Patch(script);
    if (!error.IsNull()) {
      return error.raw();
    }
  }
  return Error::null();
}


static RawError* BootstrapFromSource(Thread* thread) {
  Isolate* isolate = thread->isolate();
  Zone* zone = thread->zone();
  String& uri = String::Handle(zone);
  String& source = String::Handle(zone);
  Script& script = Script::Handle(zone);
  Library& lib = Library::Handle(zone);
  Error& error = Error::Handle(zone);

  // Set the library tag handler for the isolate to the bootstrap
  // library tag handler so that we can load all the bootstrap libraries.
  Dart_LibraryTagHandler saved_tag_handler = isolate->library_tag_handler();
  isolate->set_library_tag_handler(BootstrapLibraryTagHandler);

  // Load, compile and patch bootstrap libraries.
  for (intptr_t i = 0; i < kBootstrapLibraryCount; ++i) {
    ObjectStore::BootstrapLibraryId id = bootstrap_libraries[i].index;
    uri = Symbols::New(thread, bootstrap_libraries[i].uri);
    lib = isolate->object_store()->bootstrap_library(id);
    ASSERT(!lib.IsNull());
    ASSERT(lib.raw() == Library::LookupLibrary(thread, uri));
    source = GetLibrarySourceByIndex(i, uri, false);
    if (source.IsNull()) {
      const String& message = String::Handle(String::NewFormatted(
          "Unable to find dart source for %s", uri.ToCString()));
      error ^= ApiError::New(message);
      break;
    }
    script = Script::New(uri, source, RawScript::kLibraryTag);
    error = Compile(lib, script);
    if (!error.IsNull()) {
      break;
    }
    // If a patch exists, load and patch the script.
    error = LoadPatchFiles(thread, lib, i);
    if (!error.IsNull()) {
      break;
    }
  }

  if (error.IsNull()) {
    Bootstrap::SetupNativeResolver();
    ClassFinalizer::ProcessPendingClasses();

    // Eagerly compile the _Closure class as it is the class of all closure
    // instances. This allows us to just finalize function types
    // without going through the hoops of trying to compile their scope class.
    Class& cls = Class::Handle(zone, isolate->object_store()->closure_class());
    Compiler::CompileClass(cls);
    // Eagerly compile Bool class, bool constants are used from within compiler.
    cls = isolate->object_store()->bool_class();
    Compiler::CompileClass(cls);
  }

  // Restore the library tag handler for the isolate.
  isolate->set_library_tag_handler(saved_tag_handler);

  return error.raw();
}


RawError* Bootstrap::DoBootstrapping() {
  Thread* thread = Thread::Current();
  Isolate* isolate = thread->isolate();
  Zone* zone = thread->zone();
  String& uri = String::Handle(zone);
  Library& lib = Library::Handle(zone);

  HANDLESCOPE(thread);

  // Ensure there are library objects for all the bootstrap libraries.
  for (intptr_t i = 0; i < kBootstrapLibraryCount; ++i) {
    ObjectStore::BootstrapLibraryId id = bootstrap_libraries[i].index;
    uri = Symbols::New(thread, bootstrap_libraries[i].uri);
    lib = isolate->object_store()->bootstrap_library(id);
    ASSERT(lib.raw() == Library::LookupLibrary(thread, uri));
    if (lib.IsNull()) {
      lib = Library::NewLibraryHelper(uri, false);
      lib.SetLoadRequested();
      lib.Register(thread);
      isolate->object_store()->set_bootstrap_library(id, lib);
    }
  }

  return BootstrapFromSource(thread);
}

}  // namespace dart
