// Copyright (c) 2016, 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.md file.

import 'package:kernel/ast.dart' as ir;

import "../elements/resolution_types.dart"
    show ResolutionDartType, ResolutionInterfaceType;
import "../elements/elements.dart"
    show
        AstElement,
        ConstructorElement,
        Element,
        ErroneousElement,
        FunctionElement,
        MethodElement;
import "../resolution/operators.dart"
    show AssignmentOperator, BinaryOperator, IncDecOperator, UnaryOperator;
import "../tree/tree.dart" show Expression, NewExpression, Node, NodeList, Send;
import "../universe/call_structure.dart" show CallStructure;
import "../universe/selector.dart" show Selector;
import 'accessors.dart';
import "kernel.dart" show Kernel;

abstract class UnresolvedVisitor {
  Kernel get kernel;

  // Implemented in KernelVisitor
  AstElement get currentElement;
  bool get isVoidContext;
  ir.Arguments buildArguments(NodeList arguments);
  ir.TreeNode visitForValue(Expression node);
  void associateCompoundComponents(Accessor accessor, Node node);

  // TODO(ahe): Delete this method.
  ir.InvalidExpression handleUnresolved(Node node);

  /// Similar to [Kernel.functionToIr] but returns null if [function] is a
  /// synthetic function created for error recovery.
  ir.Member possiblyErroneousFunctionToIr(FunctionElement function) {
    return kernel.isSyntheticError(function)
        ? null
        : kernel.functionToIr(function);
  }

  /// Throws a [NoSuchMethodError] corresponding to a call to
  /// [receiver].[memberName] with the arguments [callArguments].
  ///
  /// The exception object is built by calling [exceptionBuilder]. This should
  /// take the same arguments as the default constructor to [NoSuchMethodError],
  /// but the method itself may encode additional details about the call than
  /// is possible through the public interface of NoSuchMethodError.
  ///
  /// Note that [callArguments] are the arguments as they occur in the attempted
  /// call in user code -- they are not the arguments to [exceptionBuilder].
  ///
  /// If [candidateTarget] is given, it will provide the expected parameter
  /// names.
  ir.Expression buildThrowNoSuchMethodError(ir.Procedure exceptionBuilder,
      ir.Expression receiver, String memberName, ir.Arguments callArguments,
      [Element candidateTarget]) {
    ir.Expression memberNameArg =
        markSynthetic(new ir.SymbolLiteral(memberName));
    ir.Expression positional =
        markSynthetic(new ir.ListLiteral(callArguments.positional));
    ir.Expression named =
        markSynthetic(new ir.MapLiteral(callArguments.named.map((e) {
      return new ir.MapEntry(
          markSynthetic(new ir.SymbolLiteral(e.name)), e.value);
    }).toList()));
    if (candidateTarget is FunctionElement) {
      // Ensure [candidateTarget] has been resolved.
      possiblyErroneousFunctionToIr(candidateTarget);
    }
    ir.Expression existingArguments;
    if (candidateTarget is FunctionElement &&
        !kernel.isSyntheticError(candidateTarget) &&
        candidateTarget.hasFunctionSignature) {
      List<ir.Expression> existingArgumentsList = <ir.Expression>[];
      candidateTarget.functionSignature.forEachParameter((param) {
        existingArgumentsList
            .add(markSynthetic(new ir.StringLiteral(param.name)));
      });
      existingArguments =
          markSynthetic(new ir.ListLiteral(existingArgumentsList));
    } else {
      existingArguments = new ir.NullLiteral();
    }
    ir.Expression construction = markSynthetic(new ir.StaticInvocation(
        exceptionBuilder,
        new ir.Arguments(<ir.Expression>[
          receiver,
          memberNameArg,
          positional,
          named,
          existingArguments
        ])));
    return new ir.Throw(construction);
  }

  ir.Expression markSynthetic(ir.Expression expression) {
    kernel.syntheticNodes.add(expression);
    return expression;
  }

