// 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 dart2js.js_emitter.constant_ordering;

import '../constants/values.dart';
import '../elements/entities.dart' show ClassEntity, FieldEntity, MemberEntity;
import '../elements/types.dart';
import 'sorter.dart' show Sorter;

/// A canonical but arbitrary ordering of constants. The ordering is 'stable'
/// under perturbation of the source.
abstract class ConstantOrdering {
  factory ConstantOrdering(Sorter sorter) = _ConstantOrdering;

  int compare(ConstantValue a, ConstantValue b);
}

class _ConstantOrdering
    implements ConstantOrdering, ConstantValueVisitor<int, ConstantValue> {
  final Sorter _sorter;
  _DartTypeOrdering _dartTypeOrdering;
  _ConstantOrdering(this._sorter) {
    _dartTypeOrdering = _DartTypeOrdering(this);
  }

  @override
  int compare(ConstantValue a, ConstantValue b) => compareValues(a, b);

  int compareValues(ConstantValue a, ConstantValue b) {
    if (identical(a, b)) return 0;
    int r = a.kind.index.compareTo(b.kind.index);
    if (r != 0) return r;
    return a.accept(this, b);
  }

  static int compareLists<S, T>(int compare(S a, T b), List<S> a, List<T> b) {
    int r = a.length.compareTo(b.length);
    if (r != 0) return r;
    for (int i = 0; i < a.length; i++) {
      r = compare(a[i], b[i]);
      if (r != 0) return r;
    }
    return 0;
  }

  int compareClasses(ClassEntity a, ClassEntity b) {
    int r = a.name.compareTo(b.name);
    if (r != 0) return r;
    return _sorter.compareClassesByLocation(a, b);
  }

  int compareMembers(MemberEntity a, MemberEntity b) {
    int r = a.name.compareTo(b.name);
    if (r != 0) return r;
    return _sorter.compareMembersByLocation(a, b);
  }

  int compareDartTypes(DartType a, DartType b) {
    return _dartTypeOrdering.compare(a, b);
  }

  @override
  int visitFunction(FunctionConstantValue a, FunctionConstantValue b) {
    return compareMembers(a.element, b.element);
  }

  @override
  int visitNull(NullConstantValue a, NullConstantValue b) {
    return 0;
  }

  @override
  int visitNonConstant(NonConstantValue a, NonConstantValue b) {
    return 0;
  }

  @override
  int visitInt(IntConstantValue a, IntConstantValue b) {
    return a.intValue.compareTo(b.intValue);
  }

  @override
  int visitDouble(DoubleConstantValue a, DoubleConstantValue b) {
    return a.doubleValue.compareTo(b.doubleValue);
  }

  @override
  int visitBool(BoolConstantValue a, BoolConstantValue b) {
    int aInt = a.boolValue ? 1 : 0;
    int bInt = b.boolValue ? 1 : 0;
    return aInt.compareTo(bInt);
  }

  @override
  int visitString(StringConstantValue a, StringConstantValue b) {
    String aString = a.stringValue;
    String bString = b.stringValue;
    return aString.compareTo(bString);
  }

  @override
  int visitList(ListConstantValue a, ListConstantValue b) {
    int r = compareLists(compareValues, a.entries, b.entries);
    if (r != 0) return r;
    return compareDartTypes(a.type, b.type);
  }

  @override
  int visitSet(SetConstantValue a, SetConstantValue b) {
    int r = compareLists(compareValues, a.values, b.values);
    if (r != 0) return r;
    return compareDartTypes(a.type, b.type);
  }

  @override
  int visitMap(MapConstantValue a, MapConstantValue b) {
    int r = compareLists(compareValues, a.keys, b.keys);
    if (r != 0) return r;
    r = compareLists(compareValues, a.values, b.values);
    if (r != 0) return r;
    return compareDartTypes(a.type, b.type);
  }

  @override
  int visitConstructed(ConstructedConstantValue a, ConstructedConstantValue b) {
    int r = compareDartTypes(a.type, b.type);
    if (r != 0) return r;

    // TODO(sra): Avoid all these tear-offs.
    List<FieldEntity> aFields = a.fields.keys.toList()..sort(compareMembers);
    List<FieldEntity> bFields = b.fields.keys.toList()..sort(compareMembers);

    r = compareLists(compareMembers, aFields, bFields);
    if (r != 0) return r;

    return compareLists(
        compareValues,
        aFields.map((field) => a.fields[field]).toList(),
        aFields.map((field) => b.fields[field]).toList());
  }

  @override
  int visitType(TypeConstantValue a, TypeConstantValue b) {
    int r = compareDartTypes(a.representedType, b.representedType);
    if (r != 0) return r;
    return compareDartTypes(a.type, b.type);
  }

  @override
  int visitInterceptor(InterceptorConstantValue a, InterceptorConstantValue b) {
    return compareClasses(a.cls, b.cls);
  }

  @override
  int visitDummyInterceptor(
      DummyInterceptorConstantValue a, DummyInterceptorConstantValue b) {
    // Never emitted.
    return 0;
  }

  @override
  int visitLateSentinel(
          LateSentinelConstantValue a, LateSentinelConstantValue b) =>
      0;

  @override
  int visitUnreachable(UnreachableConstantValue a, UnreachableConstantValue b) {
    // Never emitted.
    return 0;
  }

  @override
  int visitJsName(JsNameConstantValue a, JsNameConstantValue b) {
    // An opaque deferred JS AST reference to a name.
    return 0;
  }

  @override
  int visitDeferredGlobal(
      DeferredGlobalConstantValue a, DeferredGlobalConstantValue b) {
    int r = compareValues(a.referenced, b.referenced);
    if (r != 0) return r;
    return a.unit.compareTo(b.unit);
  }

  @override
  int visitInstantiation(
      InstantiationConstantValue a, InstantiationConstantValue b) {
    int r = compareValues(a.function, b.function);
    if (r != 0) return r;
    return compareLists(compareDartTypes, a.typeArguments, b.typeArguments);
  }
}

