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

library dart2js.resolution.result;

import '../constants/expressions.dart';
import '../dart_types.dart';
import '../elements/elements.dart';
import '../tree/tree.dart';
import '../universe/call_structure.dart' show
    CallStructure;

enum ResultKind {
  NONE,
  ELEMENT,
  TYPE,
  ASSERT,
  CONSTANT,
  PREFIX,
}

/// The result of resolving a node.
abstract class ResolutionResult {
  const ResolutionResult();

  // TODO(johnniwinther): Remove this factory constructor when `null` is never
  // passed as an element result.
  factory ResolutionResult.forElement(Element element) {
    return element != null ? new ElementResult(element) : const NoneResult();
  }

  ResultKind get kind;
  Node get node => null;
  Element get element => null;
  DartType get type => null;
  ConstantExpression get constant => null;
  bool get isConstant => false;
}

/// The prefix of top level or member access, like `prefix.member`,
/// `prefix.Class.member` or `Class.member`.
class PrefixResult extends ResolutionResult {
  final PrefixElement prefix;
  final ClassElement cls;

  PrefixResult(this.prefix, this.cls);

  Element get element => cls != null ? cls : prefix;

  bool get isDeferred => prefix != null && prefix.isDeferred;

  ResultKind get kind => ResultKind.PREFIX;

  String toString() => 'PrefixResult($prefix,$cls)';
}

/// The result for the resolution of a node that points to an [Element].
class ElementResult extends ResolutionResult {
  final Element element;

  ResultKind get kind => ResultKind.ELEMENT;

  ElementResult(this.element) {
    assert(element != null);
  }

  String toString() => 'ElementResult($element)';
}

/// The result for the resolution of a node that points to an [DartType].
class TypeResult extends ResolutionResult {
  final DartType type;

  TypeResult(this.type) {
    assert(type != null);
  }

  ResultKind get kind => ResultKind.TYPE;

  Element get element => type.element;

  String toString() => 'TypeResult($type)';
}

/// The result for resolving a constant expression.
class ConstantResult extends ResolutionResult {
  final Node node;
  final ConstantExpression constant;
  final Element element;

  /// Creates a result for the [constant] expression. [node] is provided for
  /// error reporting on the constant and [element] is provided if the
  /// expression additionally serves an [Element] like [ElementResult].
  ConstantResult(this.node, this.constant, {this.element});

  bool get isConstant => true;

  ResultKind get kind => ResultKind.CONSTANT;

  String toString() => 'ConstantResult(${constant.getText()})';
}

class NoneResult extends ResolutionResult {
  const NoneResult();

  ResultKind get kind => ResultKind.NONE;

  String toString() => 'NoneResult()';
}

/// The result of resolving a list of arguments.
class ArgumentsResult {
  /// The call structure of the arguments.
  final CallStructure callStructure;

  /// The resolutions results for each argument.
  final List<ResolutionResult> argumentResults;

  /// `true` if the arguments are valid as arguments to a constructed constant
  /// expression.
  final bool isValidAsConstant;

  ArgumentsResult(
      this.callStructure,
      this.argumentResults,
      {this.isValidAsConstant});

  /// Returns the list of [ConstantExpression]s for each of the arguments. If
  /// [isValidAsConstant] is `false`, `null` is returned.
  List<ConstantExpression> get constantArguments {
    if (!isValidAsConstant) return null;
    return argumentResults.map((ResolutionResult result) {
      return result.constant;
    }).toList();
  }
}
