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

import '../tree_ir/tree_ir_nodes.dart' as tree;
import 'backend_ast_nodes.dart';
import '../constants/expressions.dart';
import '../constants/values.dart';
import '../dart_types.dart';
import '../elements/elements.dart';
import '../elements/modelx.dart' as modelx;
import '../universe/universe.dart';
import '../tree/tree.dart' as tree show Modifiers;

/// Translates the dart_tree IR to Dart backend AST.
RootNode emit(tree.RootNode root) {
  return new ASTEmitter().emit(root);
}

// TODO(johnniwinther): Split into function/block state.
class BuilderContext<T> {
  /// Builder context for the enclosing function, or null if the current
  /// function is not a local function.
  BuilderContext<T> _parent;

  /// Variables to be hoisted at the top of the current function.
  final List<VariableDeclaration> variables = <VariableDeclaration>[];

  /// Maps variables to their name.
  final Map<tree.Variable, String> variableNames;

  /// Maps local constants to their name.
  final Map<VariableElement, String> constantNames =
      <VariableElement, String>{};

  /// Variables that have had their declaration created.
  final Set<tree.Variable> declaredVariables = new Set<tree.Variable>();

  /// Variables that are used as catch handler parameters.
  final Set<tree.Variable> handlerVariables = new Set<tree.Variable>();

  /// Variable names that have already been used. Used to avoid name clashes.
  final Set<String> usedVariableNames;

  /// Statements emitted by the most recent call to [visitStatement].
  List<T> _statementBuffer = <T>[];

  /// The element currently being emitted.
  ExecutableElement currentElement;

  /// Bookkeeping object needed to synthesize a variable declaration.
  final modelx.VariableList variableList
      = new modelx.VariableList(tree.Modifiers.EMPTY);

  /// Input to [visitStatement]. Denotes the statement that will execute next
  /// if the statements produced by [visitStatement] complete normally.
  /// Set to null if control will fall over the end of the method.
  tree.Statement fallthrough = null;

  /// Labels that could not be eliminated using fallthrough.
  final Set<tree.Label> _usedLabels = new Set<tree.Label>();

  final bool inInitializer;

  /// The first dart_tree statement that is not converted to a variable
  /// initializer.
  tree.Statement firstStatement;

  BuilderContext() : usedVariableNames = new Set<String>(),
                     inInitializer = false,
                     variableNames = <tree.Variable, String>{};

  BuilderContext.inner(BuilderContext<T> parent)
      : this._parent = parent,
        usedVariableNames = parent.usedVariableNames,
        inInitializer = false,
        variableNames = <tree.Variable, String>{};

  BuilderContext.initializer(BuilderContext<T> parent)
      : this._parent = parent,
        usedVariableNames = parent.usedVariableNames,
        inInitializer = true,
        variableNames =
            new Map<tree.Variable, String>.from(parent.variableNames);

  // TODO(johnniwinther): Fully encapsulate handling of parameter, variable
  // and local function declarations.
  void addDeclaration(tree.Variable variable, [Expression initializer]) {
    assert(!declaredVariables.contains(variable));
    String name = getVariableName(variable);
    VariableDeclaration decl = new VariableDeclaration(name, initializer);
    decl.element = variable.element;
    declaredVariables.add(variable);
    variables.add(decl);
  }

  /// Creates an [Identifier] referring to the given variable.
  Expression makeVariableAccess(tree.Variable variable) {
    return new Identifier(getVariableName(variable))
               ..element = variable.element;
  }

  /// Generates a name for the given variable and synthesizes an element for it,
  /// if necessary.
  String getVariableName(tree.Variable variable) {
    // If the variable belongs to an enclosing function, ask the parent emitter
    // for the variable name.
    if (!inInitializer && variable.host != currentElement) {
      return _parent.getVariableName(variable);
    }

    // Get the name if we already have one.
    String name = variableNames[variable];
    if (name != null) {
      return name;
    }

    // Synthesize a variable name that isn't used elsewhere.
    // The [usedVariableNames] set is shared between nested emitters,
    // so this also prevents clash with variables in an enclosing/inner scope.
    // The renaming phase after codegen will further prefix local variables
    // so they cannot clash with top-level variables or fields.
    String prefix = variable.element == null ? 'v' : variable.element.name;
    int counter = 0;
    name = variable.element == null ? '$prefix$counter' : variable.element.name;
    while (!usedVariableNames.add(name)) {
      ++counter;
      name = '$prefix$counter';
    }
    variableNames[variable] = name;

    // Synthesize an element for the variable
    if (variable.element == null || name != variable.element.name) {
      // TODO(johnniwinther): Replace by synthetic [Entity].
      variable.element = new _SyntheticLocalVariableElement(
          name,
          currentElement,
          variableList);
    }
    return name;
  }

  /// Adds declarations for all variables that are still undeclared.
  void declareRemainingVariables() {
    // These variables can be referenced from other variable initializers if
    // they are set by an assignment expression, so we declare variables before
    // those with initializers.
    List<VariableDeclaration> declarations = <VariableDeclaration>[];
    for (tree.Variable variable in variableNames.keys) {
      if (!declaredVariables.contains(variable)) {
        String name = getVariableName(variable);
        VariableDeclaration decl = new VariableDeclaration(name);
        decl.element = variable.element;
        declarations.add(decl);
        declaredVariables.add(variable);
      }
    }
    // Prepend all variables at once to avoid quadratic blowup.
    variables.insertAll(0, declarations);
  }

  String getConstantName(VariableElement element) {
    assert(element.kind == ElementKind.VARIABLE);
    if (element.enclosingElement != currentElement) {
      return _parent.getConstantName(element);
    }
    String name = constantNames[element];
    if (name != null) {
      return name;
    }
    String prefix = element.name;
    int counter = 0;
    name = element.name;
    while (!usedVariableNames.add(name)) {
      ++counter;
      name = '$prefix$counter';
    }
    constantNames[element] = name;
    return name;
  }

