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

/// Defines the front-end API for converting source code to Dart Kernel objects.
library front_end.kernel_generator;

import 'dart:async' show Future;

import 'package:kernel/ast.dart' show Component;

import 'package:kernel/class_hierarchy.dart' show ClassHierarchy;

import 'package:kernel/core_types.dart' show CoreTypes;

import '../base/processed_options.dart' show ProcessedOptions;

import '../fasta/compiler_context.dart' show CompilerContext;

import '../fasta/fasta_codes.dart' show messageMissingMain, noLength;

import '../fasta/severity.dart' show Severity;

import '../kernel_generator_impl.dart'
    show generateKernel, generateKernelInternal;

import 'compiler_options.dart' show CompilerOptions;

/// Generates a kernel representation of the program whose main library is in
/// the given [source].
///
/// Intended for whole-program (non-modular) compilation.
///
/// Given the Uri of a file containing a program's `main` method, this function
/// follows `import`, `export`, and `part` declarations to discover the whole
/// program, and converts the result to Dart Kernel format.
///
/// If `compileSdk` in [options] is true, the generated [CompilerResult] will
/// include code for the SDK.
///
/// If summaries are provided in [options], the compiler will use them instead
/// of compiling the libraries contained in those summaries. This is useful, for
/// example, when compiling for platforms that already embed those sources (like
/// the sdk in the standalone VM).
///
/// The input [source] is expected to be a script with a main method, otherwise
/// an error is reported.
// TODO(sigmund): rename to kernelForScript?
Future<CompilerResult> kernelForProgram(
    Uri source, CompilerOptions options) async {
  return (await kernelForProgramInternal(source, options));
}

Future<CompilerResult> kernelForProgramInternal(
    Uri source, CompilerOptions options,
    {bool retainDataForTesting: false}) async {
  ProcessedOptions pOptions =
      new ProcessedOptions(options: options, inputs: [source]);
  return await CompilerContext.runWithOptions(pOptions, (context) async {
    CompilerResult result = await generateKernelInternal(
        includeHierarchyAndCoreTypes: true,
        retainDataForTesting: retainDataForTesting);
    Component component = result?.component;
    if (component == null) return null;

    if (component.mainMethod == null) {
      context.options.report(
          messageMissingMain.withLocation(source, -1, noLength),
          Severity.error);
      return null;
    }
    return result;
  });
}

/// Generates a kernel representation for a module containing [sources].
///
/// A module is a collection of libraries that are compiled together. Libraries
/// in the module may depend on each other and may have dependencies to
/// libraries in other modules. Unlike library dependencies, module dependencies
/// must be acyclic.
///
/// This API is intended for modular compilation. Dependencies to other modules
/// are specified using [CompilerOptions.inputSummaries]. Any dependency
/// of [sources] that is not listed in [CompilerOptions.inputSummaries] and
/// [CompilerOptions.sdkSummary] is treated as an additional source file for the
/// module.
///
/// Any `part` declarations found in [sources] must refer to part files which
/// are also listed in the module sources, otherwise an error results.  (It
/// is not permitted to refer to a part file declared in another module).
///
/// The return value is a [CompilerResult] object with no main method set in
/// the [Component] of its `component` property. The [Component] includes
/// external libraries for those libraries loaded through summaries.
Future<CompilerResult> kernelForModule(
    List<Uri> sources, CompilerOptions options) async {
  return (await generateKernel(
      new ProcessedOptions(options: options, inputs: sources),
      includeHierarchyAndCoreTypes: true));
}

/// Result object for [kernelForProgram] and [kernelForModule].
abstract class CompilerResult {
  /// The generated summary bytes, if it was requested.
  List<int> get summary;

  /// The generated component, if it was requested.
  Component get component;

  /// Dependencies traversed by the compiler. Used only for generating
  /// dependency .GN files in the dart-sdk build system.
  /// Note this might be removed when we switch to compute dependencies without
  /// using the compiler itself.
  List<Uri> get deps;

  /// The [ClassHierarchy] for the compiled [component], if it was requested.
  ClassHierarchy get classHierarchy;

  /// The [CoreTypes] object for the compiled [component], if it was requested.
  CoreTypes get coreTypes;
}
