// 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 dart_tree;

import '../dart2jslib.dart' as dart2js;
import '../dart_types.dart';
import '../util/util.dart';
import '../elements/elements.dart' show FunctionElement, FunctionSignature;
import '../ir/ir_nodes.dart' as ir;
import '../tree/tree.dart' as ast;
import '../scanner/scannerlib.dart';

// The Tree language is the target of translation out of the CPS-based IR.
//
// The translation from CPS to Dart consists of several stages.  Among the
// stages are translation to direct style, translation out of SSA, eliminating
// unnecessary names, recognizing high-level control constructs.  Combining
// these separate concerns is complicated and the constraints of the CPS-based
// language do not permit a multi-stage translation.
//
// For that reason, CPS is translated to the direct-style language Tree.
// Translation out of SSA, unnaming, and control-flow, as well as 'instruction
// selection' are performed on the Tree language.
//
// In contrast to the CPS-based IR, non-primitive expressions can be named and
// arguments (to calls, primitives, and blocks) can be arbitrary expressions.

/**
 * The base class of all Tree nodes.
 */
abstract class Node {
  accept(Visitor visitor);
}

/**
 * The base class of [Expression]s.
 */
abstract class Expression extends Node {
  bool get isPure;
}

/**
 * Variables are [Expression]s.
 */
class Variable extends Expression {
  // A counter used to generate names.  The counter is reset to 0 for each
  // function emitted.
  static int counter = 0;
  static String _newName() => 'v${counter++}';

  ast.Identifier identifier = null;

  ast.Identifier assignIdentifier() {
    assert(identifier == null);
    String name = _newName();
    identifier = Emitter.makeIdentifier(name);
    return identifier;
  }

  final bool isPure = true;

  accept(Visitor visitor) => visitor.visitVariable(this);
}

/**
 * A sequence of expressions.
 */
class Sequence extends Expression {
  final List<Expression> expressions;

  Sequence(this.expressions);

  bool get isPure => expressions.every((e) => e.isPure);

  accept(Visitor visitor) => visitor.visitSequence(this);
}

/**
 * A local binding of a [Variable] to an [Expression].
 *
 * In contrast to the CPS-based IR, non-primitive expressions can be named
 * with let.
 */
class LetVal extends Expression {
  final Variable variable;
  final Expression definition;
  final Expression body;

  LetVal(this.variable, this.definition, this.body);

  bool get isPure => definition.isPure && body.isPure;

  accept(Visitor visitor) => visitor.visitLetVal(this);
}

/**
 * A call to a static target.
 *
 * In contrast to the CPS-based IR, the arguments can be arbitrary expressions.
 */
class InvokeStatic extends Expression {
  final FunctionElement target;
  final List<Expression> arguments;

  InvokeStatic(this.target, this.arguments);

  final bool isPure = false;

  accept(Visitor visitor) => visitor.visitInvokeStatic(this);
}

/**
 * A return exit from the function.
 *
 * In contrast to the CPS-based IR, the return value is an arbitrary
 * expression.
 */
class Return extends Expression {
  Expression value;

  Return(this.value);

  final bool isPure = true;

  accept(Visitor visitor) => visitor.visitReturn(this);
}

/**
 * A constant.
 */
class Constant extends Expression {
  final dart2js.Constant value;

  Constant(this.value);

  final bool isPure = true;

  accept(Visitor visitor) => visitor.visitConstant(this);
}

abstract class Visitor<T> {
  // Abstract classes.
  T visitNode(Node node) => node.accept(this);
  T visitExpression(Expression node) => visitNode(node);

  // Concrete classes.
  T visitVariable(Variable node) => visitExpression(node);
  T visitSequence(Sequence node) => visitExpression(node);
  T visitLetVal(LetVal node) => visitExpression(node);
  T visitInvokeStatic(InvokeStatic node) => visitExpression(node);
  T visitReturn(Return node) => visitExpression(node);
  T visitConstant(Constant node) => visitExpression(node);
}