  List<T> inSubcontext(f(BuilderContext<T> subcontext),
                       {tree.Statement fallthrough}) {
    List<T> savedBuffer = this._statementBuffer;
    tree.Statement savedFallthrough = this.fallthrough;
    List<T> buffer = this._statementBuffer = <T>[];
    if (fallthrough != null) {
      this.fallthrough = fallthrough;
    }
    f(this);
    this.fallthrough = savedFallthrough;
    this._statementBuffer = savedBuffer;
    return buffer;
  }

  /// Removes a trailing "return null" from the current block.
  void removeTrailingReturn(bool isReturnNull(T statement)) {
    if (_statementBuffer.isEmpty) return;
    if (isReturnNull(_statementBuffer.last)) {
      _statementBuffer.removeLast();
    }
  }

  /// Register [label] as used.
  void useLabel(tree.Label label) {
    _usedLabels.add(label);
  }

  /// Remove [label] and return `true` if it was used.
  bool removeUsedLabel(tree.Label label) {
    return _usedLabels.remove(label);
  }

  /// Add [statement] to the current block.
  void addStatement(T statement) {
    _statementBuffer.add(statement);
  }

  /// The statements in the current block.
  Iterable<T> get statements => _statementBuffer;
}

/// Translates the dart_tree IR to Dart backend AST.
/// An instance of this class should only be used once; a fresh emitter
/// must be created for each function to be emitted.
class ASTEmitter
  extends tree.StatementVisitor1<dynamic, BuilderContext<Statement>>
     with tree.ExpressionVisitor1<Expression, BuilderContext<Statement>>,
          tree.RootVisitor1<RootNode, BuilderContext<Statement>>,
          tree.InitializerVisitor1<Initializer, BuilderContext<Statement>> {

  RootNode emit(tree.RootNode node) {
    return visitRootNode(node, new BuilderContext<Statement>());
  }

  @override
  FieldDefinition visitFieldDefinition(tree.FieldDefinition definition,
                                       BuilderContext<Statement> context) {
    context.currentElement = definition.element;
    Expression initializer;
    if (!definition.isEmpty) {
      visitStatement(definition.body, context);
      List<Statement> bodyParts;
      for (tree.Variable variable in context.variableNames.keys) {
        if (!context.declaredVariables.contains(variable)) {
          context.addDeclaration(variable);
        }
      }
      if (context.variables.length > 0) {
        bodyParts = new List<Statement>();
        bodyParts.add(new VariableDeclarations(context.variables));
        bodyParts.addAll(context.statements);
      } else {
        bodyParts = context.statements;
      }
      initializer = ensureExpression(bodyParts);
    }

    return new FieldDefinition(definition.element, initializer);
  }

  /// Returns an expression that will evaluate all of [bodyParts].
  /// If [bodyParts] is a single [Return] return its value.
  /// Otherwise wrap the body-parts in an immediately invoked closure.
  Expression ensureExpression(List<Statement> bodyParts) {
    if (bodyParts.length == 1) {
      Statement onlyStatement = bodyParts.single;
      if (onlyStatement is Return) {
        return onlyStatement.expression;
      }
    }
    Statement body = new Block(bodyParts);
    FunctionExpression function =
        new FunctionExpression(new Parameters([]), body);
    function.element = null;
    return new CallFunction(function, []);
  }

  bool _recognizeTrailingReturn(Statement statement) {
    if (statement is Return) {
      Expression expr = statement.expression;
      if (expr == null || expr is Literal && expr.value.isNull) {
        return true;
      }
    }
    return false;
  }

  @override
  FunctionExpression visitConstructorDefinition(
        tree.ConstructorDefinition definition,
        BuilderContext<Statement> context) {
    context.currentElement = definition.element;

    Parameters parameters = emitRootParameters(
        definition, definition.defaultParameterValues, context);

    // Declare parameters.
    for (tree.Variable param in definition.parameters) {
      context.variableNames[param] = param.element.name;
      context.usedVariableNames.add(param.element.name);
      context.declaredVariables.add(param);
    }

    List<Initializer> initializers;
    Statement body;

    if (!definition.isEmpty) {
      initializers =
          definition.initializers.map((tree.Initializer initializer) {
        return visitInitializer(initializer, context);
      }).toList();

      context.firstStatement = definition.body;
      visitStatement(definition.body, context);
      context.removeTrailingReturn(_recognizeTrailingReturn);

      // Some of the variable declarations have already been added
      // if their first assignment could be pulled into the initializer.
      // Add the remaining variable declarations now.
      context.declareRemainingVariables();

      // Add constant declarations.
      List<VariableDeclaration> constants = <VariableDeclaration>[];
      for (ConstDeclaration constDecl in definition.localConstants) {
        if (!context.constantNames.containsKey(constDecl.element)) {
          continue; // Discard unused constants declarations.
        }
        String name = context.getConstantName(constDecl.element);
        Expression value =
            ConstantEmitter.createExpression(constDecl.expression, context);
        VariableDeclaration decl = new VariableDeclaration(name, value);
        decl.element = constDecl.element;
        constants.add(decl);
      }

      List<Statement> bodyParts = [];
      if (constants.length > 0) {
        bodyParts.add(new VariableDeclarations(constants, isConst: true));
      }
      if (context.variables.length > 0) {
        bodyParts.add(new VariableDeclarations(context.variables));
      }
      bodyParts.addAll(context.statements);
      body = new Block(bodyParts);
    }
    return new ConstructorDefinition(
        parameters,
        body,
        initializers,
        context.currentElement.name,
        definition.element.isConst)..element = context.currentElement;
  }

  @override
  FunctionExpression visitFunctionDefinition(
        tree.FunctionDefinition definition,
        BuilderContext<Statement> context) {
    context.currentElement = definition.element;

    Parameters parameters = emitRootParameters(
        definition, definition.defaultParameterValues, context);

    // Declare parameters.
    for (tree.Variable param in definition.parameters) {
      context.variableNames[param] = param.element.name;
      context.usedVariableNames.add(param.element.name);
      context.declaredVariables.add(param);
    }

    Statement body;
    if (definition.isEmpty) {
      body = new EmptyStatement();
    } else {
      context.firstStatement = definition.body;
      visitStatement(definition.body, context);
      context.removeTrailingReturn(_recognizeTrailingReturn);

      // Some of the variable declarations have already been added
      // if their first assignment could be pulled into the initializer.
      // Add the remaining variable declarations now.
      context.declareRemainingVariables();

      // Add constant declarations.
      List<VariableDeclaration> constants = <VariableDeclaration>[];
      for (ConstDeclaration constDecl in definition.localConstants) {
        if (!context.constantNames.containsKey(constDecl.element)) {
          continue; // Discard unused constants declarations.
        }
        String name = context.getConstantName(constDecl.element);
        Expression value =
            ConstantEmitter.createExpression(constDecl.expression, context);
        VariableDeclaration decl = new VariableDeclaration(name, value);
        decl.element = constDecl.element;
        constants.add(decl);
      }

      List<Statement> bodyParts = [];
      if (constants.length > 0) {
        bodyParts.add(new VariableDeclarations(constants, isConst: true));
      }
      if (context.variables.length > 0) {
        bodyParts.add(new VariableDeclarations(context.variables));
      }
      bodyParts.addAll(context.statements);

      body = new Block(bodyParts);
    }
    FunctionType functionType = context.currentElement.type;

    return new FunctionExpression(
        parameters,
        body,
        name: context.currentElement.name,
        returnType: TypeGenerator.createOptionalType(functionType.returnType),
        isGetter: context.currentElement.isGetter,
        isSetter: context.currentElement.isSetter)
        ..element = context.currentElement;
  }

  /// Emits parameters that are not nested inside other parameters.
  /// Root parameters can have default values, while inner parameters cannot.
  Parameters emitRootParameters(tree.RootNode function,
                                List<ConstantExpression> defaults,
                                BuilderContext<Statement> context) {
    FunctionType functionType = function.element.type;
    List<Parameter> required = TypeGenerator.createParameters(
        functionType.parameterTypes,
        context: context,
        elements: function.parameters.map((p) => p.element));
    bool optionalParametersAreNamed = !functionType.namedParameters.isEmpty;
    List<Parameter> optional = TypeGenerator.createParameters(
        optionalParametersAreNamed
            ? functionType.namedParameterTypes
            : functionType.optionalParameterTypes,
        context: context,
        defaultValues: defaults,
        elements: function.parameters.skip(required.length)
            .map((p) => p.element));
    return new Parameters(required, optional, optionalParametersAreNamed);
  }

  /// True if the two expressions are a reference to the same variable.
  bool isSameVariable(Receiver e1, Receiver e2) {
    return e1 is Identifier &&
           e2 is Identifier &&
           e1.element is VariableElement &&
           e1.element == e2.element;
  }

  Expression makeAssignment(Expression target, Expression value) {
    // Try to print as compound assignment or increment
    if (value is BinaryOperator && isCompoundableOperator(value.operator)) {
      Receiver leftOperand = value.left;
      Expression rightOperand = value.right;
      bool valid = false;
      if (isSameVariable(target, leftOperand)) {
        valid = true;
      } else if (target is FieldExpression &&
                 leftOperand is FieldExpression &&
                 isSameVariable(target.object, leftOperand.object) &&
                 target.fieldName == leftOperand.fieldName) {
        valid = true;
      } else if (target is IndexExpression &&
                 leftOperand is IndexExpression &&
                 isSameVariable(target.object, leftOperand.object) &&
                 isSameVariable(target.index, leftOperand.index)) {
        valid = true;
      }
      if (valid) {
        if (rightOperand is Literal && rightOperand.value.isOne &&
            (value.operator == '+' || value.operator == '-')) {
          return new Increment.prefix(target, value.operator + value.operator);
        } else {
          return new Assignment(target, value.operator + '=', rightOperand);
        }
      }
    }
    // Fall back to regular assignment
    return new Assignment(target, '=', value);
  }

  Block visitInSubContext(tree.Statement statement,
                          BuilderContext<Statement> context,
                          {tree.Statement fallthrough}) {
    return new Block(context.inSubcontext(
        (BuilderContext<Statement> subcontext) {
      visitStatement(statement, subcontext);
    }, fallthrough: fallthrough));
  }

  void addLabeledStatement(tree.Label label,
                           Statement statement,
                           BuilderContext<Statement> context) {
    if (context.removeUsedLabel(label)) {
      context.addStatement(new LabeledStatement(label.name, statement));
    } else {
      context.addStatement(statement);
    }
  }

  @override
  void visitExpressionStatement(tree.ExpressionStatement stmt,
                                BuilderContext<Statement> context) {
    if (stmt.expression is tree.Assign) {
      emitAssignStatement(stmt.expression, stmt, context);
      return;
    }
    Expression e = visitExpression(stmt.expression, context);
    context.addStatement(new ExpressionStatement(e));
    visitStatement(stmt.next, context);
  }

  @override
  void visitVariableDeclaration(tree.VariableDeclaration node,
                                BuilderContext<Statement> context) {
    Expression value = visitExpression(node.value, context);
    String name = context.getVariableName(node.variable);
    VariableDeclaration decl = new VariableDeclaration(name, value)
                                   ..element = node.variable.element;
    context.declaredVariables.add(node.variable);
    context.addStatement(new VariableDeclarations([decl]));
    visitStatement(node.next, context);
  }

  @override
  void visitLabeledStatement(tree.LabeledStatement stmt,
                             BuilderContext<Statement> context) {
    Block block = visitInSubContext(stmt.body, context, fallthrough: stmt.next);
    addLabeledStatement(stmt.label, block, context);

    visitStatement(stmt.next, context);
  }

  bool isNullLiteral(Expression exp) => exp is Literal && exp.value.isNull;

  void emitAssignStatement(tree.Assign assign,
                           tree.Statement statement,
                           BuilderContext<Statement> context) {
    // Try to emit a local function declaration. This is useful for functions
    // that may occur in expression context, but could not be inlined anywhere.
    if (assign.variable.element is FunctionElement &&
        assign.value is tree.FunctionExpression &&
        !context.declaredVariables.contains(assign.variable) &&
        assign.variable.writeCount == 1) {
      tree.FunctionExpression functionExp = assign.value;
      FunctionExpression function =
          makeSubFunction(functionExp.definition, context);
      FunctionDeclaration decl = new FunctionDeclaration(function);
      context.addStatement(decl);
      context.declaredVariables.add(assign.variable);

      visitStatement(statement.next, context);
      return;
    }

    Expression definition = visitExpression(assign.value, context);
    bool isFirstOccurrence = (context.variableNames[assign.variable] == null);
    bool isDeclaredHere = assign.variable.host == context.currentElement;
    bool isFirstStatement = context.firstStatement == statement;

    // Try to pull into initializer.
    if (isFirstStatement && isFirstOccurrence && isDeclaredHere) {
      if (isNullLiteral(definition)) definition = null;
      context.addDeclaration(assign.variable, definition);
      context.firstStatement = statement.next;
      visitStatement(statement.next, context);
      return;
    }

    context.addStatement(new ExpressionStatement(makeAssignment(
        context.makeVariableAccess(assign.variable),
        definition)));
    visitStatement(statement.next, context);
  }

  @override
  void visitReturn(tree.Return stmt, BuilderContext<Statement> context) {
    if (context.currentElement.isGenerativeConstructor &&
        !context.inInitializer) {
      assert(() {
        tree.Expression value = stmt.value;
        return value is tree.Constant && value.value.isNull;
      });
      context.addStatement(new Return(null));
    } else {
      Expression inner = visitExpression(stmt.value, context);
      context.addStatement(new Return(inner));
    }
  }

  @override
  void visitThrow(tree.Throw stmt, BuilderContext<Statement> context) {
    Expression value = visitExpression(stmt.value, context);
    context.addStatement(new ExpressionStatement(new Throw(value)));
  }

  @override
  void visitRethrow(tree.Rethrow stmt, BuilderContext<Statement> context) {
    context.addStatement(new Rethrow());
  }

  @override
  void visitBreak(tree.Break stmt, BuilderContext<Statement> context) {
    tree.Statement fall = context.fallthrough;
    if (stmt.target.binding.next == fall) {
      // Fall through to break target
    } else if (fall is tree.Break && fall.target == stmt.target) {
      // Fall through to equivalent break
    } else {
      context.useLabel(stmt.target);
      context.addStatement(new Break(stmt.target.name));
    }
  }

  @override
  void visitContinue(tree.Continue stmt,
                     BuilderContext<Statement> context) {
    tree.Statement fall = context.fallthrough;
    if (stmt.target.binding == fall) {
      // Fall through to continue target
    } else if (fall is tree.Continue && fall.target == stmt.target) {
      // Fall through to equivalent continue
    } else {
      context.useLabel(stmt.target);
      context.addStatement(new Continue(stmt.target.name));
    }
  }

  @override
  void visitIf(tree.If stmt,
               BuilderContext<Statement> context) {
    Expression condition = visitExpression(stmt.condition, context);
    Block thenBlock = visitInSubContext(stmt.thenStatement, context);
    Block elseBlock= visitInSubContext(stmt.elseStatement, context);
    context.addStatement(new If(condition, thenBlock, elseBlock));
  }

  @override
  void visitWhileTrue(tree.WhileTrue stmt,
                      BuilderContext<Statement> context) {
    Block body = visitInSubContext(stmt.body, context, fallthrough: stmt);
    Statement statement =
        new While(new Literal(new TrueConstantValue()), body);
    addLabeledStatement(stmt.label, statement, context);
  }

  @override
  void visitWhileCondition(tree.WhileCondition stmt,
                           BuilderContext<Statement> context) {
    Expression condition = visitExpression(stmt.condition, context);
    Block body = visitInSubContext(stmt.body, context, fallthrough: stmt);
    Statement statement = new While(condition, body);
    addLabeledStatement(stmt.label, statement, context);

    visitStatement(stmt.next, context);
  }

  @override
  void visitTry(tree.Try stmt,
                BuilderContext<Statement> context) {
    Block tryBody = visitInSubContext(stmt.tryBody, context);
    Block catchBody = visitInSubContext(stmt.catchBody, context);
    CatchBlock catchBlock;
    tree.Variable exceptionVariable = stmt.catchParameters[0];
    context.handlerVariables.add(exceptionVariable);
    VariableDeclaration exceptionParameter =
        new VariableDeclaration(context.getVariableName(exceptionVariable));
    exceptionParameter.element = exceptionVariable.element;
    stmt.catchParameters.forEach(context.declaredVariables.add);
    if (stmt.catchParameters.length == 2) {
      tree.Variable stackTraceVariable = stmt.catchParameters[1];
      context.handlerVariables.add(stackTraceVariable);
      VariableDeclaration stackTraceParameter =
          new VariableDeclaration(context.getVariableName(stackTraceVariable));
      stackTraceParameter.element = stackTraceVariable.element;
      catchBlock = new CatchBlock(catchBody,
          exceptionVar: exceptionParameter,
          stackVar: stackTraceParameter);
    } else {
      assert(stmt.catchParameters.length == 1);
      catchBlock = new CatchBlock(catchBody,
          exceptionVar: exceptionParameter);
    }
    context.addStatement(new Try(tryBody, <CatchBlock>[catchBlock], null));
  }

  @override
  Expression visitConstant(tree.Constant exp,
                           BuilderContext<Statement> context) {
    return ConstantEmitter.createExpression(exp.expression, context);
  }

  @override
  Expression visitThis(tree.This exp,
                       BuilderContext<Statement> context) {
    return new This();
  }

  @override
  Expression visitReifyTypeVar(tree.ReifyTypeVar exp,
                               BuilderContext<Statement> context) {
    return new ReifyTypeVar(exp.typeVariable.name)
               ..element = exp.typeVariable;
  }

  List<Expression> visitExpressions(List<tree.Expression> expressions,
                                    BuilderContext<Statement> context) {
    return expressions.map((expression) => visitExpression(expression, context))
        .toList(growable: false);
  }

  @override
  Expression visitLiteralList(tree.LiteralList exp,
                              BuilderContext<Statement> context) {
    return new LiteralList(visitExpressions(exp.values, context),
        typeArgument:
            TypeGenerator.createOptionalType(exp.type.typeArguments.single));
  }

  @override
  Expression visitLiteralMap(tree.LiteralMap exp,
                             BuilderContext<Statement> context) {
    List<LiteralMapEntry> entries = new List<LiteralMapEntry>.generate(
        exp.entries.length,
        (i) => new LiteralMapEntry(
            visitExpression(exp.entries[i].key, context),
            visitExpression(exp.entries[i].value, context)));
    List<TypeAnnotation> typeArguments = exp.type.treatAsRaw
        ? null
        : exp.type.typeArguments.map(TypeGenerator.createType)
             .toList(growable: false);
    return new LiteralMap(entries, typeArguments: typeArguments);
  }

  @override
  Expression visitTypeOperator(tree.TypeOperator exp,
                               BuilderContext<Statement> context) {
    return new TypeOperator(visitExpression(exp.receiver, context),
                            exp.operator,
                            TypeGenerator.createType(exp.type));
  }

  List<Argument> emitArguments(List<Expression> arguments,
                               Selector selector) {
    int positionalArgumentCount = selector.positionalArgumentCount;
    List<Argument> result = new List<Argument>.generate(positionalArgumentCount,
        (i) => arguments[i]);
    for (int i = 0; i < selector.namedArgumentCount; ++i) {
      result.add(new NamedArgument(selector.namedArguments[i],
          arguments[positionalArgumentCount + i]));
    }
    return result;
  }

  List<Expression> visitArgumentList(List<tree.Expression> arguments,
                                     BuilderContext context) {
    return arguments
        .map((tree.Expression argument) => visitExpression(argument, context))
        .toList();
  }

  @override
  Expression visitInvokeStatic(tree.InvokeStatic exp,
                               BuilderContext<Statement> context) {
    switch (exp.selector.kind) {
      case SelectorKind.GETTER:
        return new Identifier(exp.target.name)..element = exp.target;

      case SelectorKind.SETTER:
        return new Assignment(
            new Identifier(exp.target.name)..element = exp.target,
            '=',
            visitExpression(exp.arguments[0], context));

      case SelectorKind.CALL:
        return new CallStatic(
            null, exp.target.name,
            emitArguments(visitArgumentList(exp.arguments, context),
                          exp.selector))
            ..element = exp.target;

      default:
        throw "Unexpected selector kind: ${exp.selector.kind}";
    }
  }

  Expression emitMethodCall(tree.Invoke exp, Receiver receiver,
                            BuilderContext<Statement> context) {
    List<Argument> args =
        emitArguments(visitArgumentList(exp.arguments, context), exp.selector);
    switch (exp.selector.kind) {
      case SelectorKind.CALL:
        if (exp.selector.name == "call") {
          return new CallFunction(receiver, args);
        }
        return new CallMethod(receiver, exp.selector.name, args);

      case SelectorKind.OPERATOR:
        if (args.length == 0) {
          String name = exp.selector.name;
          if (name == 'unary-') {
            name = '-';
          }
          return new UnaryOperator(name, receiver);
        }
        return new BinaryOperator(receiver, exp.selector.name, args[0]);

      case SelectorKind.GETTER:
        return new FieldExpression(receiver, exp.selector.name);

      case SelectorKind.SETTER:
        return makeAssignment(
            new FieldExpression(receiver, exp.selector.name),
            args[0]);

      case SelectorKind.INDEX:
        Expression e = new IndexExpression(receiver, args[0]);
        if (args.length == 2) {
          e = makeAssignment(e, args[1]);
        }
        return e;

      default:
        throw "Unexpected selector in InvokeMethod: ${exp.selector.kind}";
    }
  }

  @override
  Expression visitInvokeMethod(tree.InvokeMethod exp,
                               BuilderContext<Statement> context) {
    Expression receiver = visitExpression(exp.receiver, context);
    return emitMethodCall(exp, receiver, context);
  }

  @override
  Expression visitInvokeMethodDirectly(tree.InvokeMethodDirectly exp,
                                       BuilderContext<Statement> context) {
    // When targeting Dart, InvokeMethodDirectly is only used for super calls.
    // The receiver is known to be `this`, and the target method is a method
    // on the super class. So we just translate it as a method call with the
    // super receiver.
    return emitMethodCall(exp, new SuperReceiver(), context);
  }

  @override
  Expression visitInvokeConstructor(tree.InvokeConstructor exp,
                                    BuilderContext<Statement> context) {
    List<Argument> args =
        emitArguments(visitArgumentList(exp.arguments, context), exp.selector);
    FunctionElement constructor = exp.target;
    String name = constructor.name.isEmpty ? null : constructor.name;
    return new CallNew(TypeGenerator.createType(exp.type),
                       args,
                       constructorName: name,
                       isConst: exp.constant != null)
               ..constructor = constructor
               ..dartType = exp.type;
  }

  @override
  Expression visitConcatenateStrings(tree.ConcatenateStrings exp,
                                     BuilderContext<Statement> context) {
    return new StringConcat(visitExpressions(exp.arguments, context));
  }

  @override
  Expression visitConditional(tree.Conditional exp,
                              BuilderContext<Statement> context) {
    return new Conditional(
        visitExpression(exp.condition, context),
        visitExpression(exp.thenExpression, context),
        visitExpression(exp.elseExpression, context));
  }

  @override
  Expression visitLogicalOperator(tree.LogicalOperator exp,
                                  BuilderContext<Statement> context) {
    return new BinaryOperator(visitExpression(exp.left, context),
                              exp.operator,
                              visitExpression(exp.right, context));
  }

  @override
  Expression visitNot(tree.Not exp,
                      BuilderContext<Statement> context) {
    return new UnaryOperator('!', visitExpression(exp.operand, context));
  }

  @override
  Expression visitVariableUse(tree.VariableUse exp,
                              BuilderContext<Statement> context) {
    return context.makeVariableAccess(exp.variable);
  }

  @override
  Expression visitAssign(tree.Assign node, BuilderContext<Statement> context) {
    // This is called only when an assignment occurs in expression context.
    return makeAssignment(
        context.makeVariableAccess(node.variable),
        visitExpression(node.value, context));
  }

  FunctionExpression makeSubFunction(tree.FunctionDefinition function,
                                     BuilderContext<Statement> context) {
    return visitFunctionDefinition(function,
        new BuilderContext<Statement>.inner(context));
  }

  @override
  Expression visitFunctionExpression(tree.FunctionExpression exp,
                                     BuilderContext<Statement> context) {
    return makeSubFunction(exp.definition, context)..name = null;
  }

  @override
  void visitFunctionDeclaration(tree.FunctionDeclaration node,
                                BuilderContext<Statement> context) {
    assert(context.variableNames[node.variable] == null);
    String name = context.getVariableName(node.variable);
    FunctionExpression inner = makeSubFunction(node.definition, context);
    inner.name = name;
    FunctionDeclaration decl = new FunctionDeclaration(inner);
    context.declaredVariables.add(node.variable);
    context.addStatement(decl);
    visitStatement(node.next, context);
  }

  List<Statement> buildInInitializerContext(tree.Statement root,
                                            BuilderContext context) {
    BuilderContext inner = new BuilderContext<Statement>.initializer(context);
    inner.currentElement = context.currentElement;
    inner.firstStatement = root;
    visitStatement(root, inner);
    List<Statement> bodyParts;
    for (tree.Variable variable in inner.variableNames.keys) {
      if (!context.declaredVariables.contains(variable) &&
          !inner.declaredVariables.contains(variable)) {
        inner.addDeclaration(variable);
      }
    }
    if (inner.variables.length > 0) {
      bodyParts = new List<Statement>();
      bodyParts.add(new VariableDeclarations(inner.variables));
      bodyParts.addAll(inner.statements);
    } else {
      bodyParts = inner.statements;
    }
    return bodyParts;
  }

  @override
  Initializer visitFieldInitializer(tree.FieldInitializer node,
                                   BuilderContext<Statement> context) {
    return new FieldInitializer(node.element,
        ensureExpression(buildInInitializerContext(node.body, context)));
  }

  @override
  Initializer visitSuperInitializer(tree.SuperInitializer node,
                                   BuilderContext<Statement> context) {
    List<Argument> arguments = node.arguments.map((tree.Statement argument) {
      return ensureExpression(buildInInitializerContext(argument, context));
    }).toList();
    return new SuperInitializer(node.target,
                                emitArguments(arguments, node.selector));
  }

  @override
  Expression visitTypeExpression(tree.TypeExpression node, arg) {
    throw '$node not supported by dart backend';
  }

  @override
  visitGetField(tree.GetField node, arg) => errorUnsupportedNode(node);

  @override
  visitSetField(tree.SetField node, arg) => errorUnsupportedNode(node);

  @override
  visitCreateBox(tree.CreateBox node, arg) => errorUnsupportedNode(node);

  @override
  visitCreateInstance(tree.CreateInstance node, arg) {
    return errorUnsupportedNode(node);
  }

  @override
  Expression visitReadTypeVariable(tree.ReadTypeVariable node, arg) {
    return errorUnsupportedNode(node);
  }

  @override
  Expression visitReifyRuntimeType(tree.ReifyRuntimeType node, arg) {
    return errorUnsupportedNode(node);
  }

  errorUnsupportedNode(tree.JsSpecificNode node) {
    throw '$node not supported by dart backend';
  }

}

