// Copyright (c) 2014, 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 analyzer2dart.cps_generator;

import 'package:analyzer/analyzer.dart';

import 'package:compiler/src/dart_types.dart' as dart2js;
import 'package:compiler/src/elements/elements.dart' as dart2js;
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/generated/element.dart' as analyzer;

import 'package:compiler/src/dart2jslib.dart'
    show DART_CONSTANT_SYSTEM;
import 'package:compiler/src/cps_ir/cps_ir_nodes.dart' as ir;
import 'package:compiler/src/cps_ir/cps_ir_builder.dart';
import 'package:compiler/src/universe/universe.dart';

import 'semantic_visitor.dart';
import 'element_converter.dart';
import 'util.dart';
import 'identifier_semantics.dart';

/// Visitor that converts the AST node of an analyzer element into a CPS ir
/// node.
class CpsElementVisitor extends analyzer.SimpleElementVisitor<ir.Node> {
  final ElementConverter converter;
  final AstNode node;

  CpsElementVisitor(this.converter, this.node);

  @override
  ir.FunctionDefinition visitFunctionElement(analyzer.FunctionElement element) {
    CpsGeneratingVisitor visitor = new CpsGeneratingVisitor(converter, element);
    FunctionDeclaration functionDeclaration = node;
    return visitor.handleFunctionDeclaration(
        element, functionDeclaration.functionExpression.body);
  }

  @override
  ir.FunctionDefinition visitMethodElement(analyzer.MethodElement element) {
    CpsGeneratingVisitor visitor = new CpsGeneratingVisitor(converter, element);
    MethodDeclaration methodDeclaration = node;
    return visitor.handleFunctionDeclaration(element, methodDeclaration.body);
  }

  @override
  ir.FieldDefinition visitTopLevelVariableElement(
      analyzer.TopLevelVariableElement element) {
    CpsGeneratingVisitor visitor = new CpsGeneratingVisitor(converter, element);
    VariableDeclaration variableDeclaration = node;
    return visitor.handleFieldDeclaration(element, variableDeclaration);
  }

  @override
  ir.ExecutableDefinition visitConstructorElement(
      analyzer.ConstructorElement element) {
    CpsGeneratingVisitor visitor = new CpsGeneratingVisitor(converter, element);
    if (!element.isFactory) {
      ConstructorDeclaration constructorDeclaration = node;
      FunctionBody body;
      if (constructorDeclaration != null) {
        body = constructorDeclaration.body;
      } else {
        assert(element.isSynthetic);
      }
      return visitor.handleConstructorDeclaration(element, body);
    }
    // TODO(johnniwinther): Support factory constructors.
    return null;
  }
}