  /// Throws a NoSuchMethodError for an unresolved getter named [name].
  ir.Expression buildThrowUnresolvedGetter(String name,
      [ir.Procedure exceptionBuilder]) {
    // TODO(asgerf): We should remove this fallback, but in some cases we do
    //   not get sufficient information to determine exactly what kind of
    //   getter it is.
    exceptionBuilder ??= kernel.getGenericNoSuchMethodBuilder();
    return buildThrowNoSuchMethodError(
        exceptionBuilder, new ir.NullLiteral(), name, new ir.Arguments.empty());
  }

  ir.Expression buildThrowUnresolvedSetter(String name, ir.Expression argument,
      [ir.Procedure exceptionBuilder]) {
    // TODO(asgerf): We should remove this fallback, but in some cases we do
    //   not get sufficient information to determine exactly what kind of
    //   setter it is.
    exceptionBuilder ??= kernel.getGenericNoSuchMethodBuilder();
    return buildThrowNoSuchMethodError(exceptionBuilder, new ir.NullLiteral(),
        name, new ir.Arguments(<ir.Expression>[argument]));
  }

  ir.Expression buildThrowUnresolvedSuperGetter(String name) {
    // TODO(sra): This is incorrect when the superclass defines noSuchMethod.
    return buildThrowNoSuchMethodError(kernel.getUnresolvedSuperGetterBuilder(),
        new ir.ThisExpression(), name, new ir.Arguments.empty());
  }

  ir.Expression buildThrowUnresolvedSuperSetter(
      String name, ir.Expression argument) {
    return buildThrowNoSuchMethodError(
        kernel.getUnresolvedSuperSetterBuilder(),
        new ir.ThisExpression(),
        name,
        new ir.Arguments(<ir.Expression>[argument]));
  }

  ir.Expression buildThrowSingleArgumentError(
      ir.Procedure exceptionBuilder, String errorMessage) {
    return new ir.Throw(new ir.StaticInvocation(exceptionBuilder,
        new ir.Arguments(<ir.Expression>[new ir.StringLiteral(errorMessage)])));
  }

  SuperIndexAccessor buildUnresolvedSuperIndexAccessor(
      Node index, Element element) {
    ir.Member member = possiblyErroneousFunctionToIr(element);
    return new SuperIndexAccessor(this, visitForValue(index), member, member);
  }

  SuperPropertyAccessor buildUnresolvedSuperPropertyAccessor(
      String name, Element getter) {
    return new SuperPropertyAccessor(this, kernel.irName(name, currentElement),
        getter == null ? null : possiblyErroneousFunctionToIr(getter), null);
  }

  ir.Expression visitUnresolvedClassConstructorInvoke(
      NewExpression node,
      ErroneousElement element,
      ResolutionDartType type,
      NodeList arguments,
      Selector selector,
      _) {
    // TODO(asgerf): The VM includes source information as part of the error
    //   message.  We could do the same when we add source maps.
    return buildThrowSingleArgumentError(
        kernel.getMalformedTypeErrorBuilder(), element.message);
  }

  ir.Expression visitUnresolvedConstructorInvoke(
      NewExpression node,
      Element constructor,
      ResolutionDartType type,
      NodeList arguments,
      Selector selector,
      _) {
    ir.Expression receiver = new ir.TypeLiteral(kernel.interfaceTypeToIr(type));
    String methodName =
        node.send.selector != null ? '${node.send.selector}' : type.name;
    return buildThrowNoSuchMethodError(kernel.getUnresolvedConstructorBuilder(),
        receiver, methodName, buildArguments(arguments), constructor);
  }

  ir.Expression visitUnresolvedCompound(
      Send node, Element element, AssignmentOperator operator, Node rhs, _) {
    return buildThrowUnresolvedGetter('${node.selector}');
  }

  ir.Expression visitUnresolvedGet(Send node, Element element, _) {
    return buildThrowUnresolvedGetter('${node.selector}');
  }