/**
 * Builder translates from CPS-based IR to direct-style Tree.
 *
 * A call `Invoke(fun, cont, args)`, where cont is a singly-referenced
 * non-exit continuation `Cont(v, body)` is translated into a direct-style call
 * whose value is bound in the continuation body:
 *
 * `LetVal(v, Invoke(fun, args), body)`
 *
 * and the continuation definition is eliminated.  A similar translation is
 * applied to continuation invocations where the continuation is
 * singly-referenced, though such invocations should not appear in optimized
 * IR.
 *
 * A call `Invoke(fun, cont, args)`, where cont is multiply referenced, is
 * translated into a call followed by a jump with an argument:
 *
 * `Jump L(Invoke(fun, args))`
 *
 * and the continuation is translated into a named block that takes an
 * argument:
 *
 * `LetLabel(L, v, body)`
 *
 * Block arguments are later replaced with data flow during the Tree-to-Tree
 * translation out of SSA.  Jumps are eliminated during the Tree-to-Tree
 * control-flow recognition.
 *
 * Otherwise, the output of Builder looks very much like the input.  In
 * particular, intermediate values and blocks used for local control flow are
 * still all named.
 */
class Builder extends ir.Visitor<Expression> {
  final dart2js.Compiler compiler;

  // Uses of IR definitions are replaced with Tree variables.  This is the
  // mapping from definitions to variables.
  final Map<ir.Definition, Variable> variables = {};

  ir.Continuation returnContinuation;

  Builder(this.compiler);

  List<Expression> translateArguments(List<ir.Reference> args) {
    return new List.generate(args.length,
         (int index) => variables[args[index].definition]);
  }

  Expression visitFunction(ir.Function node) {
    // Functions are simplistically translated to their bodies.  For now this
    // is good enough.
    returnContinuation = node.returnContinuation;
    return node.body.accept(this);
  }

  Expression visitLetPrim(ir.LetPrim node) {
    // LetPrim is translated to LetVal.
    Expression definition = node.primitive.accept(this);
    if (node.primitive.hasAtLeastOneUse) {
      Variable variable = new Variable();
      variables[node.primitive] = variable;
      return new LetVal(variable, definition, node.body.accept(this));
    } else {
      return new Sequence([definition, node.body.accept(this)]);
    }
  }

  Expression visitLetCont(ir.LetCont node) {
    // TODO(kmillikin): Allow continuations to have multiple uses.  This could
    // arise due to the representation of local control flow or due to
    // optimization.
    assert(node.continuation.hasAtMostOneUse);
    return node.body.accept(this);
  }

  Expression visitInvokeStatic(ir.InvokeStatic node) {
    // Calls are translated to direct style.
    List<Expression> arguments = translateArguments(node.arguments);
    Expression invoke = new InvokeStatic(node.target, arguments);
    ir.Continuation cont = node.continuation.definition;
    if (cont == returnContinuation) {
      return new Return(invoke);
    } else {
      assert(cont.hasExactlyOneUse);
      if (cont.parameter.hasAtLeastOneUse) {
        Variable variable = new Variable();
        variables[cont.parameter] = variable;
        return new LetVal(variable, invoke, cont.body.accept(this));
      } else {
        return new Sequence([invoke, cont.body.accept(this)]);
      }
    }
  }

  Expression visitInvokeContinuation(ir.InvokeContinuation node) {
    // TODO(kmillikin): Support non-return continuations.  These could arise
    // due to local control flow or due to inlining or other optimization.
    assert(node.continuation.definition == returnContinuation);
    return new Return(variables[node.argument.definition]);
  }

  Expression visitConstant(ir.Constant node) {
    return new Constant(node.value);
  }

  Expression visitParameter(ir.Parameter node) {
    // Continuation parameters are not visited (continuations themselves are
    // not visited yet).
    compiler.internalError(compiler.currentElement, 'Unexpected IR node.');
    return null;
  }

