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


import "package:expect/expect.dart";
import "package:async_helper/async_helper.dart";

// The >>> operator is (again) supported by Dart
// (This test does not test int.operator>>>, such a test belongs in the corelib
// test collection. Const uses of int.operator>>> is tested elsewhere as well).

/// Syntactically tricky coincidences containing >>> and >>>=.
/// DO NOT FORMAT THIS FILE. There should not be a space between >>> and =.
typedef F3<T extends List<List<int>>>= T Function();
typedef F4<T extends List<List<List<int>>>>= T Function();
typedef F5<T extends List<List<List<List<int>>>>>= T Function();
typedef F6<T extends List<List<List<List<List<int>>>>>>= T Function();
class E3<T extends List<List<int>>> {}
class E4<T extends List<List<List<int>>>> {}
class E5<T extends List<List<List<List<int>>>>> {}
class E6<T extends List<List<List<List<List<int>>>>>> {}

main() {
  // >>> is an overridable operator.
  const c1 = C(1);
  const c2 = C(2);
  Expect.identical(c2, c1 >>> c2);

  /// It combines to an assignment operator.
  C c = c1;
  c >>>= c2;
  Expect.identical(c2, c);

  // Operand needs to have correct type for typed invocation.
  c1 //
     >>> 4 //# 01: compile-time error
     >>> "string" //# 02: compile-time error
  ;
  c //
     >>>= 4 //# 03: compile-time error
  ;

  // Dynamic invocations are allowed, and check types at run-time.
  dynamic d = c1;
  Expect.identical(c2, d >>> c2);
  Expect.throws(() => d >>> 4);

  // There is a symbol for >>>, both as constructed and literal.
  Expect.identical(const Symbol(">>>"), #>>>);

  // No such method can catch dynamic invocations of >>>:
  dynamic nsm = NSM();
  Invocation invocation = nsm >>> c2;
  Expect.isTrue(invocation.isMethod);
  Expect.isFalse(invocation.isAccessor);
  Expect.equals(#>>>, invocation.memberName);
  Expect.equals(1, invocation.positionalArguments.length);
  Expect.identical(c2, invocation.positionalArguments[0]);
  Expect.equals(0, invocation.namedArguments.length);

  invocation = (nsm >>>= c2);
  Expect.isTrue(invocation.isMethod);
  Expect.isFalse(invocation.isAccessor);
  Expect.equals(#>>>, invocation.memberName);
  Expect.equals(1, invocation.positionalArguments.length);
  Expect.identical(c2, invocation.positionalArguments[0]);
  Expect.equals(0, invocation.namedArguments.length);

  // And unimplemented interface methods.
  ShiftNSM shnsm = ShiftNSM();
  invocation = shnsm >>> c2;
  Expect.isTrue(invocation.isMethod);
  Expect.isFalse(invocation.isAccessor);
  Expect.equals(#>>>, invocation.memberName);
  Expect.equals(1, invocation.positionalArguments.length);
  Expect.identical(c2, invocation.positionalArguments[0]);
  Expect.equals(0, invocation.namedArguments.length);

  // If there is an interface, we must match it, even if the call
  // otherwise goes to noSuchMethod.
  shnsm //
      >>> 4 //# 04: compile-time error
  ;

  /// A type error in the nSM return value is caught.
  dynamic badNSM = BadNSM();
  Expect.throws(() => badNSM >>> "not an int", (e) => e != "Unreachable");
  Expect.throws(() => badNSM >>> 4, (e) => e != "Unreachable");

  asyncStart();
  () async {
    // Operands can be asynchronous.
    var fc1 = Future.value(c1);
    var fc2 = Future.value(c2);
    Expect.identical(c2, (await fc1) >>> (await fc2));
    /// The operator itself can be async.
    var async = Async();
    Expect.identical(c1, await (async >>> c1));

    var asyncStar = AsyncStar();
    int count = 0;
    await for (var v in asyncStar >>> c1) {
      count++;
      Expect.identical(c1, v);
    }
    Expect.equals(1, count);
    asyncEnd();
  }();

  {
    var syncStar = SyncStar();
    int count = 0;
    for (var v in syncStar >>> c1) {
      count++;
      Expect.identical(c1, v);
    }
    Expect.equals(1, count);
  }

  // >>> has same precedence as >> (and <<), is left associative.
  // Binds weaker than addition/multiplication, stronger than other bitwise
  // operators and comparisons.
  final a = Assoc("*");
  Expect.equals("((~*)>>>(~*))", "${~a >>> ~a}");
  Expect.equals("((*+*)>>>(*+*))", "${a + a >>> a + a}");
  Expect.equals("((*/*)>>>(*/*))", "${a / a >>> a / a}");
  Expect.equals("(((*>>*)>>>*)>>*)", "${a >> a >>> a >> a}");
  Expect.equals("((*&(*>>>*))&*)", "${a & a >>> a & a}");
  Expect.equals("((*|(*>>>*))|*)", "${a | a >>> a | a}");
  Expect.equals("((*^(*>>>*))^*)", "${a ^ a >>> a ^ a}");
  Expect.equals("(*<(*>>>*))", "${a < a >>> a}");
  Expect.equals("((*>>>*)<*)", "${a >>> a < a}");

  var res = a;
  res >>>= a;
  res >>>= a;
  Expect.equals("((*>>>*)>>>*)", "$res");

  // Exercise the type declarations below.
  E3<List<List<int>>>();
  E4<List<List<List<int>>>>();
  E5<List<List<List<List<int>>>>>();
  E6<List<List<List<List<List<int>>>>>>();
  Expect.type<F3<List<List<int>>>>(() => <List<int>>[]);
  Expect.type<F4<List<List<List<int>>>>>(() => <List<List<int>>>[]);
  Expect.type<F5<List<List<List<List<int>>>>>>(() => <List<List<List<int>>>>[]);
  Expect.type<F6<List<List<List<List<List<int>>>>>>>(
      () => <List<List<List<List<int>>>>>[]);
}

/// Class with a simple overridden `operator>>>`.
class C {
  final int id;
  const C(this. id);
  C operator >>>(C other) => other;
  String toString() => "C($id)";
}

/// Invalid declarations of `>>>` operator.
class Invalid {
  // Overridable operator must have exactly one required parameter.
  Object operator>>>() => null;  //# arg0: compile-time error
  Object operator>>>(v1, v2) => null;  //# arg2: compile-time error
  Object operator>>>([v1]) => null;  //# argOpt: compile-time error
  Object operator>>>({v1}) => null;  //# argNam: compile-time error
}

/// Class with noSuchMethod and no `>>>` operator.
class NSM {
  dynamic noSuchMethod(Invocation invocation) {
    return invocation;
  }
}

/// Class with nSM and abstract `>>>` (implicit typed forwarder).
class ShiftNSM extends NSM {
  dynamic operator>>>(C o);
}

/// Class with nSM and abstract `>>>` where nSM returns wrong type.
class BadNSM {
  int operator>>>(int n);
  dynamic noSuchMethod(Invocation i) {
    if (i.memberName == #>>>) {
      if (i.positionalArguments.first is! int) throw "Unreachable";
      return "notAnInt";
    }
    return super.noSuchMethod(i);
  }
}

/// Class with an `async` implementation of `operator >>>`
class Async {
  Future<C> operator >>>(C value) async => value;
}

/// Class with an `async*` implementation of `operator >>>`
class AsyncStar {
  Stream<C> operator >>>(C value) async* {
    yield value;
  }
}

/// Class with a `sync*` implementation of `operator >>>`
class SyncStar {
  Iterable<C> operator >>>(C value) sync* {
    yield value;
  }
}

/// Helper class to record precedence and associativity of operators.
class Assoc {
  final String ops;
  Assoc(this.ops);
  Assoc operator ~() => Assoc("(~${this})");
  Assoc operator +(Assoc other) => Assoc("(${this}+$other)");
  Assoc operator /(Assoc other) => Assoc("(${this}/$other)");
  Assoc operator &(Assoc other) => Assoc("(${this}&$other)");
  Assoc operator |(Assoc other) => Assoc("(${this}|$other)");
  Assoc operator ^(Assoc other) => Assoc("(${this}^$other)");
  Assoc operator >(Assoc other) => Assoc("(${this}>$other)");
  Assoc operator >>(Assoc other) => Assoc("(${this}>>$other)");
  Assoc operator >>>(Assoc other) => Assoc("(${this}>>>$other)");
  Assoc operator <(Assoc other) => Assoc("(${this}<$other)");
  Assoc operator >=(Assoc other) => Assoc("(${this}>=$other)");
  Assoc operator <=(Assoc other) => Assoc("(${this}<=$other)");
  String toString() => ops;
}