  ir.Expression visitUnresolvedInvoke(
      Send node, Element element, NodeList arguments, Selector selector, _) {
    // TODO(asgerf): Should we use a type literal as receiver for unresolved
    //   static invocations?
    return buildThrowNoSuchMethodError(kernel.getGenericNoSuchMethodBuilder(),
        new ir.NullLiteral(), element.name, buildArguments(arguments), element);
  }

  ir.Expression visitUnresolvedPostfix(
      Send node, Element element, IncDecOperator operator, _) {
    return buildThrowUnresolvedGetter('${node.selector}');
  }

  ir.Expression visitUnresolvedPrefix(
      Send node, Element element, IncDecOperator operator, _) {
    return buildThrowUnresolvedGetter('${node.selector}');
  }

  ir.Expression visitUnresolvedRedirectingFactoryConstructorInvoke(
      NewExpression node,
      ConstructorElement constructor,
      ResolutionInterfaceType type,
      NodeList arguments,
      CallStructure callStructure,
      _) {
    // The body of the factory will throw an error.
    return new ir.StaticInvocation(
        possiblyErroneousFunctionToIr(constructor), buildArguments(arguments));
  }

  ir.Expression visitUnresolvedSet(Send node, Element element, Node rhs, _) {
    return buildThrowUnresolvedSetter('${node.selector}', visitForValue(rhs));
  }

  ir.Expression visitUnresolvedSetIfNull(
      Send node, Element element, Node rhs, _) {
    return buildThrowUnresolvedGetter('${node.selector}');
  }

  ir.Expression visitUnresolvedStaticGetterCompound(Send node, Element element,
      MethodElement setter, AssignmentOperator operator, Node rhs, _) {
    return buildThrowUnresolvedGetter(
        '${node.selector}', kernel.getUnresolvedStaticGetterBuilder());
  }

  ir.Expression visitUnresolvedStaticGetterPostfix(Send node, Element element,
      MethodElement setter, IncDecOperator operator, _) {
    return buildThrowUnresolvedGetter(
        '${node.selector}', kernel.getUnresolvedStaticGetterBuilder());
  }

  ir.Expression visitUnresolvedStaticGetterPrefix(Send node, Element element,
      MethodElement setter, IncDecOperator operator, _) {
    return buildThrowUnresolvedGetter(
        '${node.selector}', kernel.getUnresolvedStaticGetterBuilder());
  }

  ir.Expression visitUnresolvedStaticGetterSetIfNull(
      Send node, Element element, MethodElement setter, Node rhs, _) {
    return buildThrowUnresolvedGetter(
        '${node.selector}', kernel.getUnresolvedStaticGetterBuilder());
  }

  ir.Expression visitUnresolvedStaticSetterCompound(
      Send node,
      MethodElement getter,
      Element element,
      AssignmentOperator operator,
      Node rhs,
      _) {
    return buildThrowUnresolvedSetter('${node.selector}', visitForValue(rhs),
        kernel.getUnresolvedStaticSetterBuilder());
  }

  ir.Expression visitUnresolvedStaticSetterPostfix(Send node,
      MethodElement getter, Element element, IncDecOperator operator, _) {
    var accessor = new ClassStaticAccessor(
        this, getter.name, possiblyErroneousFunctionToIr(getter), null);
    var result = accessor.buildPostfixIncrement(
        new ir.Name(operator.selectorName),
        voidContext: isVoidContext);
    associateCompoundComponents(accessor, node);
    return result;
  }

  ir.Expression visitUnresolvedStaticSetterPrefix(Send node,
      MethodElement getter, Element element, IncDecOperator operator, _) {
    var accessor = new ClassStaticAccessor(
        this, getter.name, possiblyErroneousFunctionToIr(getter), null);
    var result = accessor.buildPrefixIncrement(
        new ir.Name(operator.selectorName),
        voidContext: isVoidContext);
    associateCompoundComponents(accessor, node);
    return result;
  }