class TypeGenerator {

  /// TODO(johnniwinther): Remove this when issue 21283 has been resolved.
  static int pseudoNameCounter = 0;

  static Parameter emitParameter(DartType type,
                                 BuilderContext<Statement> context,
                                 {String name,
                                  Element element,
                                  ConstantExpression defaultValue}) {
    if (name == null && element != null) {
      name = element.name;
    }
    if (name == null) {
      name = '_${pseudoNameCounter++}';
    }
    Parameter parameter;
    if (type.isFunctionType) {
      FunctionType functionType = type;
      TypeAnnotation returnType = createOptionalType(functionType.returnType);
      Parameters innerParameters =
          createParametersFromType(functionType);
      parameter = new Parameter.function(name, returnType, innerParameters);
    } else {
      TypeAnnotation typeAnnotation = createOptionalType(type);
      parameter = new Parameter(name, type: typeAnnotation);
    }
    parameter.element = element;
    if (defaultValue != null && !defaultValue.value.isNull) {
      parameter.defaultValue =
          ConstantEmitter.createExpression(defaultValue, context);
    }
    return parameter;
  }

  static Parameters createParametersFromType(FunctionType functionType) {
    pseudoNameCounter = 0;
    if (functionType.namedParameters.isEmpty) {
      return new Parameters(
          createParameters(functionType.parameterTypes),
          createParameters(functionType.optionalParameterTypes),
          false);
    } else {
      return new Parameters(
          createParameters(functionType.parameterTypes),
          createParameters(functionType.namedParameterTypes,
                         names: functionType.namedParameters),
          true);
    }
  }

