// Copyright (c) 2011, 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.
// Test various setter situations, testing special cases in optimizing compiler.
// VMOptions=--optimization-counter-threshold=10 --no-use-osr

import "package:expect/expect.dart";

class A {
  int field = 0;
}

class B extends A {}

void sameImplicitSetter() {
  oneTarget(var a, var v) {
    a.field = v;
  }

  A a = new A();
  B b = new B();
  // Optimize 'oneTarget' for one class, one target.
  for (int i = 0; i < 20; i++) {
    oneTarget(a, 5);
    Expect.equals(5, a.field);
  }
  // Deoptimize 'oneTarget', since class B is not expected.
  oneTarget(b, 6);
  Expect.equals(6, b.field);
  // Optimize 'oneTarget' for A and B classes, one target.
  for (int i = 0; i < 20; i++) {
    oneTarget(a, 7);
    Expect.equals(7, a.field);
  }
  oneTarget(b, 8);
  Expect.equals(8, b.field);
}

// Deoptimize when no feedback exists.
void setterNoFeedback() {
  maybeSet(var a, var v, bool set_it) {
    if (set_it) {
      return a.field = v;
    }
    return -1;
  }

  A a = new A();
  for (int i = 0; i < 20; i++) {
    var r = maybeSet(a, 5, false);
    Expect.equals(0, a.field);
    Expect.equals(-1, r);
  }
  var r = maybeSet(a, 5, true);
  Expect.equals(5, a.field);
  Expect.equals(5, r);
  for (int i = 0; i < 20; i++) {
    var r = maybeSet(a, 6, true);
    Expect.equals(6, a.field);
    Expect.equals(6, r);
  }
}

// Check non-implicit setter
class X {
  int pField = 0;
  set field(v) {
    pField = v;
  }

  get field => 10;
}

void sameNotImplicitSetter() {
  oneTarget(var a, var v) {
    return a.field = v;
  }

  incField(var a) {
    a.field++;
  }

  X x = new X();
  for (int i = 0; i < 20; i++) {
    var r = oneTarget(x, 3);
    Expect.equals(3, x.pField);
    Expect.equals(3, r);
  }
  oneTarget(x, 0);
  for (int i = 0; i < 20; i++) {
    incField(x);
  }
  Expect.equals(11, x.pField);
}

class Y {
  int field = 0;
}

multiImplicitSetter() {
  oneTarget(var a, var v) {
    return a.field = v;
  }

  // Both classes 'Y' and 'A' have a distinct field getter.
  A a = new A();
  Y y = new Y();
  for (int i = 0; i < 20; i++) {
    var r = oneTarget(a, 5);
    Expect.equals(5, a.field);
    Expect.equals(5, r);
    r = oneTarget(y, 6);
    Expect.equals(6, y.field);
    Expect.equals(6, r);
  }
}

class Z {
  int pField = 0;
  set field(v) {
    pField = v;
  }

  get field => 10;
}

multiNotImplicitSetter() {
  oneTarget(var a, var v) {
    return a.field = v;
  }

  Y y = new Y();
  Z z = new Z();
  for (int i = 0; i < 20; i++) {
    var r = oneTarget(y, 8);
    Expect.equals(8, y.field);
    Expect.equals(8, r);
    r = oneTarget(z, 12);
    Expect.equals(12, z.pField);
    Expect.equals(12, r);
  }
  A a = new A();
  var r = oneTarget(a, 11);
  Expect.equals(11, a.field);
  Expect.equals(11, r);
}

void main() {
  sameImplicitSetter();
  setterNoFeedback();
  sameNotImplicitSetter();

  multiImplicitSetter();
  multiNotImplicitSetter();
}
