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

// TODO(johnniwinther): Remove this library when all constant constructors are
// computed during resolution.
library dart2js.constants.constant_constructors;

import '../common.dart';
import '../dart_types.dart';
import '../elements/elements.dart';
import '../resolution/operators.dart';
import '../resolution/semantic_visitor.dart';
import '../resolution/send_resolver.dart' show DeclarationResolverMixin;
import '../resolution/send_structure.dart';
import '../resolution/tree_elements.dart' show TreeElements;
import '../tree/tree.dart';
import '../universe/call_structure.dart' show CallStructure;
import 'constructors.dart';
import 'expressions.dart';

ConstantConstructor computeConstantConstructor(ResolvedAst resolvedAst) {
  ConstantConstructorComputer visitor =
      new ConstantConstructorComputer(resolvedAst.elements);
  return resolvedAst.node.accept(visitor);
}

class ConstantConstructorComputer extends SemanticVisitor
    with
        SemanticDeclarationResolvedMixin,
        DeclarationResolverMixin,
        GetBulkMixin,
        SetBulkMixin,
        ErrorBulkMixin,
        InvokeBulkMixin,
        IndexSetBulkMixin,
        CompoundBulkMixin,
        SetIfNullBulkMixin,
        UnaryBulkMixin,
        BaseBulkMixin,
        BinaryBulkMixin,
        PrefixBulkMixin,
        PostfixBulkMixin,
        NewBulkMixin,
        InitializerBulkMixin,
        FunctionBulkMixin,
        VariableBulkMixin
    implements SemanticDeclarationVisitor, SemanticSendVisitor {
  final Map<FieldElement, ConstantExpression> fieldMap =
      <FieldElement, ConstantExpression>{};
  final Map<dynamic /*int|String*/, ConstantExpression> defaultValues =
      <dynamic /*int|String*/, ConstantExpression>{};

  ConstantConstructorComputer(TreeElements elements) : super(elements);

  SemanticDeclarationVisitor get declVisitor => this;

  SemanticSendVisitor get sendVisitor => this;

  ClassElement get currentClass => currentConstructor.enclosingClass;

  ConstructorElement get currentConstructor => elements.analyzedElement;

  apply(Node node, [_]) => node.accept(this);

  visitNode(Node node) {
    internalError(node, 'Unhandled node $node: ${node.toDebugString()}');
  }

  @override
  bulkHandleNode(Node node, String template, _) {
    internalError(node, template.replaceFirst('#', '$node'));
  }

  internalError(Node node, String message) {
    throw new UnsupportedError(message);
  }

  ConstantConstructor visitGenerativeConstructorDeclaration(
      FunctionExpression node,
      ConstructorElement constructor,
      NodeList parameters,
      NodeList initializers,
      Node body,
      _) {
    applyParameters(parameters, _);
    ConstructedConstantExpression constructorInvocation =
        applyInitializers(node, _);
    constructor.enclosingClass.forEachInstanceField((_, FieldElement field) {
      if (!fieldMap.containsKey(field)) {
        fieldMap[field] = field.constant;
      }
    });
    return new GenerativeConstantConstructor(
        currentClass.thisType, defaultValues, fieldMap, constructorInvocation);
  }

  ConstantConstructor visitRedirectingGenerativeConstructorDeclaration(
      FunctionExpression node,
      ConstructorElement constructor,
      NodeList parameters,
      NodeList initializers,
      _) {
    applyParameters(parameters, _);
    ConstructedConstantExpression constructorInvocation =
        applyInitializers(node, _);
    return new RedirectingGenerativeConstantConstructor(
        defaultValues, constructorInvocation);
  }

  ConstantConstructor visitRedirectingFactoryConstructorDeclaration(
      FunctionExpression node,
      ConstructorElement constructor,
      NodeList parameters,
      InterfaceType redirectionType,
      ConstructorElement redirectionTarget,
      _) {
    List<String> argumentNames = [];
    List<ConstantExpression> arguments = [];
    int index = 0;
    for (ParameterElement parameter in constructor.parameters) {
      if (parameter.isNamed) {
        String name = parameter.name;
        argumentNames.add(name);
        arguments.add(new NamedArgumentReference(name));
      } else {
        arguments.add(new PositionalArgumentReference(index));
      }
      index++;
    }
    CallStructure callStructure = new CallStructure(index, argumentNames);

    return new RedirectingFactoryConstantConstructor(
        new ConstructedConstantExpression(
            redirectionType, redirectionTarget, callStructure, arguments));
  }

  @override
  visitFactoryConstructorDeclaration(FunctionExpression node,
      ConstructorElement constructor, NodeList parameters, Node body, _) {
    // TODO(johnniwinther): Handle constant constructors with errors.
    internalError(node, "Factory constructor cannot be constant: $node.");
  }

  applyParameters(NodeList parameters, _) {
    computeParameterStructures(parameters).forEach((s) => s.dispatch(this, _));
  }

  visitParameterDeclaration(VariableDefinitions node, Node definition,
      ParameterElement parameter, int index, _) {
    // Do nothing.
  }

  visitOptionalParameterDeclaration(
      VariableDefinitions node,
      Node definition,
      ParameterElement parameter,
      ConstantExpression defaultValue,
      int index,
      _) {
    assert(invariant(node, defaultValue != null));
    defaultValues[index] = defaultValue;
  }

  visitNamedParameterDeclaration(VariableDefinitions node, Node definition,
      ParameterElement parameter, ConstantExpression defaultValue, _) {
    assert(invariant(node, defaultValue != null));
    String name = parameter.name;
    defaultValues[name] = defaultValue;
  }

  visitInitializingFormalDeclaration(VariableDefinitions node, Node definition,
      InitializingFormalElement parameter, int index, _) {
    fieldMap[parameter.fieldElement] = new PositionalArgumentReference(index);
  }

  visitOptionalInitializingFormalDeclaration(
      VariableDefinitions node,
      Node definition,
      InitializingFormalElement parameter,
      ConstantExpression defaultValue,
      int index,
      _) {
    assert(invariant(node, defaultValue != null));
    defaultValues[index] = defaultValue;
    fieldMap[parameter.fieldElement] = new PositionalArgumentReference(index);
  }

  visitNamedInitializingFormalDeclaration(
      VariableDefinitions node,
      Node definition,
      InitializingFormalElement parameter,
      ConstantExpression defaultValue,
      _) {
    assert(invariant(node, defaultValue != null));
    String name = parameter.name;
    defaultValues[name] = defaultValue;
    fieldMap[parameter.fieldElement] = new NamedArgumentReference(name);
  }

  /// Apply this visitor to the constructor [initializers].
  ConstructedConstantExpression applyInitializers(
      FunctionExpression constructor, _) {
    ConstructedConstantExpression constructorInvocation;
    InitializersStructure initializers =
        computeInitializersStructure(constructor);
    for (InitializerStructure structure in initializers.initializers) {
      if (structure.isConstructorInvoke) {
        constructorInvocation = structure.dispatch(this, _);
      } else {
        structure.dispatch(this, _);
      }
    }
    return constructorInvocation;
  }

  visitFieldInitializer(SendSet node, FieldElement field, Node initializer, _) {
    fieldMap[field] = apply(initializer);
  }

  visitParameterGet(Send node, ParameterElement parameter, _) {
    if (parameter.isNamed) {
      return new NamedArgumentReference(parameter.name);
    } else {
      return new PositionalArgumentReference(
          parameter.functionDeclaration.parameters.indexOf(parameter));
    }
  }

  ConstructedConstantExpression visitSuperConstructorInvoke(
      Send node,
      ConstructorElement superConstructor,
      InterfaceType type,
      NodeList arguments,
      CallStructure callStructure,
      _) {
    List<ConstantExpression> argumentExpression =
        arguments.nodes.map((a) => apply(a)).toList();
    return new ConstructedConstantExpression(
        type, superConstructor, callStructure, argumentExpression);
  }

  ConstructedConstantExpression visitImplicitSuperConstructorInvoke(
      FunctionExpression node,
      ConstructorElement superConstructor,
      InterfaceType type,
      _) {
    return new ConstructedConstantExpression(type, superConstructor,
        CallStructure.NO_ARGS, const <ConstantExpression>[]);
  }

  ConstructedConstantExpression visitThisConstructorInvoke(
      Send node,
      ConstructorElement thisConstructor,
      NodeList arguments,
      CallStructure callStructure,
      _) {
    List<ConstantExpression> argumentExpression =
        arguments.nodes.map((a) => apply(a)).toList();
    return new ConstructedConstantExpression(currentClass.thisType,
        thisConstructor, callStructure, argumentExpression);
  }

  @override
  ConstantExpression visitBinary(
      Send node, Node left, BinaryOperator operator, Node right, _) {
    return new BinaryConstantExpression(apply(left), operator, apply(right));
  }

  @override
  ConstantExpression visitEquals(Send node, Node left, Node right, _) {
    return new BinaryConstantExpression(
        apply(left), BinaryOperator.EQ, apply(right));
  }

  @override
  ConstantExpression visitNotEquals(Send node, Node left, Node right, _) {
    return new BinaryConstantExpression(
        apply(left), BinaryOperator.NOT_EQ, apply(right));
  }

  @override
  ConstantExpression visitUnary(
      Send node, UnaryOperator operator, Node expression, _) {
    return new UnaryConstantExpression(operator, apply(expression));
  }

  @override
  ConstantExpression visitStaticFieldGet(Send node, FieldElement field, _) {
    return new VariableConstantExpression(field);
  }

  @override
  ConstantExpression visitTopLevelFieldGet(Send node, FieldElement field, _) {
    return new VariableConstantExpression(field);
  }

  @override
  ConstantExpression visitLiteralInt(LiteralInt node) {
    return new IntConstantExpression(node.value);
  }

  @override
  ConstantExpression visitLiteralDouble(LiteralDouble node) {
    return new DoubleConstantExpression(node.value);
  }

  @override
  ConstantExpression visitLiteralBool(LiteralBool node) {
    return new BoolConstantExpression(node.value);
  }

  @override
  ConstantExpression visitLiteralNull(LiteralNull node) {
    return new NullConstantExpression();
  }

  @override
  ConstantExpression visitLiteralString(LiteralString node) {
    return new StringConstantExpression(node.dartString.slowToString());
  }

  @override
  ConstantExpression visitConditional(Conditional node) {
    return new ConditionalConstantExpression(apply(node.condition),
        apply(node.thenExpression), apply(node.elseExpression));
  }

  @override
  ConstantExpression visitParenthesizedExpression(
      ParenthesizedExpression node) {
    return apply(node.expression);
  }

  @override
  ConstantExpression visitTopLevelFunctionInvoke(
      Send node,
      MethodElement function,
      NodeList arguments,
      CallStructure callStructure,
      _) {
    if (function.name != 'identical' || !function.library.isDartCore) {
      throw new UnsupportedError("Unexpected function call: $function");
    }
    return new IdenticalConstantExpression(
        apply(arguments.nodes.head), apply(arguments.nodes.tail.head));
  }

  @override
  ConstantExpression visitNamedArgument(NamedArgument node) {
    return apply(node.expression);
  }

  @override
  ConstantExpression visitIfNull(Send node, Node left, Node right, _) {
    return new BinaryConstantExpression(
        apply(left), BinaryOperator.IF_NULL, apply(right));
  }
}
