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

library fasta.transform_set_literals;

import 'dart:core' hide MapEntry;

import 'package:kernel/ast.dart'
    show
        Arguments,
        Class,
        Constructor,
        ConstructorInvocation,
        DartType,
        Expression,
        InterfaceType,
        Let,
        Library,
        MapEntry,
        MapLiteral,
        MethodInvocation,
        Name,
        NullLiteral,
        Procedure,
        SetLiteral,
        StaticInvocation,
        TreeNode,
        VariableDeclaration,
        VariableGet;

import 'package:kernel/core_types.dart' show CoreTypes;

import 'package:kernel/visitor.dart' show Transformer;

import '../source/source_loader.dart' show SourceLoader;

import 'redirecting_factory_body.dart' show RedirectingFactoryBody;

// TODO(askesc): Delete this class when all backends support set literals.
class SetLiteralTransformer extends Transformer {
  final CoreTypes coreTypes;
  final DartType nullType;
  final Procedure setFactory;
  final Procedure addMethod;
  final Constructor unmodifiableSetConstructor;

  static Procedure _findSetFactory(CoreTypes coreTypes) {
    Procedure factory = coreTypes.index.getMember('dart:core', 'Set', '');
    RedirectingFactoryBody body = factory?.function?.body;
    return body?.target;
  }

  static Procedure _findAddMethod(CoreTypes coreTypes) {
    return coreTypes.index.getMember('dart:core', 'Set', 'add');
  }

  static Constructor _findUnmodifiableSetConstructor(
      SourceLoader<Library> loader) {
    // We should not generally dig into libraries like this, and we should
    // avoid dependencies on libraries other than the ones indexed by
    // CoreTypes. This is a temporary solution until all backends have
    // implemented support for set literals.
    Uri collectionUri = Uri.parse("dart:collection");
    Library collectionLibrary = loader.builders[collectionUri].target;
    for (int i = 0; i < collectionLibrary.classes.length; i++) {
      Class classNode = collectionLibrary.classes[i];
      if (classNode.name == "_UnmodifiableSet") {
        for (int j = 0; j < collectionLibrary.classes.length; j++) {
          Constructor constructor = classNode.constructors[j];
          if (constructor.name.name.isEmpty) {
            return constructor;
          }
        }
      }
    }
    return null;
  }

  SetLiteralTransformer(SourceLoader<Library> loader)
      : coreTypes = loader.coreTypes,
        nullType = new InterfaceType(loader.coreTypes.nullClass, []),
        setFactory = _findSetFactory(loader.coreTypes),
        addMethod = _findAddMethod(loader.coreTypes),
        unmodifiableSetConstructor = _findUnmodifiableSetConstructor(loader);

  TreeNode visitSetLiteral(SetLiteral node) {
    if (node.isConst) {
      List<MapEntry> entries = new List<MapEntry>(node.expressions.length);
      for (int i = 0; i < node.expressions.length; i++) {
        // expression_i: null
        Expression entry = node.expressions[i].accept(this);
        entries[i] = new MapEntry(entry, new NullLiteral());
      }
      Expression mapExp = new MapLiteral(entries,
          keyType: node.typeArgument, valueType: nullType, isConst: true);
      return new ConstructorInvocation(unmodifiableSetConstructor,
          new Arguments([mapExp], types: [node.typeArgument]),
          isConst: true);
    } else {
      // Outermost declaration of let chain: Set<E> setVar = new Set<E>();
      VariableDeclaration setVar = new VariableDeclaration.forValue(
          new StaticInvocation(
              setFactory, new Arguments([], types: [node.typeArgument])),
          type: new InterfaceType(coreTypes.setClass, [node.typeArgument]));
      // Innermost body of let chain: setVar
      Expression setExp = new VariableGet(setVar);
      for (int i = node.expressions.length - 1; i >= 0; i--) {
        // let _ = setVar.add(expression) in rest
        Expression entry = node.expressions[i].accept(this);
        setExp = new Let(
            new VariableDeclaration.forValue(new MethodInvocation(
                new VariableGet(setVar),
                new Name("add"),
                new Arguments([entry]),
                addMethod)),
            setExp);
      }
      return new Let(setVar, setExp);
    }
  }
}