  Expression visitContinuation(ir.Continuation node) {
    // Until continuations with multiple uses are supported, they are not
    // visited.
    compiler.internalError(compiler.currentElement, 'Unexpected IR node.');
    return null;
  }
}

/**
 * Unnamer propagates single-use definitions to their use site when possible.
 *
 * After translating out of CPS, all intermediate values are bound by [LetVal].
 * This transformation propagates such definitions to their uses when it is
 * safe and profitable.  Bindings are processed "on demand" when their uses are
 * seen, but are only processed once to keep this transformation linear in
 * the size of the tree.
 *
 * The transformation builds an environment containing [LetVal] bindings that
 * are in scope.  These bindings have yet-untranslated definitions.  When a use
 * is encountered the transformation determines if it is safe and profitable
 * to propagate the definition to its use.  If so, it is removed from the
 * environment and the definition is recursively processed (in the
 * new environment at the use site) before being propagated.
 *
 * See [visitVariable] for the implementation of the heuristic for propagating
 * a definition.
 */
class Unnamer extends Visitor<Expression> {
  // The binding environment.  The rightmost element of the list is the nearest
  // enclosing binding.
  List<LetVal> environment;

  Expression unname(Expression body) {
    environment = <LetVal>[];
    body = body.accept(this);

    // TODO(kmillikin):  Allow definitions that are not propagated.  Here,
    // this means rebuilding the binding with a recursively unnamed definition,
    // or else introducing a variable definition and an assignment.
    assert(environment.isEmpty);
    return body;
  }

  Expression visitVariable(Variable node) {
    // Propagate a variable's definition to its use site if:
    // 1.  It has a single use, to avoid code growth and potential duplication
    //     of side effects, AND
    // 2a. It is pure (i.e., does not have side effects that prevent it from
    //     being moved), OR
    // 2b. There are only pure expressions between the definition and use.

    // TODO(kmillikin): It's not always beneficial to propagate pure
    // definitions---it can prevent propagation of their inputs.  Implement
    // a heuristic to avoid this.

    // TODO(kmillikin): Replace linear search with something faster in
    // practice.
    bool seenImpure = false;
    for (int i = environment.length - 1; i >= 0; --i) {
      if (environment[i].variable == node) {
        if (!seenImpure || environment[i].definition.isPure) {
          // Use the definition if it is pure or if it is the first impure
          // definition (i.e., propagating past only pure expressions).
          return environment.removeAt(i).definition.accept(this);
        }
        break;
      } else if (!environment[i].definition.isPure) {
        // Once the first impure definition is seen, impure definitions should
        // no longer be propagated.  Continue searching for a pure definition.
        seenImpure = true;
      }
    }
    // If the definition could not be propagated, leave the variable use.
    return node;
  }

  Expression visitSequence(Sequence node) {
    for (int i = 0; i < node.expressions.length; ++i) {
      node.expressions[i] = node.expressions[i].accept(this);
    }
    return node;
  }

  Expression visitLetVal(LetVal node) {
    environment.add(node);
    Expression body = node.body.accept(this);

    // TODO(kmillikin): Allow definitions that are not propagated.  Currently,
    // the only bindings are anonymous intermediate values (which only have one
    // use in the absence of optimizations) and they are not reordered.
    assert(!environment.contains(node));
    return body;
  }

  Expression visitInvokeStatic(InvokeStatic node) {
    // Process arguments right-to-left, the opposite of evaluation order.
    for (int i = node.arguments.length - 1; i >= 0; --i) {
      node.arguments[i] = node.arguments[i].accept(this);
    }
    return node;
  }

  Expression visitReturn(Return node) {
    node.value = node.value.accept(this);
    return node;
  }

  visitConstant(Constant node) {
    return node;
  }
}

