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

library compiler;

import 'dart:async';

import 'compiler_new.dart' as new_api;
import 'src/old_to_new_api.dart';
import 'src/options.dart' show CompilerOptions;

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

/// Returns a future that completes to the source corresponding to [uri].
/// If an exception occurs, the future completes with this exception.
///
/// The source can be represented either as a [:List<int>:] of UTF-8 bytes or as
/// a [String].
///
/// 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.
typedef Future /* <String | List<int>> */ CompilerInputProvider(Uri uri);

/// Deprecated, please use [CompilerInputProvider] instead.
typedef Future<String> ReadStringFromUri(Uri uri);

/// Returns an [EventSink] that will serve as compiler output for the given
/// component.
///
/// Components are identified by [name] and [extension]. By convention,
/// the empty string [:"":] will represent the main script
/// (corresponding to the script parameter of [compile]) even if the
/// main script is a library. For libraries that are compiled
/// separately, the library name is used.
///
/// At least the following extensions can be expected:
///
/// * "js" for JavaScript output.
/// * "js.map" for source maps.
/// * "dart" for Dart output.
/// * "dart.map" for source maps.
///
/// As more features are added to the compiler, new names and
/// extensions may be introduced.
typedef EventSink<String> CompilerOutputProvider(String name, String extension);

/// 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.
typedef void DiagnosticHandler(
    Uri uri, int begin, int end, String message, 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;

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

/// Returns a future that completes to a non-null String when [script]
/// has been successfully compiled.
///
/// The compiler output is obtained by providing an [outputProvider].
///
/// If the compilation fails, the future's value will be [:null:] and
/// [handler] will have been invoked at least once with [:kind ==
/// Diagnostic.ERROR:] or [:kind == Diagnostic.CRASH:].
///
/// Deprecated: if no [outputProvider] is given, the future completes
/// to the compiled script. This behavior will be removed in the future
/// as the compiler may create multiple files to support lazy loading
/// of libraries.
Future<CompilationResult> compile(Uri script, Uri librariesSpecificationUri,
    CompilerInputProvider inputProvider, DiagnosticHandler handler,
    [List<String> options = const [],
    CompilerOutputProvider outputProvider,
    Map<String, String> environment = const {},
    Uri packageConfig]) {
  CompilerOptions compilerOptions = CompilerOptions.parse(options,
      librariesSpecificationUri: librariesSpecificationUri)
    ..entryUri = script
    ..packageConfig = packageConfig
    ..environment = environment;

  new_api.CompilerInput compilerInput = new LegacyCompilerInput(inputProvider);
  new_api.CompilerDiagnostics compilerDiagnostics =
      new LegacyCompilerDiagnostics(handler);
  new_api.CompilerOutput compilerOutput =
      new LegacyCompilerOutput(outputProvider);

  return new_api
      .compile(
          compilerOptions, compilerInput, compilerDiagnostics, compilerOutput)
      .then((new_api.CompilationResult result) {
    return new CompilationResult(result.compiler, isSuccess: result.isSuccess);
  });
}

/// Kind of diagnostics that the compiler can report.
class Diagnostic {
  /// An error as identified by the "Dart Programming Language
  /// Specification" [http://www.dartlang.org/docs/spec/].
  ///
  /// Note: the compiler may still produce an executable result after
  /// reporting a compilation error. The specification says:
  ///
  /// "A compile-time error must be reported by a Dart compiler before
  /// the erroneous code is executed." and "If a compile-time error
  /// occurs within the code of a running isolate A, A is immediately
  /// suspended."
  ///
  /// This means that the compiler can generate code that when executed
  /// terminates execution.
  static const Diagnostic ERROR = const Diagnostic(1, 'error');

  /// A warning as identified by the "Dart Programming Language
  /// Specification" [http://www.dartlang.org/docs/spec/].
  static const Diagnostic WARNING = const Diagnostic(2, 'warning');

  /// Any other warning that is not covered by [WARNING].
  static const Diagnostic HINT = const Diagnostic(4, 'hint');

  /// Additional information about the preceding non-info diagnostic from the
  /// compiler.
  ///
  /// For example, consider a duplicated definition. The compiler first emits a
  /// message about the duplicated definition, then emits an info message about
  /// the location of the existing definition.
  static const Diagnostic INFO = const Diagnostic(8, 'info');

  /// Informational messages that shouldn't be printed unless
  /// explicitly requested by the user of a compiler.
  static const Diagnostic VERBOSE_INFO = const Diagnostic(16, 'verbose info');

  /// An internal error in the compiler.
  static const Diagnostic CRASH = const Diagnostic(32, 'crash');

  /// An [int] representation of this kind. The ordinals are designed
  /// to be used as bitsets.
  final int ordinal;

  /// The name of this kind.
  final String name;

  /// This constructor is not private to support user-defined
  /// diagnostic kinds.
  const Diagnostic(this.ordinal, this.name);

  @override
  String toString() => name;
}