  static List<Parameter> createParameters(
      Iterable<DartType> parameterTypes,
      {BuilderContext<Statement> context,
       Iterable<String> names: const <String>[],
       Iterable<ConstantExpression> defaultValues: const <ConstantExpression>[],
       Iterable<Element> elements: const <Element>[]}) {
    Iterator<String> name = names.iterator;
    Iterator<ConstantExpression> defaultValue = defaultValues.iterator;
    Iterator<Element> element = elements.iterator;
    return parameterTypes.map((DartType type) {
      name.moveNext();
      defaultValue.moveNext();
      element.moveNext();
      return emitParameter(type, context,
                           name: name.current,
                           defaultValue: defaultValue.current,
                           element: element.current);
    }).toList();
  }

  /// Like [createTypeAnnotation] except the dynamic type is converted to null.
  static TypeAnnotation createOptionalType(DartType type) {
    if (type.treatAsDynamic) {
      return null;
    } else {
      return createType(type);
    }
  }

  /// Creates the [TypeAnnotation] for a [type] that is not function type.
  static TypeAnnotation createType(DartType type) {
    if (type is GenericType) {
      if (type.treatAsRaw) {
        return new TypeAnnotation(type.element.name)..dartType = type;
      }
      return new TypeAnnotation(
          type.element.name,
          type.typeArguments.map(createType).toList(growable:false))
          ..dartType = type;
    } else if (type is VoidType) {
      return new TypeAnnotation('void')
          ..dartType = type;
    } else if (type is TypeVariableType) {
      return new TypeAnnotation(type.name)
          ..dartType = type;
    } else if (type is DynamicType) {
      return new TypeAnnotation("dynamic")
          ..dartType = type;
    } else if (type is MalformedType) {
      return new TypeAnnotation(type.name)
          ..dartType = type;
    } else {
      throw "Unsupported type annotation: $type";
    }
  }

}


