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

/// Analysis to determine how to generate code for `LookupMap`s.
library compiler.src.js_backend.lookup_map_analysis;

import 'package:pub_semver/pub_semver.dart';

import '../common.dart';
import '../common_elements.dart';
import '../common/backend_api.dart';
import '../compile_time_constants.dart';
import '../constants/constant_system.dart';
import '../constants/values.dart'
    show
        ConstantValue,
        ConstructedConstantValue,
        ListConstantValue,
        NullConstantValue,
        StringConstantValue,
        TypeConstantValue;
import '../elements/elements.dart' show ClassElement, FieldElement;
import '../elements/entities.dart';
import '../elements/resolution_types.dart' show ResolutionInterfaceType;
import '../options.dart';
import '../universe/use.dart' show ConstantUse, StaticUse;
import '../universe/world_impact.dart'
    show WorldImpact, StagedWorldImpactBuilder;
import 'backend_helpers.dart';

/// Lookup map handling for resolution.
///
/// This analysis checks for the import of `package:lookup_map/lookup_map.dart`,
/// and if found, read the `_version` variable from it.
///
/// In [LookupMapAnalysis] the value of `_version` is checked to ensure that it
/// is valid to perform the optimization of `LookupMap`. The actual optimization
/// is performed by [LookupMapAnalysis].
class LookupMapResolutionAnalysis {
  static final Uri PACKAGE_LOOKUP_MAP =
      new Uri(scheme: 'package', path: 'lookup_map/lookup_map.dart');

  /// Reference the diagnostic reporting system for logging and reporting issues
  /// to the end-user.
  final DiagnosticReporter _reporter;

  final ElementEnvironment _elementEnvironment;

  /// The resolved [FieldEntity] associated with the top-level `_version`.
  FieldEntity lookupMapVersionVariable;

  /// The resolved [LibraryEntity] associated with
  /// `package:lookup_map/lookup_map.dart`.
  LibraryEntity lookupMapLibrary;

  final StagedWorldImpactBuilder _impactBuilder =
      new StagedWorldImpactBuilder();

  LookupMapResolutionAnalysis(this._reporter, this._elementEnvironment);

  /// Compute the [WorldImpact] for the constants registered since last flush.
  WorldImpact flush() {
    return _impactBuilder.flush();
  }

  /// Initializes this analysis by providing the resolved library. This is
  /// invoked during resolution when the `lookup_map` library is discovered.
  void init(LibraryEntity library) {
    lookupMapLibrary = library;
    // We will enable the lookupMapAnalysis as long as we get a known version of
    // the lookup_map package. We otherwise produce a warning.
    lookupMapVersionVariable =
        _elementEnvironment.lookupLibraryMember(lookupMapLibrary, '_version');
    if (lookupMapVersionVariable == null) {
      _reporter.reportHintMessage(
          library, MessageKind.UNRECOGNIZED_VERSION_OF_LOOKUP_MAP);
    } else {
      _impactBuilder
          .registerStaticUse(new StaticUse.staticGet(lookupMapVersionVariable));
    }
  }
}

/// An analysis and optimization to remove unused entries from a `LookupMap`.
///
/// `LookupMaps` are defined in `package:lookup_map/lookup_map.dart`. They are
/// simple maps that contain constant expressions as keys, and that only support
/// the lookup operation.
///
/// This analysis and optimization will tree-shake the contents of the maps by
/// looking at the program and finding which keys are clearly unused. Not all
/// constants can be approximated statically, so this optimization is limited to
/// the following keys:
///
///   * Const expressions that can only be created via const constructors. This
///   excludes primitives, strings, and any const type that overrides the ==
///   operator.
///
///   * Type literals.
///
/// Type literals are more complex than const expressions because they can be
/// created in multiple ways. We can approximate the possible set of keys if we
/// follow these rules:
///
///   * Include all type-literals used explicitly in the code (excluding
///   obviously the uses that can be removed from LookupMaps)
///
///   * Include every reflectable type-literal if a mirror API is used to create
///   types (e.g.  ClassMirror.reflectedType).
///
///   * Include all allocated types if the program contains `e.runtimeType`
///   expressions.
///
///   * Include all generic-type arguments, if the program uses type
///   variables in expressions such as `class A<T> { Type get extract => T }`.
///
// TODO(sigmund): add support for const expressions, currently this
// implementation only supports Type literals. To support const expressions we
// need to change some of the invariants below (e.g. we can no longer use the
// ClassElement of a type to refer to keys we need to discover).
// TODO(sigmund): detect uses of mirrors
class LookupMapAnalysis {
  const LookupMapAnalysis._();