/// Visitor that converts analyzer AST nodes into CPS ir nodes.
class CpsGeneratingVisitor extends SemanticVisitor<ir.Node>
    with IrBuilderMixin<AstNode> {
  /// Promote the type of [irBuilder] to [DartIrBuilder].
  /// The JS backend requires closure conversion which we do not support yet.
  DartIrBuilder get irBuilder => super.irBuilder;
  final analyzer.Element element;
  final ElementConverter converter;

  CpsGeneratingVisitor(this.converter, this.element);

  Source get currentSource => element.source;

  analyzer.LibraryElement get currentLibrary => element.library;

  ir.Node visit(AstNode node) => node.accept(this);

  ir.ConstructorDefinition handleConstructorDeclaration(
      analyzer.ConstructorElement constructor, FunctionBody body) {
    dart2js.ConstructorElement element = converter.convertElement(constructor);
    return withBuilder(
        new DartIrBuilder(DART_CONSTANT_SYSTEM,
                          element,
                          // TODO(johnniwinther): Supported closure variables.
                          new NullCapturedVariableInfo()),
        () {
      irBuilder.buildFunctionHeader(
          constructor.parameters.map(converter.convertElement));
      // Visit the body directly to avoid processing the signature as
      // expressions.
      // Call to allow for `body == null` in case of synthesized constructors.
      build(body);
      return irBuilder.makeConstructorDefinition(const [], const []);
    });
  }

  ir.FieldDefinition handleFieldDeclaration(
      analyzer.PropertyInducingElement field, VariableDeclaration node) {
    dart2js.FieldElement element = converter.convertElement(field);
    return withBuilder(
        new DartIrBuilder(DART_CONSTANT_SYSTEM,
                          element,
                          // TODO(johnniwinther): Supported closure variables.
                          new NullCapturedVariableInfo()),
        () {
      irBuilder.buildFieldInitializerHeader();
      ir.Primitive initializer = build(node.initializer);
      return irBuilder.makeFieldDefinition(initializer);
    });
  }

  ir.FunctionDefinition handleFunctionDeclaration(
      analyzer.ExecutableElement function, FunctionBody body) {
    dart2js.FunctionElement element = converter.convertElement(function);
    return withBuilder(
        new DartIrBuilder(DART_CONSTANT_SYSTEM,
                          element,
                          // TODO(johnniwinther): Supported closure variables.
                          new NullCapturedVariableInfo()),
        () {
      irBuilder.buildFunctionHeader(
          function.parameters.map(converter.convertElement));
      // Visit the body directly to avoid processing the signature as
      // expressions.
      visit(body);
      return irBuilder.makeFunctionDefinition(const []);
    });
  }

  @override
  ir.Primitive visitFunctionExpression(FunctionExpression node) {
    return irBuilder.buildFunctionExpression(
        handleFunctionDeclaration(node.element, node.body));
  }

  @override
  ir.FunctionDefinition visitFunctionDeclaration(FunctionDeclaration node) {
    return handleFunctionDeclaration(
        node.element, node.functionExpression.body);
  }

  @override
  visitFunctionDeclarationStatement(FunctionDeclarationStatement node) {
    FunctionDeclaration functionDeclaration = node.functionDeclaration;
    analyzer.FunctionElement function = functionDeclaration.element;
    dart2js.FunctionElement element = converter.convertElement(function);
    ir.FunctionDefinition definition = handleFunctionDeclaration(
        function, functionDeclaration.functionExpression.body);
    irBuilder.declareLocalFunction(element, definition);
  }

  List<ir.Primitive> visitArguments(ArgumentList argumentList) {
    List<ir.Primitive> arguments = <ir.Primitive>[];
    for (Expression argument in argumentList.arguments) {
      ir.Primitive value = build(argument);
      if (value == null) {
        giveUp(argument,
            'Unsupported argument: $argument (${argument.runtimeType}).');
      }
      arguments.add(value);
    }
    return arguments;
  }

  @override
  ir.Node visitMethodInvocation(MethodInvocation node) {
    // Overridden to avoid eager visits of the receiver and arguments.
    return handleMethodInvocation(node);
  }

  @override
  ir.Primitive visitDynamicInvocation(MethodInvocation node,
                                      AccessSemantics semantics) {
    // TODO(johnniwinther): Handle implicit `this`.
    ir.Primitive receiver = build(semantics.target);
    List<ir.Primitive> arguments = visitArguments(node.argumentList);
    return irBuilder.buildDynamicInvocation(
        receiver,
        createSelectorFromMethodInvocation(
            node.argumentList, node.methodName.name),
        arguments);
  }

  @override
  ir.Primitive visitStaticMethodInvocation(MethodInvocation node,
                                           AccessSemantics semantics) {
    analyzer.Element staticElement = semantics.element;
    dart2js.Element element = converter.convertElement(staticElement);
    List<ir.Primitive> arguments = visitArguments(node.argumentList);
    return irBuilder.buildStaticInvocation(
        element,
        createSelectorFromMethodInvocation(
            node.argumentList, node.methodName.name),
        arguments);
  }

  @override
  ir.Node visitLocalFunctionAccess(AstNode node, AccessSemantics semantics) {
    return handleLocalAccess(node, semantics);
  }

  ir.Primitive handleLocalInvocation(MethodInvocation node,
                                     AccessSemantics semantics) {
    analyzer.Element staticElement = semantics.element;
    dart2js.Element element = converter.convertElement(staticElement);
    ir.Primitive receiver = irBuilder.buildLocalGet(element);
    List<ir.Definition> arguments = visitArguments(node.argumentList);
    return irBuilder.buildCallInvocation(
      receiver,
      createSelectorFromMethodInvocation(
          node.argumentList, node.methodName.name),
      arguments);
  }

  @override
  ir.Node visitLocalVariableInvocation(MethodInvocation node,
                                       AccessSemantics semantics) {
    return handleLocalInvocation(node, semantics);
  }

  @override
  ir.Primitive visitLocalFunctionInvocation(MethodInvocation node,
                                            AccessSemantics semantics) {
    return handleLocalInvocation(node, semantics);
  }

  @override
  ir.Primitive visitFunctionExpressionInvocation(
      FunctionExpressionInvocation node) {
    ir.Primitive target = build(node.function);
    List<ir.Definition> arguments = visitArguments(node.argumentList);
    return irBuilder.buildCallInvocation(
        target,
        createSelectorFromMethodInvocation(node.argumentList, 'call'),
        arguments);
  }

  @override
  ir.Primitive visitInstanceCreationExpression(
      InstanceCreationExpression node) {
    analyzer.Element staticElement = node.staticElement;
    if (staticElement != null) {
      dart2js.Element element = converter.convertElement(staticElement);
      dart2js.DartType type = converter.convertType(node.staticType);
      List<ir.Primitive> arguments = visitArguments(node.argumentList);
      String name = '';
      if (node.constructorName.name != null) {
        name = node.constructorName.name.name;
      }
      return irBuilder.buildConstructorInvocation(
          element,
          createSelectorFromMethodInvocation(node.argumentList, name),
          type,
          arguments);
    }
    return giveUp(node, "Unresolved constructor invocation.");
  }

  @override
  ir.Constant visitNullLiteral(NullLiteral node) {
    return irBuilder.buildNullLiteral();
  }

  @override
  ir.Constant visitBooleanLiteral(BooleanLiteral node) {
    return irBuilder.buildBooleanLiteral(node.value);
  }

  @override
  ir.Constant visitDoubleLiteral(DoubleLiteral node) {
    return irBuilder.buildDoubleLiteral(node.value);
  }

  @override
  ir.Constant visitIntegerLiteral(IntegerLiteral node) {
    return irBuilder.buildIntegerLiteral(node.value);
  }

  @override
  visitAdjacentStrings(AdjacentStrings node) {
    String value = node.stringValue;
    if (value != null) {
      return irBuilder.buildStringLiteral(value);
    }
    giveUp(node, "Non constant adjacent strings.");
  }

  @override
  ir.Constant visitSimpleStringLiteral(SimpleStringLiteral node) {
    return irBuilder.buildStringLiteral(node.value);
  }

  @override
  visitStringInterpolation(StringInterpolation node) {
    giveUp(node, "String interpolation.");
  }

  @override
  visitReturnStatement(ReturnStatement node) {
    irBuilder.buildReturn(build(node.expression));
  }

  @override
  ir.Node visitPropertyAccess(PropertyAccess node) {
    // Overridden to avoid eager visits of the receiver.
    return handlePropertyAccess(node);
  }

  @override
  ir.Node visitLocalVariableAccess(AstNode node, AccessSemantics semantics) {
    return handleLocalAccess(node, semantics);
  }

  @override
  ir.Node visitParameterAccess(AstNode node, AccessSemantics semantics) {
    return handleLocalAccess(node, semantics);
  }

  @override
  visitVariableDeclaration(VariableDeclaration node) {
    // TODO(johnniwinther): Handle constant local variables.
    ir.Node initialValue = build(node.initializer);
    irBuilder.declareLocalVariable(
        converter.convertElement(node.element),
        initialValue: initialValue);
  }

  dart2js.Element getLocal(AstNode node, AccessSemantics semantics) {
    analyzer.Element element = semantics.element;
    dart2js.Element target = converter.convertElement(element);
    assert(invariant(node, target.isLocal, '$target expected to be local.'));
    return target;
  }

  ir.Primitive handleLocalAccess(AstNode node, AccessSemantics semantics) {
    return irBuilder.buildLocalGet(getLocal(node, semantics));
  }

  ir.Primitive handleLocalAssignment(AssignmentExpression node,
                                     AccessSemantics semantics) {
    if (node.operator.lexeme != '=') {
      return giveUp(node, 'Assignment operator: ${node.operator.lexeme}');
    }
    return irBuilder.buildLocalSet(
        getLocal(node, semantics),
        build(node.rightHandSide));
  }

  @override
  ir.Node visitAssignmentExpression(AssignmentExpression node) {
    // Avoid eager visiting of left and right hand side.
    return handleAssignmentExpression(node);
  }

  @override
  ir.Node visitLocalVariableAssignment(AssignmentExpression node,
                                       AccessSemantics semantics) {
    return handleLocalAssignment(node, semantics);
  }

  @override
  ir.Node visitParameterAssignment(AssignmentExpression node,
                                   AccessSemantics semantics) {
    return handleLocalAssignment(node, semantics);
  }

  @override
  ir.Node visitStaticFieldAssignment(AssignmentExpression node,
                                     AccessSemantics semantics) {
    if (node.operator.lexeme != '=') {
      return giveUp(node, 'Assignment operator: ${node.operator.lexeme}');
    }
    analyzer.Element element = semantics.element;
    dart2js.Element target = converter.convertElement(element);
    // TODO(johnniwinther): Selector information should be computed in the
    // [TreeShaker] and shared with the [CpsGeneratingVisitor].
    assert(invariant(node, target.isTopLevel || target.isStatic,
                     '$target expected to be top-level or static.'));
    return irBuilder.buildStaticSet(
        target,
        new Selector.setter(target.name, target.library),
        build(node.rightHandSide));
  }

  @override
  ir.Node visitDynamicAccess(AstNode node, AccessSemantics semantics) {
    // TODO(johnniwinther): Handle implicit `this`.
    ir.Primitive receiver = build(semantics.target);
    return irBuilder.buildDynamicGet(receiver,
        new Selector.getter(semantics.identifier.name,
                            converter.convertElement(element.library)));
  }

  @override
  ir.Node visitStaticFieldAccess(AstNode node, AccessSemantics semantics) {
    analyzer.Element element = semantics.element;
    dart2js.Element target = converter.convertElement(element);
    // TODO(johnniwinther): Selector information should be computed in the
    // [TreeShaker] and shared with the [CpsGeneratingVisitor].
    assert(invariant(node, target.isTopLevel || target.isStatic,
                     '$target expected to be top-level or static.'));
    return irBuilder.buildStaticGet(target,
        new Selector.getter(target.name, target.library));
  }

  ir.Primitive handleBinaryExpression(BinaryExpression node,
                                      String op) {
    ir.Primitive left = build(node.leftOperand);
    ir.Primitive right = build(node.rightOperand);
    Selector selector = new Selector.binaryOperator(op);
    return irBuilder.buildDynamicInvocation(
        left, selector, <ir.Primitive>[right]);
  }

  ir.Node handleLazyOperator(BinaryExpression node, {bool isLazyOr: false}) {
    return irBuilder.buildLogicalOperator(
        build(node.leftOperand),
        subbuild(node.rightOperand),
        isLazyOr: isLazyOr);
  }

  @override
  ir.Node visitBinaryExpression(BinaryExpression node) {
    // TODO(johnniwinther,paulberry,brianwilkerson): The operator should be
    // available through an enum.
    String op = node.operator.lexeme;
    switch (op) {
    case '||':
    case '&&':
      return handleLazyOperator(node, isLazyOr: op == '||');
    case '!=':
      return irBuilder.buildNegation(handleBinaryExpression(node, '=='));
    default:
      return handleBinaryExpression(node, op);
    }
  }

  @override
  ir.Node visitConditionalExpression(ConditionalExpression node) {
    return irBuilder.buildConditional(
        build(node.condition),
        subbuild(node.thenExpression),
        subbuild(node.elseExpression));
  }

  @override
  visitIfStatement(IfStatement node) {
    irBuilder.buildIf(
        build(node.condition),
        subbuild(node.thenStatement),
        subbuild(node.elseStatement));
  }

  @override
  visitBlock(Block node) {
    irBuilder.buildBlock(node.statements, build);
  }

  @override
  ir.Node visitListLiteral(ListLiteral node) {
    dart2js.InterfaceType type = converter.convertType(node.staticType);
    // TODO(johnniwinther): Use `build` instead of `(e) => build(e)` when issue
    // 18630 has been resolved.
    Iterable<ir.Primitive> values = node.elements.map((e) => build(e));
    return irBuilder.buildListLiteral(type, values);
  }

  @override
  ir.Node visitMapLiteral(MapLiteral node) {
    dart2js.InterfaceType type = converter.convertType(node.staticType);
    return irBuilder.buildMapLiteral(
        type,
        node.entries.map((e) => e.key),
        node.entries.map((e) => e.value),
        build);
  }

  @override
  visitForStatement(ForStatement node) {
    // TODO(johnniwinther): Support `for` as a jump target.
    List<dart2js.LocalElement> loopVariables = <dart2js.LocalElement>[];
    SubbuildFunction buildInitializer;
    if (node.variables != null) {
      buildInitializer = subbuild(node.variables);
      for (VariableDeclaration variable in node.variables.variables) {
        loopVariables.add(converter.convertElement(variable.element));
      }
    } else {
      buildInitializer = subbuild(node.initialization);
    }
    irBuilder.buildFor(buildInitializer: buildInitializer,
                       buildCondition: subbuild(node.condition),
                       buildBody: subbuild(node.body),
                       buildUpdate: subbuildSequence(node.updaters),
                       loopVariables: loopVariables);
  }

  @override
  visitWhileStatement(WhileStatement node) {
    // TODO(johnniwinther): Support `while` as a jump target.
    irBuilder.buildWhile(buildCondition: subbuild(node.condition),
                         buildBody: subbuild(node.body));
  }

  @override
  visitDeclaredIdentifier(DeclaredIdentifier node) {
    giveUp(node, "Unexpected node: DeclaredIdentifier");
  }

  @override
  visitForEachStatement(ForEachStatement node) {
    SubbuildFunction buildVariableDeclaration;
    dart2js.Element variableElement;
    Selector variableSelector;
    if (node.identifier != null) {
       AccessSemantics accessSemantics =
           node.identifier.accept(ACCESS_SEMANTICS_VISITOR);
       if (accessSemantics.kind == AccessKind.DYNAMIC) {
         variableSelector = new Selector.setter(
             node.identifier.name, converter.convertElement(currentLibrary));
       } else if (accessSemantics.element != null) {
         variableElement = converter.convertElement(accessSemantics.element);
         variableSelector = new Selector.setter(
             variableElement.name,
             converter.convertElement(accessSemantics.element.library));
       } else {
         giveUp(node, 'For-in of unresolved variable: $accessSemantics');
       }
    } else {
      assert(invariant(
          node, node.loopVariable != null, "Loop variable expected"));
      variableElement = converter.convertElement(node.loopVariable.element);
      buildVariableDeclaration = (IrBuilder builder) {
        builder.declareLocalVariable(variableElement);
      };
    }
    // TODO(johnniwinther): Support `for-in` as a jump target.
    irBuilder.buildForIn(
        buildExpression: subbuild(node.iterable),
        buildVariableDeclaration: buildVariableDeclaration,
        variableElement: variableElement,
        variableSelector: variableSelector,
        buildBody: subbuild(node.body));
  }
  @override
  ir.Primitive visitIsExpression(IsExpression node) {
    return irBuilder.buildTypeOperator(
        visit(node.expression),
        converter.convertType(node.type.type),
        isTypeTest: true,
        isNotCheck: node.notOperator != null);
  }

  @override
  ir.Primitive visitAsExpression(AsExpression node) {
    return irBuilder.buildTypeOperator(
        visit(node.expression),
        converter.convertType(node.type.type),
        isTypeTest: false);
  }
}

class NullCapturedVariableInfo extends DartCapturedVariableInfo {
  Iterable get capturedVariables => const [];
}