class ConstantEmitter
    extends ConstantExpressionVisitor<BuilderContext<Statement>, Expression> {
  const ConstantEmitter();

  /// Creates the [Expression] for the constant [exp].
  static Expression createExpression(ConstantExpression exp,
                                     BuilderContext<Statement> context) {
    return const ConstantEmitter().visit(exp, context);
  }

  Expression handlePrimitiveConstant(PrimitiveConstantValue value) {
    // Num constants may be negative, while literals must be non-negative:
    // Literals are non-negative in the specification, and a negated literal
    // parses as a call to unary `-`. The AST unparser assumes literals are
    // non-negative and relies on this to avoid incorrectly generating `--`,
    // the predecrement operator.
    // Translate such constants into their positive value wrapped by
    // the unary minus operator.
    if (value.isNum) {
      NumConstantValue numConstant = value;
      if (numConstant.primitiveValue.isNegative) {
        return negatedLiteral(numConstant);
      }
    }
    return new Literal(value);
  }

  List<Expression> visitExpressions(List<ConstantExpression> expressions,
                                    BuilderContext<Statement> context) {
    return expressions.map((expression) => visit(expression, context))
        .toList(growable: false);
  }

  @override
  Expression visitPrimitive(PrimitiveConstantExpression exp,
                            BuilderContext<Statement> context) {
    return handlePrimitiveConstant(exp.value);
  }

  /// Given a negative num constant, returns the corresponding positive
  /// literal wrapped by a unary minus operator.
  Expression negatedLiteral(NumConstantValue constant) {
    assert(constant.primitiveValue.isNegative);
    NumConstantValue positiveConstant;
    if (constant.isInt) {
      positiveConstant = new IntConstantValue(-constant.primitiveValue);
    } else if (constant.isDouble) {
      positiveConstant = new DoubleConstantValue(-constant.primitiveValue);
    } else {
      throw "Unexpected type of NumConstant: $constant";
    }
    return new UnaryOperator('-', new Literal(positiveConstant));
  }

  @override
  Expression visitList(ListConstantExpression exp,
                       BuilderContext<Statement> context) {
    return new LiteralList(
        visitExpressions(exp.values, context),
        isConst: true,
        typeArgument:
            TypeGenerator.createOptionalType(exp.type.typeArguments.single));
  }

  @override
  Expression visitMap(MapConstantExpression exp,
                      BuilderContext<Statement> context) {
    List<LiteralMapEntry> entries = new List<LiteralMapEntry>.generate(
        exp.values.length,
        (i) => new LiteralMapEntry(visit(exp.keys[i], context),
                                   visit(exp.values[i], context)));
    List<TypeAnnotation> typeArguments = exp.type.treatAsRaw
        ? null
        : exp.type.typeArguments.map(TypeGenerator.createType).toList();
    return new LiteralMap(entries, isConst: true, typeArguments: typeArguments);
  }

  @override
  Expression visitConstructed(ConstructedConstantExpression exp,
                              BuilderContext<Statement> context) {
    int positionalArgumentCount = exp.callStructure.positionalArgumentCount;
    List<Argument> args = new List<Argument>.generate(
        positionalArgumentCount,
        (i) => visit(exp.arguments[i], context));
    for (int i = 0; i < exp.callStructure.namedArgumentCount; ++i) {
      args.add(new NamedArgument(exp.callStructure.namedArguments[i],
          visit(exp.arguments[positionalArgumentCount + i], context)));
    }

    FunctionElement constructor = exp.target;
    String name = constructor.name.isEmpty ? null : constructor.name;
    return new CallNew(TypeGenerator.createType(exp.type),
                       args,
                       constructorName: name,
                       isConst: true)
               ..constructor = constructor
               ..dartType = exp.type;
  }

  @override
  Expression visitConcatenate(ConcatenateConstantExpression exp,
                              BuilderContext<Statement> context) {

    return new StringConcat(visitExpressions(exp.arguments, context));
  }

  @override
  Expression visitSymbol(SymbolConstantExpression exp,
                         BuilderContext<Statement> context) {
    return new LiteralSymbol(exp.name);
  }

  @override
  Expression visitType(TypeConstantExpression exp,
                       BuilderContext<Statement> context) {
    DartType type = exp.type;
    return new LiteralType(type.name)
               ..type = type;
  }

  @override
  Expression visitVariable(VariableConstantExpression exp,
                           BuilderContext<Statement> context) {
    Element element = exp.element;
    if (element.kind != ElementKind.VARIABLE) {
      return new Identifier(element.name)..element = element;
    }
    String name = context.getConstantName(element);
    return new Identifier(name)
               ..element = element;
  }

  @override
  Expression visitFunction(FunctionConstantExpression exp,
                           BuilderContext<Statement> context) {
    return new Identifier(exp.element.name)
               ..element = exp.element;
  }

  @override
  Expression visitBinary(BinaryConstantExpression exp,
                         BuilderContext<Statement> context) {
    return handlePrimitiveConstant(exp.value);
  }

  @override
  Expression visitIdentical(IdenticalConstantExpression exp,
                            BuilderContext<Statement> context) {
    return handlePrimitiveConstant(exp.value);
  }

  @override
  Expression visitConditional(ConditionalConstantExpression exp,
                              BuilderContext<Statement> context) {
    if (exp.condition.value.isTrue) {
      return exp.trueExp.accept(this);
    } else {
      return exp.falseExp.accept(this);
    }
  }

  @override
  Expression visitUnary(UnaryConstantExpression exp,
                        BuilderContext<Statement> context) {
    return handlePrimitiveConstant(exp.value);
  }

  @override
  Expression visitDeferred(DeferredConstantExpression exp,
                           BuilderContext<Statement> context) {
    return exp.expression.accept(this);
  }
}