/// Visitor for distinguishing types by kind.
class _DartTypeKindVisitor implements DartTypeVisitor<int, Null> {
  const _DartTypeKindVisitor();

  static int kind(DartType type) {
    return const _DartTypeKindVisitor().visit(type);
  }

  @override
  int visit(DartType type, [_]) => type.accept(this, null);
  @override
  int visitFunctionType(FunctionType type, _) => 0;
  @override
  int visitInterfaceType(InterfaceType type, _) => 1;
  @override
  int visitFunctionTypeVariable(FunctionTypeVariable type, _) => 2;
  @override
  int visitTypeVariableType(TypeVariableType type, _) => 3;
  @override
  int visitNeverType(NeverType type, _) => 4;
  @override
  int visitDynamicType(DynamicType type, _) => 5;
  @override
  int visitVoidType(VoidType type, _) => 6;
  @override
  int visitAnyType(AnyType type, _) => 7;
  @override
  int visitErasedType(ErasedType type, _) => 8;
  @override
  int visitFutureOrType(FutureOrType type, _) => 9;
  @override
  int visitLegacyType(LegacyType type, _) => 10;
  @override
  int visitNullableType(NullableType type, _) => 11;
}

class _DartTypeOrdering extends DartTypeVisitor<int, DartType> {
  final _ConstantOrdering _constantOrdering;
  DartType _root;
  final List<FunctionTypeVariable> _leftFunctionTypeVariables = [];
  final List<FunctionTypeVariable> _rightFunctionTypeVariables = [];
  _DartTypeOrdering(this._constantOrdering);

  int compare(DartType a, DartType b) {
    if (a == b) return 0;
    int r =
        _DartTypeKindVisitor.kind(a).compareTo(_DartTypeKindVisitor.kind(b));
    if (r != 0) return r;
    _root = a;
    r = a.accept(this, b);
    _root = null;
    return r;
  }

  @override
  int visitLegacyType(covariant LegacyType type, covariant LegacyType other) =>
      compare(type.baseType, other.baseType);

  @override
  int visitNullableType(
          covariant NullableType type, covariant NullableType other) =>
      compare(type.baseType, other.baseType);

  @override
  int visitFutureOrType(
          covariant FutureOrType type, covariant FutureOrType other) =>
      compare(type.typeArgument, other.typeArgument);

  @override
  int visitNeverType(covariant NeverType type, covariant NeverType other) {
    throw UnsupportedError('Unreachable');
  }

  @override
  int visitVoidType(covariant VoidType type, covariant VoidType other) {
    throw UnsupportedError('Unreachable');
  }

  @override
  int visitTypeVariableType(
      covariant TypeVariableType type, covariant TypeVariableType other) {
    throw UnsupportedError(
        "Type variables are not expected in constants: '$type' in '$_root'");
  }

  @override
  int visitFunctionTypeVariable(covariant FunctionTypeVariable type,
      covariant FunctionTypeVariable other) {
    int leftIndex = _leftFunctionTypeVariables.indexOf(type);
    int rightIndex = _rightFunctionTypeVariables.indexOf(other);
    assert(leftIndex != -1);
    assert(rightIndex != -1);
    int r = leftIndex.compareTo(rightIndex);
    if (r != 0) return r;
    return compare(type.bound, other.bound);
  }

  @override
  int visitFunctionType(
      covariant FunctionType type, covariant FunctionType other) {
    int oldLeftLength = _leftFunctionTypeVariables.length;
    int oldRightLength = _rightFunctionTypeVariables.length;
    _leftFunctionTypeVariables.addAll(type.typeVariables);
    _rightFunctionTypeVariables.addAll(other.typeVariables);
    try {
      int r = _compareTypeArguments(type.parameterTypes, other.parameterTypes);
      if (r != 0) return r;
      r = _compareTypeArguments(
          type.optionalParameterTypes, other.optionalParameterTypes);
      if (r != 0) return r;
      r = _ConstantOrdering.compareLists((String a, String b) => a.compareTo(b),
          type.namedParameters, other.namedParameters);
      if (r != 0) return r;
      r = _compareTypeArguments(
          type.namedParameterTypes, other.namedParameterTypes);
      if (r != 0) return r;
      return compare(type.returnType, other.returnType);
    } finally {
      _leftFunctionTypeVariables.removeRange(
          oldLeftLength, _leftFunctionTypeVariables.length);
      _rightFunctionTypeVariables.removeRange(
          oldRightLength, _rightFunctionTypeVariables.length);
    }
  }

  @override
  int visitInterfaceType(
      covariant InterfaceType type, covariant InterfaceType other) {
    int r = _constantOrdering.compareClasses(type.element, other.element);
    if (r != 0) return r;
    return _compareTypeArguments(type.typeArguments, other.typeArguments);
  }

  @override
  int visitDynamicType(
      covariant DynamicType type, covariant DynamicType other) {
    throw UnsupportedError('Unreachable');
  }

  @override
  int visitErasedType(covariant ErasedType type, covariant ErasedType other) {
    throw UnsupportedError('Unreachable');
  }

  @override
  int visitAnyType(covariant AnyType type, covariant AnyType other) {
    throw UnsupportedError('Unreachable');
  }

  int _compareTypeArguments(
      List<DartType> aArguments, List<DartType> bArguments) {
    return _ConstantOrdering.compareLists(compare, aArguments, bArguments);
  }
}