  factory LookupMapAnalysis(
      DiagnosticReporter reporter,
      ConstantSystem constantSystem,
      ConstantEnvironment constants,
      ElementEnvironment elementEnvironment,
      CommonElements commonElements,
      BackendHelpers helpers,
      BackendClasses backendClasses,
      LookupMapResolutionAnalysis analysis) {
    /// Checks if the version of lookup_map is valid, and if so, enable this
    /// analysis during codegen.
    FieldElement lookupMapVersionVariable = analysis.lookupMapVersionVariable;
    if (lookupMapVersionVariable == null) return const LookupMapAnalysis._();

    // At this point, the lookupMapVersionVariable should be resolved and it's
    // constant value should be available.
    StringConstantValue value =
        constants.getConstantValue(lookupMapVersionVariable.constant);
    if (value == null) {
      reporter.reportHintMessage(lookupMapVersionVariable,
          MessageKind.UNRECOGNIZED_VERSION_OF_LOOKUP_MAP);
      return const LookupMapAnalysis._();
    }

    // TODO(sigmund): add proper version resolution using the pub_semver package
    // when we introduce the next version.
    Version version;
    try {
      version = new Version.parse(value.primitiveValue.slowToString());
    } catch (e) {}

    if (version == null || !_validLookupMapVersionConstraint.allows(version)) {
      reporter.reportHintMessage(lookupMapVersionVariable,
          MessageKind.UNRECOGNIZED_VERSION_OF_LOOKUP_MAP);
      return const LookupMapAnalysis._();
    }

    ClassEntity typeLookupMapClass =
        elementEnvironment.lookupClass(analysis.lookupMapLibrary, 'LookupMap');
    FieldElement entriesField =
        elementEnvironment.lookupClassMember(typeLookupMapClass, '_entries');
    FieldElement keyField =
        elementEnvironment.lookupClassMember(typeLookupMapClass, '_key');
    FieldElement valueField =
        elementEnvironment.lookupClassMember(typeLookupMapClass, '_value');
    // TODO(sigmund): Maybe inline nested maps to make the output code smaller?

    return new _LookupMapAnalysis(constantSystem, commonElements, helpers,
        backendClasses, entriesField, keyField, valueField, typeLookupMapClass);
  }

  /// Compute the [WorldImpact] for the constants registered since last flush.
  WorldImpact flush() => const WorldImpact();

  /// Whether [constant] is an instance of a `LookupMap`.
  bool isLookupMap(ConstantValue constant) => false;

  /// Registers an instance of a lookup-map with the analysis.
  void registerLookupMapReference(ConstantValue lookupMap) {}

  /// Callback from the enqueuer, invoked when [element] is instantiated.
  void registerInstantiatedClass(ClassElement element) {}

  /// Callback from the enqueuer, invoked when [type] is instantiated.
  void registerInstantiatedType(ResolutionInterfaceType type) {}

  /// Callback from the codegen enqueuer, invoked when a constant (which is
  /// possibly a const key or a type literal) is used in the program.
  void registerTypeConstant(ClassElement element) {}

  void registerConstantKey(ConstantValue constant) {}

  void logSummary(void log(String message)) {}

  void onQueueClosed() {}
}

class _LookupMapAnalysis implements LookupMapAnalysis {
  static final Uri PACKAGE_LOOKUP_MAP =
      new Uri(scheme: 'package', path: 'lookup_map/lookup_map.dart');

  final ConstantSystem _constantSystem;

  final CommonElements _commonElements;

  final BackendHelpers _helpers;

  final BackendClasses _backendClasses;

  /// The resolved [ClassElement] associated with `LookupMap`.
  final ClassElement _typeLookupMapClass;

  /// The resolved [FieldElement] for `LookupMap._entries`.
  final FieldElement _entriesField;

  /// The resolved [FieldElement] for `LookupMap._key`.
  final FieldElement _keyField;

  /// The resolved [FieldElement] for `LookupMap._value`.
  final FieldElement _valueField;

  /// Constant instances of `LookupMap` and information about them tracked by
  /// this analysis.
  final Map<ConstantValue, _LookupMapInfo> _lookupMaps = {};

  /// Keys that we have discovered to be in use in the program.
  final _inUse = new Set<ConstantValue>();

  /// Internal helper to memoize the mapping between class elements and their
  /// corresponding type constants.
  final _typeConstants = <ClassElement, TypeConstantValue>{};

  /// Internal helper to memoize which classes (ignoring Type) override equals.
  ///
  /// Const keys of these types will not be tree-shaken because we can't
  /// statically guarantee that the program doesn't produce an equivalent key at
  /// runtime. Technically if we limit lookup-maps to check for identical keys,
  /// we could allow const instances of these types.  However, we internally use
  /// a hash map within lookup-maps today, so we need this restriction.
  final _typesWithEquals = <ClassElement, bool>{};

  /// Pending work to do if we discover that a new key is in use. For each key
  /// that we haven't seen, we record the list of lookup-maps that contain an
  /// entry with that key.
  final _pending = <ConstantValue, List<_LookupMapInfo>>{};