  ir.Expression visitUnresolvedStaticSetterSetIfNull(
      Send node, MethodElement getter, Element element, Node rhs, _) {
    var accessor = new ClassStaticAccessor(
        this, getter.name, possiblyErroneousFunctionToIr(getter), null);
    return accessor.buildNullAwareAssignment(visitForValue(rhs), null,
        voidContext: isVoidContext);
  }

  ir.Expression visitUnresolvedSuperBinary(
      Send node, Element element, BinaryOperator operator, Node argument, _) {
    // TODO(sra): This is incorrect when the superclass defines noSuchMethod.
    return buildThrowNoSuchMethodError(
        kernel.getUnresolvedSuperMethodBuilder(),
        new ir.ThisExpression(),
        operator.selectorName,
        new ir.Arguments(<ir.Expression>[visitForValue(argument)]));
  }

  ir.Expression visitUnresolvedSuperCompound(
      Send node, Element element, AssignmentOperator operator, Node rhs, _) {
    return buildThrowUnresolvedSuperGetter('${node.selector}');
  }

  ir.Expression visitUnresolvedSuperCompoundIndexSet(Send node, Element element,
      Node index, AssignmentOperator operator, Node rhs, _) {
    return buildUnresolvedSuperIndexAccessor(index, element)
        .buildCompoundAssignment(
            new ir.Name(operator.selectorName), visitForValue(rhs));
  }

  ir.Expression visitUnresolvedSuperGet(Send node, Element element, _) {
    return buildThrowUnresolvedSuperGetter('${node.selector}');
  }

  ir.Expression visitUnresolvedSuperGetterCompound(Send node, Element element,
      MethodElement setter, AssignmentOperator operator, Node rhs, _) {
    return buildThrowUnresolvedSuperGetter('${node.selector}');
  }

  ir.Expression visitUnresolvedSuperGetterCompoundIndexSet(
      Send node,
      Element element,
      MethodElement setter,
      Node index,
      AssignmentOperator operator,
      Node rhs,
      _) {
    return buildThrowUnresolvedSuperGetter('${node.selector}');
  }

  ir.Expression visitUnresolvedSuperGetterIndexPostfix(
      Send node,
      Element element,
      MethodElement setter,
      Node index,
      IncDecOperator operator,
      _) {
    return buildThrowUnresolvedSuperGetter('${node.selector}');
  }

  ir.Expression visitUnresolvedSuperGetterIndexPrefix(
      Send node,
      Element element,
      MethodElement setter,
      Node index,
      IncDecOperator operator,
      _) {
    return buildThrowUnresolvedSuperGetter('${node.selector}');
  }

  ir.Expression visitUnresolvedSuperGetterPostfix(Send node, Element element,
      MethodElement setter, IncDecOperator operator, _) {
    return buildThrowUnresolvedSuperGetter('${node.selector}');
  }

  ir.Expression visitUnresolvedSuperGetterPrefix(Send node, Element element,
      MethodElement setter, IncDecOperator operator, _) {
    return buildThrowUnresolvedSuperGetter('${node.selector}');
  }

  ir.Expression visitUnresolvedSuperGetterSetIfNull(
      Send node, Element element, MethodElement setter, Node rhs, _) {
    return buildThrowUnresolvedSuperGetter('${node.selector}');
  }

  ir.Expression visitUnresolvedSuperIndex(
      Send node, Element element, Node index, _) {
    return buildUnresolvedSuperIndexAccessor(index, element).buildSimpleRead();
  }

  ir.Expression visitUnresolvedSuperIndexPostfix(
      Send node, Element element, Node index, IncDecOperator operator, _) {
    return buildUnresolvedSuperIndexAccessor(index, element).buildSimpleRead();
  }

  ir.Expression visitUnresolvedSuperIndexPrefix(
      Send node, Element element, Node index, IncDecOperator operator, _) {
    return buildUnresolvedSuperIndexAccessor(index, element).buildSimpleRead();
  }

  ir.Expression visitUnresolvedSuperIndexSet(
      Send node, Element element, Node index, Node rhs, _) {
    return buildUnresolvedSuperIndexAccessor(index, element)
        .buildAssignment(visitForValue(rhs));
  }

