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

/**
 * The interface used to access the result of constant evaluation.
 *
 * Because the analyzer does not have any of the code under analysis loaded, it
 * does not do real evaluation. Instead it performs a symbolic computation and
 * presents those results through this interface.
 *
 * Instances of these constant values are accessed through the
 * [element model](../element/element.dart).
 */
import 'package:analyzer/dart/element/type.dart';

/**
 * A representation of the value of a compile-time constant expression.
 *
 * Note that, unlike the mirrors system, the object being represented does *not*
 * exist. This interface allows static analysis tools to determine something
 * about the state of the object that would exist if the code that creates the
 * object were executed, but none of the code being analyzed is actually
 * executed.
 *
 * Clients may not extend, implement or mix-in this class.
 */
abstract class DartObject {
  /**
   * Return `true` if the value of the object being represented is known.
   *
   * This method will return `false` if
   * * the value being represented is the value of a declared variable (a
   *   variable whose value is provided at run-time using a `-D` command-line
   *   option), or
   * * the value is a function.
   *
   * The result of this method does not imply anything about the state of
   * object representations returned by the method [getField], those that are
   * elements of the list returned by [toListValue], or the keys or values in
   * the map returned by [toMapValue]. For example, a representation of a list
   * can return `true` even if one or more of the elements of that list would
   * return `false`.
   */
  bool get hasKnownValue;

  /**
   * Return `true` if the object being represented represents the value 'null'.
   */
  bool get isNull;

  /**
   * Return a representation of the type of the object being represented.
   *
   * For values resulting from the invocation of a 'const' constructor, this
   * will be a representation of the run-time type of the object.
   *
   * For values resulting from a literal expression, this will be a
   * representation of the static type of the value -- `int` for integer
   * literals, `List` for list literals, etc. -- even when the static type is an
   * abstract type (such as `List`) and hence will never be the run-time type of
   * the represented object.
   *
   * For values resulting from any other kind of expression, this will be a
   * representation of the result of evaluating the expression.
   *
   * Return `null` if the expression cannot be evaluated, either because it is
   * not a valid constant expression or because one or more of the values used
   * in the expression does not have a known value.
   *
   * This method can return a representation of the type, even if this object
   * would return `false` from [hasKnownValue].
   */
  ParameterizedType get type;

  /**
   * Return a representation of the value of the field with the given [name].
   *
   * Return `null` if either the object being represented does not have a field
   * with the given name or if the implementation of the class of the object is
   * invalid, making it impossible to determine that value of the field.
   *
   * Note that, unlike the mirrors API, this method does *not* invoke a getter;
   * it simply returns a representation of the known state of a field.
   */
  DartObject getField(String name);

  /**
   * Return a boolean corresponding to the value of the object being
   * represented, or `null` if
   * * this object is not of type 'bool',
   * * the value of the object being represented is not known, or
   * * the value of the object being represented is `null`.
   */
  bool toBoolValue();

  /**
   * Return a double corresponding to the value of the object being represented,
   * or `null`
   * if
   * * this object is not of type 'double',
   * * the value of the object being represented is not known, or
   * * the value of the object being represented is `null`.
   */
  double toDoubleValue();

  /**
   * Return an integer corresponding to the value of the object being
   * represented, or `null` if
   * * this object is not of type 'int',
   * * the value of the object being represented is not known, or
   * * the value of the object being represented is `null`.
   */
  int toIntValue();

  /**
   * Return a list corresponding to the value of the object being represented,
   * or `null` if
   * * this object is not of type 'List', or
   * * the value of the object being represented is `null`.
   */
  List<DartObject> toListValue();

  /**
   * Return a map corresponding to the value of the object being represented, or
   * `null` if
   * * this object is not of type 'Map', or
   * * the value of the object being represented is `null`.
   */
  Map<DartObject, DartObject> toMapValue();

  /**
   * Return a string corresponding to the value of the object being represented,
   * or `null` if
   * * this object is not of type 'String',
   * * the value of the object being represented is not known, or
   * * the value of the object being represented is `null`.
   */
  String toStringValue();

  /**
   * Return a string corresponding to the value of the object being represented,
   * or `null` if
   * * this object is not of type 'Symbol', or
   * * the value of the object being represented is `null`.
   * (We return the string
   */
  String toSymbolValue();

  /**
   * Return the representation of the type corresponding to the value of the
   * object being represented, or `null` if
   * * this object is not of type 'Type', or
   * * the value of the object being represented is `null`.
   */
  DartType toTypeValue();
}
