// 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.

// SharedOptions=--enable-experiment=constant-update-2018

import 'package:expect/expect.dart';

import 'utils.dart';

// Typed as dynamic to also test spreading a value of type dynamic.
const dynamic list = [1, 2, 3];
const dynamic map = {1: 1, 2: 2, 3: 3};
const dynamic set = {1, 2, 3};

const dynamic dynamicTrue = true;
const Object objectTrue = true;

void main() {
  testList();
  testMap();
  testSet();
  testShortCircuit();
  testDuplicateKeys();
  testKeyOrder();
}

void testList() {
  // Then if true.
  Expect.identical(list, const <int>[1, if (true) 2, 3]);

  // Nothing if false and no else.
  Expect.identical(list, const <int>[1, if (false) 9, 2, 3]);

  // Else if false.
  Expect.identical(list, const <int>[1, if (false) 9 else 2, 3]);

  // Only if.
  Expect.identical(const [1], const <int>[if (true) 1]);

  // If at beginning.
  Expect.identical(list, const <int>[if (true) 1, 2, 3]);

  // If in middle.
  Expect.identical(list, const <int>[1, if (true) 2, 3]);

  // If at end.
  Expect.identical(list, const <int>[1, 2, if (true) 3]);

  // Multiple ifs.
  Expect.identical(list,
      const <int>[if (true) 1, if (false) 9, 2, if (true) 3]);

  // Cast condition.
  Expect.identical(const [1], const <int>[if (dynamicTrue) 1]);
  Expect.identical(const [1], const <int>[if (objectTrue) 1]);

  // Does not flatten nested collection literal.
  Expect.identical(const [1], const [if (true) [1]].first);
  Expect.identical(const {1: 1}, const [if (true) {1: 1}].first);
  Expect.identical(const {1}, const [if (true) {1}].first);

  // Nested spread.
  Expect.identical(list,
      const <int>[if (true) ...<int>[1, 2], if (false) 9 else ...<int>[3]]);

  // Nested if in then.
  Expect.identical(const [1],
      const <int>[if (true) if (true) 1, if (true) if (false) 9]);

  // Nested if in else.
  Expect.identical(const [1], const <int>[if (false) 9 else if (true) 1]);
}

void testMap() {
  // Then if true.
  Expect.identical(map, const <int, int>{1: 1, if (true) 2: 2, 3: 3});

  // Nothing if false and no else.
  Expect.identical(map, const <int, int>{1: 1, if (false) 9: 9, 2: 2, 3: 3});

  // Else if false.
  Expect.identical(map,
      const <int, int>{1: 1, if (false) 9: 9 else 2: 2, 3: 3});

  // Only if.
  Expect.identical(const {1: 1}, const <int, int>{if (true) 1: 1});

  // If at beginning.
  Expect.identical(map, const <int, int>{if (true) 1: 1, 2: 2, 3: 3});

  // If in middle.
  Expect.identical(map, const <int, int>{1: 1, if (true) 2: 2, 3: 3});

  // If at end.
  Expect.identical(map, const <int, int>{1: 1, 2: 2, if (true) 3: 3});

  // Multiple ifs.
  Expect.identical(map,
      const <int, int>{if (true) 1: 1, if (false) 9: 9, 2: 2, if (true) 3: 3});

  // Cast condition.
  Expect.identical(const {1: 1}, const <int, int>{if (dynamicTrue) 1: 1});
  Expect.identical(const {1: 1}, const <int, int>{if (objectTrue) 1: 1});

  // Nested spread.
  Expect.identical(map, const <int, int>{
    if (true) ...<int, int>{1: 1, 2: 2},
    if (false) 9: 9 else ...<int, int>{3: 3}
  });

  // Nested if in then.
  Expect.identical(const {1: 1},
      const <int, int>{if (true) if (true) 1: 1, if (true) if (false) 9: 9});

  // Nested if in else.
  Expect.identical(const {1: 1},
      const <int, int>{if (false) 9: 9 else if (true) 1: 1});
}