  ir.Expression visitUnresolvedSuperInvoke(
      Send node, Element element, NodeList arguments, Selector selector, _) {
    // TODO(asgerf): Should really invoke 'super.noSuchMethod'.
    return buildThrowNoSuchMethodError(kernel.getUnresolvedSuperMethodBuilder(),
        new ir.ThisExpression(), '${node.selector}', buildArguments(arguments));
  }

  ir.Expression visitUnresolvedSuperPostfix(
      Send node, Element element, IncDecOperator operator, _) {
    return buildThrowUnresolvedSuperGetter('${node.selector}');
  }

  ir.Expression visitUnresolvedSuperPrefix(
      Send node, Element element, IncDecOperator operator, _) {
    return buildThrowUnresolvedSuperGetter('${node.selector}');
  }

  ir.Expression visitUnresolvedSuperSetIfNull(
      Send node, Element element, Node rhs, _) {
    return buildThrowUnresolvedSuperGetter('${node.selector}');
  }

  ir.Expression visitUnresolvedSuperSetterCompound(
      Send node,
      MethodElement getter,
      Element element,
      AssignmentOperator operator,
      Node rhs,
      _) {
    return buildUnresolvedSuperPropertyAccessor('${node.selector}', getter)
        .buildCompoundAssignment(
            new ir.Name(operator.selectorName), visitForValue(rhs));
  }

  ir.Expression visitUnresolvedSuperSetterCompoundIndexSet(
      Send node,
      MethodElement getter,
      Element element,
      Node index,
      AssignmentOperator operator,
      Node rhs,
      _) {
    return buildUnresolvedSuperIndexAccessor(index, element)
        .buildCompoundAssignment(
            new ir.Name(operator.selectorName), visitForValue(rhs));
  }

  ir.Expression visitUnresolvedSuperSetterIndexPostfix(
      Send node,
      MethodElement indexFunction,
      Element element,
      Node index,
      IncDecOperator operator,
      _) {
    return buildUnresolvedSuperIndexAccessor(index, element)
        .buildPostfixIncrement(new ir.Name(operator.selectorName));
  }

  ir.Expression visitUnresolvedSuperSetterIndexPrefix(
      Send node,
      MethodElement indexFunction,
      Element element,
      Node index,
      IncDecOperator operator,
      _) {
    return buildUnresolvedSuperIndexAccessor(index, element)
        .buildPrefixIncrement(new ir.Name(operator.selectorName));
  }

  ir.Expression visitUnresolvedSuperSetterPostfix(Send node,
      MethodElement getter, Element element, IncDecOperator operator, _) {
    return buildUnresolvedSuperPropertyAccessor('${node.selector}', getter)
        .buildPostfixIncrement(new ir.Name(operator.selectorName));
  }

  ir.Expression visitUnresolvedSuperSetterPrefix(Send node,
      MethodElement getter, Element element, IncDecOperator operator, _) {
    return buildUnresolvedSuperPropertyAccessor('${node.selector}', getter)
        .buildPrefixIncrement(new ir.Name(operator.selectorName));
  }

  ir.Expression visitUnresolvedSuperSetterSetIfNull(
      Send node, MethodElement getter, Element element, Node rhs, _) {
    return buildUnresolvedSuperPropertyAccessor('${node.selector}', getter)
        .buildNullAwareAssignment(visitForValue(rhs), null);
  }

  ir.Expression visitUnresolvedSuperUnary(
      Send node, UnaryOperator operator, Element element, _) {
    // TODO(asgerf): Should really call 'super.noSuchMethod'.
    return buildThrowNoSuchMethodError(
        kernel.getUnresolvedSuperMethodBuilder(),
        new ir.ThisExpression(),
        operator.selectorName,
        new ir.Arguments.empty());
  }

  ir.Expression visitUnresolvedTopLevelGetterCompound(
      Send node,
      Element element,
      MethodElement setter,
      AssignmentOperator operator,
      Node rhs,
      _) {
    return buildThrowUnresolvedGetter(
        '${node.selector}', kernel.getUnresolvedTopLevelGetterBuilder());
  }