  final StagedWorldImpactBuilder _impactBuilder =
      new StagedWorldImpactBuilder();

  _LookupMapAnalysis(
      this._constantSystem,
      this._commonElements,
      this._helpers,
      this._backendClasses,
      this._entriesField,
      this._keyField,
      this._valueField,
      this._typeLookupMapClass);

  /// Compute the [WorldImpact] for the constants registered since last flush.
  WorldImpact flush() {
    return _impactBuilder.flush();
  }

  /// Whether [constant] is an instance of a `LookupMap`.
  bool isLookupMap(ConstantValue constant) {
    if (constant is ConstructedConstantValue) {
      ResolutionInterfaceType type = constant.type;
      return type.element.isSubclassOf(_typeLookupMapClass);
    }
    return false;
  }

  /// Registers an instance of a lookup-map with the analysis.
  void registerLookupMapReference(ConstantValue lookupMap) {
    assert(isLookupMap(lookupMap));
    _lookupMaps.putIfAbsent(
        lookupMap, () => new _LookupMapInfo(lookupMap, this).._updateUsed());
  }

  /// Whether [key] is a constant value whose type overrides equals.
  bool _overridesEquals(ConstantValue key) {
    if (key is ConstructedConstantValue) {
      ClassElement element = key.type.element;
      return _typesWithEquals.putIfAbsent(
          element, () => !element.lookupMember('==').enclosingClass.isObject);
    }
    return false;
  }

  /// Whether we need to preserve [key]. This is true for keys that are not
  /// candidates for tree-shaking in the first place (primitives and non-type
  /// const values overriding equals) and keys that we have seen in the program.
  bool _shouldKeep(ConstantValue key) =>
      key.isPrimitive || _inUse.contains(key) || _overridesEquals(key);

  void _addClassUse(ClassElement cls) {
    ConstantValue key = _typeConstants.putIfAbsent(
        cls,
        () => _constantSystem.createType(
            _commonElements, _backendClasses, cls.rawType));
    _addUse(key);
  }

  /// Record that [key] is used and update every lookup map that contains it.
  void _addUse(ConstantValue key) {
    if (_inUse.add(key)) {
      _pending[key]?.forEach((info) => info._markUsed(key));
      _pending.remove(key);
    }
  }

  /// If [key] is a type, cache it in [_typeConstants].
  _registerTypeKey(ConstantValue key) {
    if (key is TypeConstantValue &&
        key.representedType is ResolutionInterfaceType) {
      ResolutionInterfaceType type = key.representedType;
      _typeConstants[type.element] = key;
    } else {
      // TODO(sigmund): report error?
    }
  }

  /// Callback from the enqueuer, invoked when [element] is instantiated.
  void registerInstantiatedClass(ClassElement element) {
    // TODO(sigmund): only add if .runtimeType is ever used
    _addClassUse(element);
  }

  /// Callback from the enqueuer, invoked when [type] is instantiated.
  void registerInstantiatedType(ResolutionInterfaceType type) {
    // TODO(sigmund): only add if .runtimeType is ever used
    _addClassUse(type.element);
    // TODO(sigmund): only do this when type-argument expressions are used?
    _addGenerics(type);
  }

  /// Records generic type arguments in [type], in case they are retrieved and
  /// returned using a type-argument expression.
  void _addGenerics(ResolutionInterfaceType type) {
    if (!type.isGeneric) return;
    for (var arg in type.typeArguments) {
      if (arg is ResolutionInterfaceType) {
        _addClassUse(arg.element);
        // Note: this call was needed to generate correct code for
        // type_lookup_map/generic_type_test
        // TODO(sigmund): can we get rid of this?
        _impactBuilder.registerStaticUse(new StaticUse.staticInvoke(
            // TODO(johnniwinther): Find the right [CallStructure].
            _helpers.createRuntimeType,
            null));
        _addGenerics(arg);
      }
    }
  }

  /// Callback from the codegen enqueuer, invoked when a constant (which is
  /// possibly a const key or a type literal) is used in the program.
  void registerTypeConstant(ClassElement element) {
    _addClassUse(element);
  }

  void registerConstantKey(ConstantValue constant) {
    if (constant.isPrimitive || _overridesEquals(constant)) return;
    _addUse(constant);
  }

  void logSummary(void log(String message)) {
    // When --verbose is passed, we show the total number and set of keys that
    // were tree-shaken from lookup maps.
    var sb = new StringBuffer();
    int count = 0;
    for (var info in _lookupMaps.values) {
      for (var key in info.unusedEntries.keys) {
        if (count != 0) sb.write(',');
        sb.write(key.toDartText());
        count++;
      }
    }
    log(count == 0
        ? 'lookup-map: nothing was tree-shaken'
        : 'lookup-map: found $count unused keys ($sb)');
  }

