// Copyright (c) 2013, 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 universe.side_effects;

class SideEffects {
  // Changes flags.
  static const int FLAG_CHANGES_INDEX = 0;
  static const int FLAG_CHANGES_INSTANCE_PROPERTY = FLAG_CHANGES_INDEX + 1;
  static const int FLAG_CHANGES_STATIC_PROPERTY =
      FLAG_CHANGES_INSTANCE_PROPERTY + 1;
  static const int FLAG_CHANGES_COUNT = FLAG_CHANGES_STATIC_PROPERTY + 1;

  // Depends flags (one for each changes flag).
  static const int FLAG_DEPENDS_ON_INDEX_STORE = FLAG_CHANGES_COUNT;
  static const int FLAG_DEPENDS_ON_INSTANCE_PROPERTY_STORE =
      FLAG_DEPENDS_ON_INDEX_STORE + 1;
  static const int FLAG_DEPENDS_ON_STATIC_PROPERTY_STORE =
      FLAG_DEPENDS_ON_INSTANCE_PROPERTY_STORE + 1;
  static const int FLAG_DEPENDS_ON_COUNT =
      FLAG_DEPENDS_ON_STATIC_PROPERTY_STORE + 1;

  int _flags = 0;

  SideEffects() {
    setAllSideEffects();
    setDependsOnSomething();
  }

  SideEffects.empty() {
    clearAllDependencies();
    clearAllSideEffects();
  }

  SideEffects.fromFlags(this._flags);

  bool operator ==(other) => _flags == other._flags;

  int get hashCode => throw new UnsupportedError('SideEffects.hashCode');

  bool _getFlag(int position) => (_flags & (1 << position)) != 0;
  void _setFlag(int position) {
    _flags |= (1 << position);
  }

  void _clearFlag(int position) {
    _flags &= ~(1 << position);
  }

  int getChangesFlags() => _flags & ((1 << FLAG_CHANGES_COUNT) - 1);
  int getDependsOnFlags() {
    return (_flags & ((1 << FLAG_DEPENDS_ON_COUNT) - 1)) >> FLAG_CHANGES_COUNT;
  }

  bool hasSideEffects() => getChangesFlags() != 0;
  bool dependsOnSomething() => getDependsOnFlags() != 0;

  void setAllSideEffects() {
    _flags |= ((1 << FLAG_CHANGES_COUNT) - 1);
  }

  void clearAllSideEffects() {
    _flags &= ~((1 << FLAG_CHANGES_COUNT) - 1);
  }

  void setDependsOnSomething() {
    int count = FLAG_DEPENDS_ON_COUNT - FLAG_CHANGES_COUNT;
    _flags |= (((1 << count) - 1) << FLAG_CHANGES_COUNT);
  }

  void clearAllDependencies() {
    int count = FLAG_DEPENDS_ON_COUNT - FLAG_CHANGES_COUNT;
    _flags &= ~(((1 << count) - 1) << FLAG_CHANGES_COUNT);
  }

  bool dependsOnStaticPropertyStore() {
    return _getFlag(FLAG_DEPENDS_ON_STATIC_PROPERTY_STORE);
  }

  void setDependsOnStaticPropertyStore() {
    _setFlag(FLAG_DEPENDS_ON_STATIC_PROPERTY_STORE);
  }

  void clearDependsOnStaticPropertyStore() {
    _clearFlag(FLAG_DEPENDS_ON_STATIC_PROPERTY_STORE);
  }

  void setChangesStaticProperty() {
    _setFlag(FLAG_CHANGES_STATIC_PROPERTY);
  }

  void clearChangesStaticProperty() {
    _clearFlag(FLAG_CHANGES_STATIC_PROPERTY);
  }

  bool changesStaticProperty() => _getFlag(FLAG_CHANGES_STATIC_PROPERTY);

  bool dependsOnIndexStore() => _getFlag(FLAG_DEPENDS_ON_INDEX_STORE);
  void setDependsOnIndexStore() {
    _setFlag(FLAG_DEPENDS_ON_INDEX_STORE);
  }

  void clearDependsOnIndexStore() {
    _clearFlag(FLAG_DEPENDS_ON_INDEX_STORE);
  }

  void setChangesIndex() {
    _setFlag(FLAG_CHANGES_INDEX);
  }

  void clearChangesIndex() {
    _clearFlag(FLAG_CHANGES_INDEX);
  }

  bool changesIndex() => _getFlag(FLAG_CHANGES_INDEX);

  bool dependsOnInstancePropertyStore() {
    return _getFlag(FLAG_DEPENDS_ON_INSTANCE_PROPERTY_STORE);
  }

  void setDependsOnInstancePropertyStore() {
    _setFlag(FLAG_DEPENDS_ON_INSTANCE_PROPERTY_STORE);
  }

  void clearDependsOnInstancePropertyStore() {
    _setFlag(FLAG_DEPENDS_ON_INSTANCE_PROPERTY_STORE);
  }

  void setChangesInstanceProperty() {
    _setFlag(FLAG_CHANGES_INSTANCE_PROPERTY);
  }

  void clearChangesInstanceProperty() {
    _clearFlag(FLAG_CHANGES_INSTANCE_PROPERTY);
  }

  bool changesInstanceProperty() => _getFlag(FLAG_CHANGES_INSTANCE_PROPERTY);

  static int computeDependsOnFlags(int flags) => flags << FLAG_CHANGES_COUNT;

  bool dependsOn(int dependsFlags) => (_flags & dependsFlags) != 0;

  void add(SideEffects other) {
    _flags |= other._flags;
  }

  void setTo(SideEffects other) {
    _flags = other._flags;
  }

  int get flags => _flags;

  String toString() {
    StringBuffer buffer = new StringBuffer();
    buffer.write('Depends on');
    if (dependsOnIndexStore()) buffer.write(' []');
    if (dependsOnInstancePropertyStore()) buffer.write(' field store');
    if (dependsOnStaticPropertyStore()) buffer.write(' static store');
    if (!dependsOnSomething()) buffer.write(' nothing');
    buffer.write(', Changes');
    if (changesIndex()) buffer.write(' []');
    if (changesInstanceProperty()) buffer.write(' field');
    if (changesStaticProperty()) buffer.write(' static');
    if (!hasSideEffects()) buffer.write(' nothing');
    buffer.write('.');
    return buffer.toString();
  }
}