void testSet() {
  // Then if true.
  Expect.identical(set, const <int>{1, if (true) 2, 3});

  // Nothing if false and no else.
  Expect.identical(set, const <int>{1, if (false) 9, 2, 3});

  // Else if false.
  Expect.identical(set, const <int>{1, if (false) 9 else 2, 3});

  // Only if.
  Expect.identical(const <int>{1}, const <int>{if (true) 1});

  // If at beginning.
  Expect.identical(set, const <int>{if (true) 1, 2, 3});

  // If in middle.
  Expect.identical(set, const <int>{1, if (true) 2, 3});

  // If at end.
  Expect.identical(set, const <int>{1, 2, if (true) 3});

  // Multiple ifs.
  Expect.identical(set,
      const <int>{if (true) 1, if (false) 9, 2, if (true) 3});

  // Cast condition.
  Expect.identical(const <int>{1}, const <int>{if (dynamicTrue) 1});
  Expect.identical(const <int>{1}, const <int>{if (objectTrue) 1});

  // Does not flatten nested collection literal.
  Expect.identical(const <int>[1], const <List<int>>{if (true) [1]}.first);
  Expect.identical(
      const <int, int>{1: 1}, const <Map<int, int>>{if (true) {1: 1}}.first);
  Expect.identical(const <int>{1}, const <Set<int>>{if (true) {1}}.first);

  // Nested spread.
  Expect.identical(set,
      const <int>{if (true) ...<int>[1, 2], if (false) 9 else ...<int>[3]});

  // Nested if in then.
  Expect.identical(const <int>{1},
      const <int>{if (true) if (true) 1, if (true) if (false) 9});

  // Nested if in else.
  Expect.identical(const <int>{1}, const <int>{if (false) 9 else if (true) 1});
}

void testShortCircuit() {
  // A const expression that throws does not cause a compile error if it occurs
  // inside an unchosen branch of an if.

  // Store null in a dynamically-typed constant to avoid the type error on "+".
  const dynamic nil = null;

  Expect.identical(const <int>[1],
      const <int>[if (true) 1, if (false) nil + 1]);
  Expect.identical(const <int>[1, 2],
      const <int>[if (true) 1 else nil + 1, if (false) nil + 1 else 2]);

  Expect.identical(const <int, int>{1: 1}, const <int, int>{
    if (true) 1: 1,
    if (false) nil + 1: 9,
    if (false) 9: nil + 1
  });
  Expect.identical(const <int, int>{1: 1, 2: 2}, const <int, int>{
    if (true) 1: 1 else nil + 1: 9,
    if (false) 9: nil + 1 else 2: 2
  });

  Expect.identical(const <int>{1},
      const <int>{if (true) 1, if (false) nil + 1});
  Expect.identical(const <int>{1, 2},
      const <int>{if (true) 1 else nil + 1, if (false) nil + 1 else 2});

  // A const expression whose value isn't the right type does not cause a
  // compile error if it occurs inside an unchosen branch.
  const dynamic nonInt = "s";

  Expect.identical(const <int>[1], const <int>[if (true) 1, if (false) nonInt]);
  Expect.identical(const <int>[1, 2],
      const <int>[if (true) 1 else nonInt, if (false) nonInt else 2]);

  Expect.identical(const <int, int>{1: 1}, const <int, int>{
    if (true) 1: 1,
    if (false) nonInt: 9,
    if (false) 9: nonInt
  });
  Expect.identical(const <int, int>{1: 1, 2: 2}, const <int, int>{
    if (true) 1: 1 else nonInt: 9,
    if (false) 9: nonInt else 2: 2
  });

  Expect.identical(const <int>{1}, const <int>{if (true) 1, if (false) nonInt});
  Expect.identical(const <int>{1, 2},
      const <int>{if (true) 1 else nonInt, if (false) nonInt else 2});
}

void testDuplicateKeys() {
  // Duplicate keys from unchosen branches are not an error.
  Expect.mapEquals(map, <int, int>{
    1: 1,
    if (false) 1: 1,
    if (true) 2: 2 else 3: 3,
    3: 3
  });

  Expect.setEquals(set, const <int>{1, if (false) 1, if (true) 2 else 3, 3});
}

void testKeyOrder() {
  // Canonicalization isn't affected by which elements are conditional.
  Expect.identical(map,
      const <int, int>{1: 1, if (true) 2: 2, if (false) 9: 9, 3: 3});
  Expect.identical(map,
      const <int, int>{if (false) 9: 9 else 1: 1, 2: 2, if (true) 3: 3});

  Expect.identical(set, const <int>{1, if (true) 2, if (false) 9, 3});
  Expect.identical(set, const <int>{if (false) 9 else 1, 2, if (true) 3});

  // Ordering does affect canonicalization.
  Expect.notIdentical(map, const <int, int>{1: 1, if (true) 3: 3, 2: 2});
  Expect.notIdentical(set, const <int>{1, if (true) 3, 2});
}