/**
 * [Emitter] translates Tree to a Dart AST.
 *
 * The AST is handed off to the Dart backend for renaming and to emit Dart
 * code.  Generating an AST is a temporary approach to integrating Tree into
 * the Dart backend.  Ultimately, either Dart code directly will be emitted or
 * the translation will be to a backend-specific Dart AST and not the same
 * one used by the front end.
 *
 * The front end's AST is an unwieldy interface for constructing and generating
 * Dart code.  AST nodes require references to tokens and the tokens will be
 * used by the unparser.  This means that constructing an AST also requires
 * constructing (redundant) tokens.  Unparsing AST nodes also requires a
 * mapping from nodes to elements --- so this mapping must be constructed by
 * the emitter.
 */
class Emitter extends Visitor<ast.Node> {
  ConstantEmitter constantEmitter = new ConstantEmitter();

  // Accumulate a list of variables used, these are hoisted and declared on
  // entry to the function.
  List<ast.Identifier> variables = <ast.Identifier>[];

  // A mapping from nodes to elements, constructed while walking the input
  // tree.
  dart2js.TreeElementMapping treeElements;

  // Tokens needed in the AST.
  final Token openParen = new BeginGroupToken(OPEN_PAREN_INFO, -1);
  final Token closeParen = new SymbolToken(CLOSE_PAREN_INFO, -1);
  final Token openBrace = new BeginGroupToken(OPEN_CURLY_BRACKET_INFO, -1);
  final Token closeBrace = new SymbolToken(CLOSE_CURLY_BRACKET_INFO, -1);
  final Token semicolon = new SymbolToken(SEMICOLON_INFO, -1);

  // Helper methods to construct ASTs.
  static ast.Identifier makeIdentifier(String name) {
    return new ast.Identifier(
        new StringToken.fromString(IDENTIFIER_INFO, name, -1));
  }

  ast.NodeList makeArgumentList(List<ast.Node> arguments) {
    return new ast.NodeList(openParen,
                            new Link<ast.Node>.fromList(arguments),
                            closeParen,
                            ',');
  }

  ast.Block makeBlock(List<ast.Node> statements) {
    return new ast.Block(new ast.NodeList(
        openBrace, new Link<ast.Node>.fromList(statements), closeBrace));
  }

  static ast.SendSet makeAssignment(ast.Identifier identifier,
                                    ast.Expression expression) {
    return new ast.SendSet(
        null,
        identifier,
        new ast.Operator(new SymbolToken(EQ_INFO, -1)),
        new ast.NodeList.singleton(expression));
  }

