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

/// Declares classes which describe a call: selectors and arguments.
library vm.transformations.type_flow.calls;

import 'dart:core' hide Type;

import 'package:kernel/ast.dart';

import 'types.dart';
import 'utils.dart';

enum CallKind {
  Method, // x.foo(..) or foo()
  PropertyGet, // ... x.foo ...
  PropertySet, // x.foo = ...
  FieldInitializer, // run initializer of a field
  SetFieldInConstructor, // foo = ... in initializer list in a constructor
}

/// [Selector] encapsulates the way of calling (at the call site).
abstract class Selector {
  /// Call kind: how call is performed?
  final CallKind callKind;

  Selector(this.callKind);

  /// Interface or concrete target, may be null.
  Member get member;

  /// Selector name.
  Name get name => member.name;

  bool get isSetter => (callKind == CallKind.PropertySet);

  @override
  int get hashCode => callKind.hashCode;

  @override
  bool operator ==(other) =>
      identical(this, other) || other is Selector && other.callKind == callKind;

  /// Static approximation of Dart return type.
  DartType get staticReturnType {
    if (member == null) {
      return const DynamicType();
    }
    switch (callKind) {
      case CallKind.Method:
        return (member is Procedure)
            ? member.function.returnType
            : const BottomType();
      case CallKind.PropertyGet:
        return member.getterType;
      case CallKind.PropertySet:
      case CallKind.FieldInitializer:
      case CallKind.SetFieldInConstructor:
        return const BottomType();
    }
    return null;
  }

  bool memberAgreesToCallKind(Member member) {
    switch (callKind) {
      case CallKind.Method:
        return ((member is Procedure) &&
                !member.isGetter &&
                !member.isSetter) ||
            (member is Constructor);
      case CallKind.PropertyGet:
        return (member is Field) || ((member is Procedure) && member.isGetter);
      case CallKind.PropertySet:
        return (member is Field) || ((member is Procedure) && member.isSetter);
      case CallKind.FieldInitializer:
      case CallKind.SetFieldInConstructor:
        return member is Field;
    }
    return false;
  }

  String get _callKindPrefix {
    switch (callKind) {
      case CallKind.Method:
        return '';
      case CallKind.PropertyGet:
        return 'get ';
      case CallKind.PropertySet:
      case CallKind.SetFieldInConstructor:
        return 'set ';
      case CallKind.FieldInitializer:
        return 'init ';
    }
    return '';
  }
}

/// Direct call to [member].
class DirectSelector extends Selector {
  final Member member;

  DirectSelector(this.member, {CallKind callKind = CallKind.Method})
      : super(callKind) {
    assertx((callKind == CallKind.Method) ||
        (callKind == CallKind.PropertyGet) ||
        memberAgreesToCallKind(member));
  }

  @override
  int get hashCode => (super.hashCode ^ member.hashCode) & kHashMask;

  @override
  bool operator ==(other) =>
      identical(this, other) ||
      other is DirectSelector && super == (other) && other.member == member;

  @override
  String toString() => 'direct ${_callKindPrefix}[$member]';
}

/// Interface call via known interface target [member].
class InterfaceSelector extends Selector {
  final Member member;

  InterfaceSelector(this.member, {CallKind callKind = CallKind.Method})
      : super(callKind);

  @override
  int get hashCode => (super.hashCode ^ member.hashCode + 31) & kHashMask;

  @override
  bool operator ==(other) =>
      identical(this, other) ||
      other is InterfaceSelector && super == (other) && other.member == member;

  @override
  String toString() => '${_callKindPrefix}[$member]';
}

/// Virtual call (using 'this' as a receiver).
class VirtualSelector extends InterfaceSelector {
  VirtualSelector(Member member, {CallKind callKind = CallKind.Method})
      : super(member, callKind: callKind);

  @override
  int get hashCode => (super.hashCode + 37) & kHashMask;

  @override
  bool operator ==(other) =>
      identical(this, other) || other is VirtualSelector && super == (other);

  @override
  String toString() => 'virtual ${_callKindPrefix}[$member]';
}

/// Dynamic call.
class DynamicSelector extends Selector {
  @override
  final Name name;

  static final kCall = new DynamicSelector(CallKind.Method, new Name('call'));

  DynamicSelector(CallKind callKind, this.name) : super(callKind);

  @override
  Member get member => null;

  @override
  int get hashCode => (super.hashCode ^ name.hashCode + 37) & kHashMask;

  @override
  bool operator ==(other) =>
      identical(this, other) ||
      other is DynamicSelector && super == (other) && other.name == name;

  @override
  String toString() => 'dynamic ${_callKindPrefix}[$name]';
}

/// Arguments passed to a call, including implicit receiver argument.
// TODO(alexmarkov): take type arguments into account
class Args<T extends TypeExpr> {
  final List<T> values;
  final List<String> names;

  // Whether it is not known which optional arguments are passed or not.
  final bool unknownArity;

  int _hashCode;

  Args(this.values,
      {this.names = const <String>[], this.unknownArity = false}) {
    assertx(isSorted(names));
  }

  Args.withReceiver(Args<T> args, T receiver)
      : values = new List.from(args.values),
        names = args.names,
        unknownArity = args.unknownArity {
    values[0] = receiver;
  }

  int get positionalCount => values.length - names.length;
  int get namedCount => names.length;

  T get receiver => values[0];

  @override
  int get hashCode => _hashCode ??= _computeHashCode();

  int _computeHashCode() {
    int hash = 1231;
    for (var v in values) {
      hash = (((hash * 31) & kHashMask) + v.hashCode) & kHashMask;
    }
    for (var n in names) {
      hash = (((hash * 31) & kHashMask) + n.hashCode) & kHashMask;
    }
    if (unknownArity) hash ^= -1;
    return hash;
  }

  @override
  bool operator ==(other) {
    if (identical(this, other)) return true;
    if (other is Args<T> &&
        (this.values.length == other.values.length) &&
        (this.names.length == other.names.length)) {
      for (int i = 0; i < values.length; i++) {
        if (values[i] != other.values[i]) {
          return false;
        }
      }
      for (int i = 0; i < names.length; i++) {
        if (names[i] != other.names[i]) {
          return false;
        }
      }
      return unknownArity == other.unknownArity;
    }
    return false;
  }

  @override
  String toString() {
    StringBuffer buf = new StringBuffer();
    buf.write("(");
    for (int i = 0; i < positionalCount; i++) {
      if (i != 0) {
        buf.write(", ");
      }
      buf.write(values[i]);
    }
    for (int i = 0; i < names.length; i++) {
      if (positionalCount + i != 0) {
        buf.write(", ");
      }
      buf.write(names[i]);
      buf.write(': ');
      buf.write(values[positionalCount + i]);
    }
    if (unknownArity) {
      buf.write(", <unknown arity>)");
    } else {
      buf.write(")");
    }
    return buf.toString();
  }
}