  /// Callback from the backend, invoked when reaching the end of the enqueuing
  /// process, but before emitting the code. At this moment we have discovered
  /// all types used in the program and we can tree-shake anything that is
  /// unused.
  void onQueueClosed() {
    _lookupMaps.values.forEach((info) {
      assert(!info.emitted);
      info.emitted = true;
      info._prepareForEmission();
    });

    // Release resources.
    _lookupMaps.clear();
    _pending.clear();
    _inUse.clear();
  }
}

/// Internal information about the entries on a lookup-map.
class _LookupMapInfo {
  /// The original reference to the constant value.
  ///
  /// This reference will be mutated in place to remove it's entries when the
  /// map is first seen during codegen, and to restore them (or a subset of
  /// them) when we have finished discovering which entries are used. This has
  /// the side-effect that `orignal.getDependencies()` will be empty during
  /// most of codegen until we are ready to emit the constants. However,
  /// restoring the entries before emitting code lets us keep the emitter logic
  /// agnostic of this optimization.
  final ConstructedConstantValue original;

  /// Reference to the lookup map analysis to be able to refer to data shared
  /// accross infos.
  final _LookupMapAnalysis analysis;

  /// Whether we have already emitted this constant.
  bool emitted = false;

  /// Whether the `LookupMap` constant was built using the `LookupMap.pair`
  /// constructor.
  bool singlePair;

  /// Entries in the lookup map whose keys have not been seen in the rest of the
  /// program.
  Map<ConstantValue, ConstantValue> unusedEntries =
      <ConstantValue, ConstantValue>{};

  /// Entries that have been used, and thus will be part of the generated code.
  Map<ConstantValue, ConstantValue> usedEntries =
      <ConstantValue, ConstantValue>{};

  /// Creates and initializes the information containing all keys of the
  /// original map marked as unused.
  _LookupMapInfo(this.original, this.analysis) {
    ConstantValue key = original.fields[analysis._keyField];
    singlePair = !key.isNull;

    if (singlePair) {
      unusedEntries[key] = original.fields[analysis._valueField];

      // Note: we modify the constant in-place, see comment in [original].
      original.fields[analysis._keyField] = new NullConstantValue();
      original.fields[analysis._valueField] = new NullConstantValue();
    } else {
      ListConstantValue list = original.fields[analysis._entriesField];
      List<ConstantValue> keyValuePairs = list.entries;
      for (int i = 0; i < keyValuePairs.length; i += 2) {
        ConstantValue key = keyValuePairs[i];
        unusedEntries[key] = keyValuePairs[i + 1];
      }

      // Note: we modify the constant in-place, see comment in [original].
      original.fields[analysis._entriesField] =
          new ListConstantValue(list.type, []);
    }
  }

  /// Check every key in unusedEntries and mark it as used if the analysis has
  /// already discovered them. This is meant to be called once to finalize
  /// initialization after constructing an instance of this class. Afterwards,
  /// we call [_markUsed] on each individual key as it gets discovered.
  void _updateUsed() {
    // Note: we call toList because `_markUsed` modifies the map.
    for (ConstantValue key in unusedEntries.keys.toList()) {
      analysis._registerTypeKey(key);
      if (analysis._shouldKeep(key)) {
        _markUsed(key);
      } else {
        analysis._pending.putIfAbsent(key, () => []).add(this);
      }
    }
  }

  /// Marks that [key] has been seen, and thus, the corresponding entry in this
  /// map should be considered reachable.
  _markUsed(ConstantValue key) {
    assert(!emitted);
    assert(unusedEntries.containsKey(key));
    assert(!usedEntries.containsKey(key));
    ConstantValue constant = unusedEntries.remove(key);
    usedEntries[key] = constant;
    analysis._impactBuilder
        .registerConstantUse(new ConstantUse.lookupMap(constant));
  }

  /// Restores [original] to contain all of the entries marked as possibly used.
  void _prepareForEmission() {
    ListConstantValue originalEntries = original.fields[analysis._entriesField];
    ResolutionInterfaceType listType = originalEntries.type;
    List<ConstantValue> keyValuePairs = <ConstantValue>[];
    usedEntries.forEach((key, value) {
      keyValuePairs.add(key);
      keyValuePairs.add(value);
    });

    // Note: we are restoring the entries here, see comment in [original].
    if (singlePair) {
      assert(keyValuePairs.length == 0 || keyValuePairs.length == 2);
      if (keyValuePairs.length == 2) {
        original.fields[analysis._keyField] = keyValuePairs[0];
        original.fields[analysis._valueField] = keyValuePairs[1];
      }
    } else {
      original.fields[analysis._entriesField] =
          new ListConstantValue(listType, keyValuePairs);
    }
  }
}

final _validLookupMapVersionConstraint = new VersionConstraint.parse('^0.0.1');