  /**
   * Translate the body of a function to an AST FunctionExpression.
   */
  ast.FunctionExpression emit(FunctionElement element,
                              dart2js.TreeElementMapping treeElements,
                              Expression expr) {
    // Reset the variable index.  This function is not reentrant.
    Variable.counter = 0;
    this.treeElements = treeElements;
    ast.Identifier name = makeIdentifier(element.name);

    TypeEmitter typeEmitter = new TypeEmitter();
    FunctionSignature signature = element.functionSignature;
    ast.TypeAnnotation returnType;
    if (!signature.type.returnType.isDynamic) {
      returnType =
          signature.type.returnType.accept(typeEmitter, treeElements);
    }

    List<ast.VariableDefinitions> parameterList = <ast.VariableDefinitions>[];
    signature.orderedForEachParameter((parameter) {
      ast.TypeAnnotation type;
      if (!parameter.type.isDynamic) {
        type = parameter.type.accept(typeEmitter, treeElements);
      }
      parameterList.add(new ast.VariableDefinitions(
          type,
          ast.Modifiers.EMPTY,
          new ast.NodeList.singleton(makeIdentifier(parameter.name))));
    });
    ast.NodeList parameters =
        new ast.NodeList(openParen,
                         new Link<ast.Node>.fromList(parameterList),
                         closeParen,
                         ',');

    ast.Node body = expr.accept(this);

    if (!variables.isEmpty) {
      // Introduce hoisted definitions for all variables.
      ast.Identifier modifier =
          new ast.Identifier(new KeywordToken(Keyword.keywords['var'], -1));
      ast.VariableDefinitions definitions = new ast.VariableDefinitions(
          null,
          new ast.Modifiers(new ast.NodeList(
              null,
              new Link<ast.Node>.fromList([modifier]),
              null,
              ' ')),
          new ast.NodeList(
              null,
              new Link<ast.Node>.fromList(variables),
              semicolon,
              ','));
      body = concatenate(definitions, body);
    }

    if (body is ast.Return) {
      // Use a short form for bodies that are a single return.
      ast.Expression value = (body as ast.Return).expression;
      if (value is ast.LiteralNull) {
        // '{ return null; }' is '{}'.
        body = makeBlock([]);
      } else {
        // '{ return e; }' is '=> e;'.
        body = new ast.Return(new SymbolToken(FUNCTION_INFO, -1),
                              semicolon,
                              value);
      }
    } else if (body is ast.Block) {
      // Remove a final 'return null' that ends the body block.
      Link<ast.Node> nodes = (body as ast.Block).statements.nodes;
      ast.Node last;
      for (var n in nodes) {
        last = n;
      }
      if (last is ast.Return
          && (last as ast.Return).expression is ast.LiteralNull) {
        List<ast.Node> statements =
            (body as ast.Block).statements.nodes.toList();
        statements.removeLast();
        body = makeBlock(statements);
      }
    }

    return new ast.FunctionExpression(name, parameters, body, returnType,
        ast.Modifiers.EMPTY, null, null);
  }

  /**
   * Translate a list of arguments to an AST NodeList.
   */
  ast.NodeList translateArguments(List<Expression> args) {
    List<ast.Expression> arguments =
        args.map((e) => e.accept(this)).toList(growable: false);
    return makeArgumentList(arguments);
  }

  /**
   * Concatenate a pair of AST expressions or statements into a single Block
   * statement.
   */
  ast.Node concatenate(ast.Node first, ast.Node second) {
    // This is a convenient but very inefficient way to accumulate statements.
    // The Block and NodeList nodes are not mutable so we can't simply use a
    // Block or NodeList as an accumulator.  Using a List<Node> requires
    // special casing and extra state to handle the expression/statement
    // distinction.
    // TODO(kmillikin): If we don't get rid of this Emitter, use a more
    // efficient way to accumulate nodes.
    LinkBuilder<ast.Node> statements = new LinkBuilder<ast.Node>();

    addStatements(ast.Node node) {
      if (node is ast.Block) {
        for (var n in node.statements.nodes) {
          statements.addLast(n);
        }
      } else if (node is ast.Expression) {
          statements.addLast(new ast.ExpressionStatement(node, semicolon));
      } else {
        statements.addLast(node);
      }
    }

    addStatements(first);
    addStatements(second);

    return new ast.Block(
        new ast.NodeList(openBrace, statements.toLink(), closeBrace));
  }

  ast.Node visitVariable(Variable node) {
    // The scope of variables is the body of their binding, so a name has
    // already been generated when we visit a variable.
    assert(node.identifier != null);
    return new ast.Send(null, node.identifier);
  }

  ast.Node visitSequence(Sequence node) {
    return node.expressions.map((e) => e.accept(this)).reduce(concatenate);
  }

  ast.Node visitLetVal(LetVal node) {
    // Let bindings translate into assignments.
    ast.Identifier identifier = node.variable.assignIdentifier();
    variables.add(identifier);

    ast.Expression expression = node.definition.accept(this);
    ast.Expression assignment = makeAssignment(identifier, expression);

    ast.Node rest = node.body.accept(this);
    return concatenate(assignment, rest);
  }

  ast.Node visitInvokeStatic(InvokeStatic node) {
    ast.Identifier name = makeIdentifier(node.target.name);
    ast.Send send =
        new ast.Send(null, name, translateArguments(node.arguments));
    treeElements[send] = node.target;
    return send;
  }

