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

/// New Compiler API. This API is under construction, use only internally or
/// in unittests.

library compiler_new;

import 'dart:async';

import 'package:front_end/src/api_unstable/dart2js.dart' as fe;

import 'compiler.dart' show Diagnostic;
import 'src/apiimpl.dart';
import 'src/options.dart' show CompilerOptions;

export 'compiler.dart' show Diagnostic;

// Unless explicitly allowed, passing `null` for any argument to the
// methods of library will result in an Error being thrown.

/// Input kinds used by [CompilerInput.readFromUri].
enum InputKind {
  /// Data is read as UTF8 either as a [String] or a zero-terminated
  /// `List<int>`.
  UTF8,

  /// Data is read as bytes in a `List<int>`.
  binary,
}

/// Interface for data read through [CompilerInput.readFromUri].
abstract class Input<T> {
  /// The URI from which data was read.
  Uri get uri;

  /// The format of the read [data].
  InputKind get inputKind;

  /// The raw data read from [uri].
  T get data;

  /// Release any resources held by the input. After releasing, a call to `get
  /// data` will fail, and previously returned data may be invalid.
  void release();
}

/// Interface for providing the compiler with input. That is, Dart source files,
/// package config files, etc.
abstract class CompilerInput {
  /// Returns a future that completes to the source corresponding to [uri].
  /// If an exception occurs, the future completes with this exception.
  ///
  /// If [inputKind] is `InputKind.UTF8` the source can be represented either as
  /// a zero-terminated `List<int>` of UTF-8 bytes or as a [String]. If
  /// [inputKind] is `InputKind.binary` the source is a read a `List<int>`.
  ///
  /// The following text is non-normative:
  ///
  /// It is recommended to return a UTF-8 encoded list of bytes because the
  /// scanner is more efficient in this case. In either case, the data structure
  /// is expected to hold a zero element at the last position. If this is not
  /// the case, the entire data structure is copied before scanning.
  Future<Input> readFromUri(Uri uri, {InputKind inputKind: InputKind.UTF8});
}

/// Output types used in `CompilerOutput.createOutputSink`.
enum OutputType {
  /// The main JavaScript output.
  js,

  /// A deferred JavaScript output part.
  jsPart,

  /// A source map for a JavaScript output.
  sourceMap,

  /// Dump info output.
  dumpInfo,

  /// Deferred map output.
  deferredMap,

  /// Implementation specific output used for debugging the compiler.
  debug,
}

/// Sink interface used for generating output from the compiler.
abstract class OutputSink {
  /// Adds [text] to the sink.
  void add(String text);

  /// Closes the sink.
  void close();
}

/// Sink interface used for generating binary data from the compiler.
abstract class BinaryOutputSink {
  /// Writes indices [start] to [end] of [buffer] to the sink.
  void write(List<int> buffer, [int start = 0, int end]);

  /// Closes the sink.
  void close();
}

/// Interface for producing output from the compiler. That is, JavaScript target
/// files, source map files, dump info files, etc.
abstract class CompilerOutput {
  /// Returns an [OutputSink] that will serve as compiler output for the given
  /// component.
  ///
  /// Components are identified by [name], [extension], and [type]. By
  /// convention, the empty string `""` will represent the main output of the
  /// provided [type]. [name] and [extension] are otherwise suggestive.
  // TODO(johnniwinther): Replace [name] and [extension] with something like
  // [id] and [uri].
  OutputSink createOutputSink(String name, String extension, OutputType type);

  /// Returns an [BinaryOutputSink] that will serve as compiler output for the
  /// given URI.
  BinaryOutputSink createBinarySink(Uri uri);
}

/// Interface for receiving diagnostic message from the compiler. That is,
/// errors, warnings, hints, etc.
abstract class CompilerDiagnostics {
  /// Invoked by the compiler to report diagnostics. If [uri] is `null`, so are
  /// [begin] and [end]. No other arguments may be `null`. If [uri] is not
  /// `null`, neither are [begin] and [end]. [uri] indicates the compilation
  /// unit from where the diagnostic originates. [begin] and [end] are
  /// zero-based character offsets from the beginning of the compilation unit.
  /// [message] is the diagnostic message, and [kind] indicates indicates what
  /// kind of diagnostic it is.
  ///
  /// Experimental: [code] gives access to an id for the messages. Currently it
  /// is the [Message] used to create the diagnostic, if available, from which
  /// the [MessageKind] is accessible.
  void report(
      var code, Uri uri, int begin, int end, String text, Diagnostic kind);
}

/// Information resulting from the compilation.
class CompilationResult {
  /// `true` if the compilation succeeded, that is, compilation didn't fail due
  /// to compile-time errors and/or internal errors.
  final bool isSuccess;

  /// The compiler object used for the compilation.
  ///
  /// Note: The type of [compiler] is implementation dependent and may vary.
  /// Use only for debugging and testing.
  final compiler;

  /// Shared state between compilations.
  ///
  /// This is used to speed up batch mode.
  final fe.InitializedCompilerState kernelInitializedCompilerState;

  CompilationResult(this.compiler,
      {this.isSuccess: true, this.kernelInitializedCompilerState: null});
}

/// Returns a future that completes to a [CompilationResult] when the Dart
/// sources in [options] have been compiled.
///
/// The generated compiler output is obtained by providing a [compilerOutput].
///
/// If the compilation fails, the future's `CompilationResult.isSuccess` is
/// `false` and [CompilerDiagnostics.report] on [compilerDiagnostics]
/// is invoked at least once with `kind == Diagnostic.ERROR` or
/// `kind == Diagnostic.CRASH`.
Future<CompilationResult> compile(
    CompilerOptions compilerOptions,
    CompilerInput compilerInput,
    CompilerDiagnostics compilerDiagnostics,
    CompilerOutput compilerOutput) {
  if (compilerOptions == null) {
    throw new ArgumentError("compilerOptions must be non-null");
  }
  if (compilerInput == null) {
    throw new ArgumentError("compilerInput must be non-null");
  }
  if (compilerDiagnostics == null) {
    throw new ArgumentError("compilerDiagnostics must be non-null");
  }
  if (compilerOutput == null) {
    throw new ArgumentError("compilerOutput must be non-null");
  }

  CompilerImpl compiler = new CompilerImpl(
      compilerInput, compilerOutput, compilerDiagnostics, compilerOptions);
  return compiler.run(compilerOptions.entryPoint).then((bool success) {
    return new CompilationResult(compiler,
        isSuccess: success,
        kernelInitializedCompilerState:
            compiler.kernelLoader.initializedCompilerState);
  });
}