  ir.Expression visitUnresolvedTopLevelGetterPostfix(Send node, Element element,
      MethodElement setter, IncDecOperator operator, _) {
    return buildThrowUnresolvedGetter(
        '${node.selector}', kernel.getUnresolvedTopLevelGetterBuilder());
  }

  ir.Expression visitUnresolvedTopLevelGetterPrefix(Send node, Element element,
      MethodElement setter, IncDecOperator operator, _) {
    return buildThrowUnresolvedGetter(
        '${node.selector}', kernel.getUnresolvedTopLevelGetterBuilder());
  }

  ir.Expression visitUnresolvedTopLevelGetterSetIfNull(
      Send node, Element element, MethodElement setter, Node rhs, _) {
    return buildThrowUnresolvedGetter(
        '${node.selector}', kernel.getUnresolvedTopLevelGetterBuilder());
  }

  ir.Expression visitUnresolvedTopLevelSetterCompound(
      Send node,
      MethodElement getter,
      Element element,
      AssignmentOperator operator,
      Node rhs,
      _) {
    var accessor = new TopLevelStaticAccessor(
        this, getter.name, possiblyErroneousFunctionToIr(getter), null);
    var result = accessor.buildCompoundAssignment(
        new ir.Name(operator.selectorName), visitForValue(rhs),
        voidContext: isVoidContext);
    associateCompoundComponents(accessor, node);
    return result;
  }

  ir.Expression visitUnresolvedTopLevelSetterPostfix(Send node,
      MethodElement getter, Element element, IncDecOperator operator, _) {
    var accessor = new TopLevelStaticAccessor(
        this, getter.name, possiblyErroneousFunctionToIr(getter), null);
    var result = accessor.buildPostfixIncrement(
        new ir.Name(operator.selectorName),
        voidContext: isVoidContext);
    associateCompoundComponents(accessor, node);
    return result;
  }

  ir.Expression visitUnresolvedTopLevelSetterPrefix(Send node,
      MethodElement getter, Element element, IncDecOperator operator, _) {
    var accessor = new TopLevelStaticAccessor(
        this, getter.name, possiblyErroneousFunctionToIr(getter), null);
    var result = accessor.buildPrefixIncrement(
        new ir.Name(operator.selectorName),
        voidContext: isVoidContext);
    associateCompoundComponents(accessor, node);
    return result;
  }

  ir.Expression visitUnresolvedTopLevelSetterSetIfNull(
      Send node, MethodElement getter, Element element, Node rhs, _) {
    var accessor = new TopLevelStaticAccessor(
        this, getter.name, possiblyErroneousFunctionToIr(getter), null);
    return accessor.buildNullAwareAssignment(visitForValue(rhs), null,
        voidContext: isVoidContext);
  }

  ir.Expression visitUnresolvedSuperGetterIndexSetIfNull(Send node,
      Element element, MethodElement setter, Node index, Node rhs, _) {
    return buildUnresolvedSuperIndexAccessor(index, element)
        .buildNullAwareAssignment(visitForValue(rhs), null);
  }

  ir.Expression visitUnresolvedSuperSetterIndexSetIfNull(Send node,
      MethodElement getter, Element element, Node index, Node rhs, _) {
    return buildUnresolvedSuperIndexAccessor(index, element)
        .buildNullAwareAssignment(visitForValue(rhs), null);
  }

  ir.Expression visitUnresolvedSuperIndexSetIfNull(
      Send node, Element element, Node index, Node rhs, _) {
    return buildUnresolvedSuperIndexAccessor(index, element)
        .buildNullAwareAssignment(visitForValue(rhs), null);
  }

  ir.Expression visitUnresolvedSuperSet(
      Send node, Element element, Node rhs, _) {
    return buildThrowUnresolvedSuperSetter(
        '${node.selector}', visitForValue(rhs));
  }
}