  ast.Node visitReturn(Return node) {
    ast.Expression expression = node.value.accept(this);
    return new ast.Return(
        new KeywordToken(Keyword.keywords['return'], -1),
        semicolon,
        expression);
  }

  ast.Node visitConstant(Constant node) {
    return node.value.accept(constantEmitter);
  }
}

class TypeEmitter extends
    DartTypeVisitor<ast.TypeAnnotation, dart2js.TreeElementMapping> {

  // Supported types are verified at IR construction time.  The unimplemented
  // emit methods should be unreachable.
  ast.TypeAnnotation unimplemented() => throw new UnimplementedError();

  ast.TypeAnnotation makeSimpleAnnotation(
      DartType type,
      dart2js.TreeElementMapping treeElements) {
    ast.TypeAnnotation annotation =
        new ast.TypeAnnotation(Emitter.makeIdentifier(type.toString()), null);
    treeElements.setType(annotation, type);
    return annotation;
  }

  ast.TypeAnnotation visitType(DartType type,
                               dart2js.TreeElementMapping treeElements) {
    return unimplemented();
  }

  ast.TypeAnnotation visitVoidType(VoidType type,
                                   dart2js.TreeElementMapping treeElements) {
    return makeSimpleAnnotation(type, treeElements);
  }

  ast.TypeAnnotation visitInterfaceType(
      InterfaceType type,
      dart2js.TreeElementMapping treeElements) {
    assert(!type.isGeneric);
    return makeSimpleAnnotation(type, treeElements);
  }

  ast.TypeAnnotation visitTypedefType(
      TypedefType type,
      dart2js.TreeElementMapping treeElements) {
    assert(!type.isGeneric);
    return makeSimpleAnnotation(type, treeElements);
  }

  ast.TypeAnnotation visitDynamicType(
      DynamicType type,
      dart2js.TreeElementMapping treeElements) {
    return unimplemented();
  }
}

class ConstantEmitter extends dart2js.ConstantVisitor<ast.Expression> {
  ast.Expression unimplemented() => throw new UnimplementedError();

  ast.Expression visitFunction(dart2js.FunctionConstant constant) {
    return unimplemented();
  }

  ast.Expression visitNull(dart2js.NullConstant constant) {
    return new ast.LiteralNull(
        new KeywordToken(Keyword.keywords['null'], -1));
  }

  ast.Expression visitInt(dart2js.IntConstant constant) {
    return new ast.LiteralInt(
        new StringToken.fromString(INT_INFO, constant.value.toString(), -1),
        null);
  }

  ast.Expression visitDouble(dart2js.DoubleConstant constant) {
    return new ast.LiteralDouble(
        new StringToken.fromString(DOUBLE_INFO, constant.value.toString(), -1),
        null);
  }

  ast.Expression visitTrue(dart2js.TrueConstant constant) {
    return new ast.LiteralBool(
        new KeywordToken(Keyword.keywords['true'], -1), null);
  }

  ast.Expression visitFalse(dart2js.FalseConstant constant) {
    return new ast.LiteralBool(
        new KeywordToken(Keyword.keywords['false'], -1), null);
  }

  ast.Expression visitString(dart2js.StringConstant constant) {
    return unimplemented();
  }

  ast.Expression visitList(dart2js.ListConstant constant) {
    return unimplemented();
  }

  ast.Expression visitMap(dart2js.MapConstant constant) {
    return unimplemented();
  }

  ast.Expression visitConstructed(dart2js.ConstructedConstant constant) {
    return unimplemented();
  }

  ast.Expression visitType(dart2js.TypeConstant constant) {
    return unimplemented();
  }

  ast.Expression visitInterceptor(dart2js.InterceptorConstant constant) {
    return unimplemented();
  }

  ast.Expression visitDummy(dart2js.DummyConstant constant) {
    return unimplemented();
  }
}