/// Moves function parameters into a separate variable if one of its uses is
/// shadowed by an inner function parameter.
/// This artifact is necessary because function parameters cannot be renamed.
class UnshadowParameters extends tree.RecursiveVisitor {

  /// Maps parameter names to their bindings.
  Map<String, tree.Variable> environment = <String, tree.Variable>{};

  /// Parameters that are currently shadowed by another parameter.
  Set<tree.Variable> shadowedParameters = new Set<tree.Variable>();

  /// Parameters that are used in a context where it is shadowed.
  Set<tree.Variable> hasShadowedUse = new Set<tree.Variable>();

  void unshadow(tree.RootNode definition) {
    if (definition.isEmpty) return;
    unshadowFunction(definition);
  }

  void unshadowFunction(tree.RootNode definition) {
    var oldShadow = shadowedParameters;
    var oldEnvironment = environment;
    environment = new Map<String, tree.Variable>.from(environment);
    shadowedParameters = new Set<tree.Variable>.from(shadowedParameters);
    for (tree.Variable param in definition.parameters) {
      tree.Variable oldVariable = environment[param.element.name];
      if (oldVariable != null) {
        shadowedParameters.add(oldVariable);
      }
      environment[param.element.name] = param;
    }
    definition.forEachBody(visitStatement);
    environment = oldEnvironment;
    shadowedParameters = oldShadow;

    for (int i=0; i<definition.parameters.length; i++) {
      tree.Variable param = definition.parameters[i];
      if (hasShadowedUse.remove(param)) {
        tree.Variable newParam = new tree.Variable(definition.element,
            param.element);
        definition.parameters[i] = newParam;
        definition.replaceEachBody((tree.Statement body) {
          return tree.Assign.makeStatement(
              param,
              new tree.VariableUse(newParam),
              body);
        });
        newParam.writeCount = 1; // Being a parameter counts as a write.
        param.writeCount--; // Not a parameter anymore.
      }
    }
  }

  @override
  void visitInnerFunction(tree.FunctionDefinition definition) {
    unshadowFunction(definition);
  }

  @override
  visitVariable(tree.Variable variable) {
    if (shadowedParameters.contains(variable)) {
      hasShadowedUse.add(variable);
    }
  }

}

// TODO(johnniwinther): Remove this when the dart `backend_ast` does not need
// [Element] for entities.
class _SyntheticLocalVariableElement extends modelx.VariableElementX
    implements LocalVariableElement {

  _SyntheticLocalVariableElement(String name,
                                 ExecutableElement enclosingElement,
                                 modelx.VariableList variables)
      : super(name, ElementKind.VARIABLE, enclosingElement, variables, null);

  ExecutableElement get executableContext => enclosingElement;

  ExecutableElement get memberContext => executableContext.memberContext;

  bool get isLocal => true;

  LibraryElement get implementationLibrary => enclosingElement.library;
}
