// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

library rewrite_async;

import "dart:math" show max;
import 'dart:collection';

import 'package:_internal/compiler/js_lib/shared/async_await_error_codes.dart'
    as error_codes;

import "js.dart" as js;

import '../util/util.dart';
import '../dart2jslib.dart' show DiagnosticListener;

import "../helpers/helpers.dart";

/// Rewrites a [js.Fun] with async/sync*/async* functions and await and yield
/// (with dart-like semantics) to an equivalent function without these.
/// await-for is not handled and must be rewritten before. (Currently handled
/// in ssa/builder.dart).
///
/// When generating the input to this, special care must be taken that
/// parameters to sync* functions that are mutated in the body must be boxed.
/// (Currently handled in closure.dart).
///
/// Look at [visitFun], [visitDartYield] and [visitAwait] for more explanation.
abstract class AsyncRewriterBase extends js.NodeVisitor {

  // Local variables are hoisted to the top of the function, so they are
  // collected here.
  List<js.VariableDeclaration> localVariables =
      new List<js.VariableDeclaration>();

  Map<js.Node, int> continueLabels = new Map<js.Node, int>();
  Map<js.Node, int> breakLabels = new Map<js.Node, int>();

  /// The label of a finally part.
  Map<js.Block, int> finallyLabels = new Map<js.Block, int>();

  /// The label of the catch handler of a [js.Try] or a [js.Fun] or [js.Catch].
  ///
  /// These mark the points an error can be consumed.
  ///
  /// - The handler of a [js.Fun] is the outermost and will rethrow the error.
  /// - The handler of a [js.Try] will run the catch handler.
  /// - The handler of a [js.Catch] is a synthetic handler that ensures the
  ///   right finally blocks are run if an error is thrown inside a
  ///   catch-handler.
  Map<js.Node, int> handlerLabels = new Map<js.Node, int>();

  int exitLabel;
  int rethrowLabel;

  /// A stack of all (surrounding) jump targets.
  ///
  /// Jump targets are:
  ///
  /// * The function, signalling a return or uncaught throw.
  /// * Loops.
  /// * LabeledStatements (also used for 'continue' when attached to loops).
  /// * Try statements, for catch and finally handlers.
  /// * Catch handlers, when inside a catch-part of a try, the catch-handler is
  ///   used to associate with a synthetic handler that will ensure the right
  ///   finally blocks are visited.
  ///
  /// When jumping to a target it is necessary to visit all finallies that
  /// are on the way to target (i.e. more nested than the jump target).
  List<js.Node> jumpTargets = new List<js.Node>();

  List<int> continueStack = new List<int>();
  List<int> breakStack = new List<int>();
  List<int> returnStack = new List<int>();

  List<Pair<String, String>> variableRenamings =
      new List<Pair<String, String>>();

  PreTranslationAnalysis analysis;

  final Function safeVariableName;

  // All the <x>Name variables are names of Javascript variables used in the
  // transformed code.

  /// Contains the result of an awaited expression, or a conditional or
  /// lazy boolean operator.
  ///
  /// For example a conditional expression is roughly translated like:
  /// [[cond ? a : b]]
  ///
  /// Becomes:
  ///
  /// while true { // outer while loop
  ///   switch (goto) { // Simulates goto
  ///     ...
  ///       goto = [[cond]] ? thenLabel : elseLabel
  ///       break;
  ///     case thenLabel:
  ///       result = [[a]];
  ///       goto = joinLabel;
  ///     case elseLabel:
  ///       result = [[b]];
  ///     case joinLabel:
  ///       // Now the result of computing the condition is in result.
  ///     ....
  ///   }
  /// }
  ///
  /// It is a parameter to the [body] function, so that [awaitStatement] can
  /// call [body] with the result of an awaited Future.
  js.VariableUse get result => new js.VariableUse(resultName);
  String resultName;

  /// A parameter to the [bodyName] function. Indicating if we are in success
  /// or error case.
  String errorCodeName;

  /// The inner function that is scheduled to do each await/yield,
  /// and called to do a new iteration for sync*.
  js.VariableUse get body => new js.VariableUse(bodyName);
  String bodyName;

  /// Used to simulate a goto.
  ///
  /// To "goto" a label, the label is assigned to this variable, and break out
  /// of the switch to take another iteration in the while loop. See [addGoto]
  js.VariableUse get goto => new js.VariableUse(gotoName);
  String gotoName;

  /// Variable containing the label of the current error handler.
  js.VariableUse get handler => new js.VariableUse(handlerName);
  String handlerName;

  /// A stack of labels of finally blocks to visit, and the label to go to after
  /// the last.
  js.VariableUse get next => new js.VariableUse(nextName);
  String nextName;

  /// The current returned value (a finally block may overwrite it).
  js.VariableUse get returnValue => new js.VariableUse(returnValueName);
  String returnValueName;

  /// Stores the current error when we are in the process of handling an error.
  js.VariableUse get currentError => new js.VariableUse(currentErrorName);
  String currentErrorName;

  /// The label of the outer loop.
  ///
  /// Used if there are untransformed loops containing break or continues to
  /// targets outside the loop.
  String outerLabelName;

  /// If javascript `this` is used, it is accessed via this variable, in the
  /// [bodyName] function.
  js.VariableUse get self => new js.VariableUse(selfName);
  String selfName;

  final DiagnosticListener diagnosticListener;
  // For error reporting only.
  Spannable get spannable {
    return (_spannable == null) ? NO_LOCATION_SPANNABLE : _spannable;
  }

  Spannable _spannable;

  int _currentLabel = 0;

  // The highest temporary variable index currently in use.
  int currentTempVarIndex = 0;
  // The highest temporary variable index ever in use in this function.
  int tempVarHighWaterMark = 0;
  Map<int, js.Expression> tempVarNames = new Map<int, js.Expression>();

  bool get isAsync => false;
  bool get isSyncStar => false;
  bool get isAsyncStar => false;

  AsyncRewriterBase(this.diagnosticListener,
                    spannable,
                    this.safeVariableName)
      : _spannable = spannable;

  /// Initialize names used by the subClass.
  void initializeNames();

  /// Main entry point.
  /// Rewrites a sync*/async/async* function to an equivalent normal function.
  ///
  /// [spannable] can be passed to have a location for error messages.
  js.Fun rewrite(js.Fun node, [Spannable spannable]) {
    _spannable = spannable;

    analysis = new PreTranslationAnalysis(unsupported);
    analysis.analyze(node);

    // To avoid name collisions with existing names, the fresh names are
    // generated after the analysis.
    resultName = freshName("result");
    errorCodeName = freshName("errorCode");
    bodyName = freshName("body");
    gotoName = freshName("goto");
    handlerName = freshName("handler");
    nextName = freshName("next");
    returnValueName = freshName("returnValue");
    currentErrorName = freshName("currentError");
    outerLabelName = freshName("outer");
    selfName = freshName("self");
    // Initialize names specific to the subclass.
    initializeNames();

    return node.accept(this);
  }

  js.Expression get currentErrorHandler {
    return js.number(handlerLabels[jumpTargets.lastWhere(
        (node) => handlerLabels[node] != null)]);
  }

  int allocateTempVar() {
    assert(tempVarHighWaterMark >= currentTempVarIndex);
    currentTempVarIndex++;
    tempVarHighWaterMark = max(currentTempVarIndex, tempVarHighWaterMark);
    return currentTempVarIndex;
  }

  js.VariableUse useTempVar(int i) {
    return tempVarNames.putIfAbsent(
        i, () => new js.VariableUse(freshName("temp$i")));
  }

  /// Generates a variable name with [safeVariableName] based on [originalName]
  /// with a suffix to guarantee it does not collide with already used names.
  String freshName(String originalName) {
    String safeName = safeVariableName(originalName);
    String result = safeName;
    int counter = 1;
    while (analysis.usedNames.contains(result)) {
      result = "$safeName$counter";
      ++counter;
    }
    analysis.usedNames.add(result);
    return result;
  }

  /// All the pieces are collected in this map, to create a switch with a case
  /// for each label.
  ///
  /// The order is important, therefore the type is explicitly LinkedHashMap.
  LinkedHashMap<int, List<js.Statement>> labelledParts =
      new LinkedHashMap<int, List<js.Statement>>();

  /// Description of each label for readability of the non-minified output.
  Map<int, String> labelComments = new Map<int, String>();

  /// True if the function has any try blocks containing await.
  bool hasTryBlocks = false;

  /// True if the traversion currently is inside a loop or switch for which
  /// [shouldTransform] is false.
  bool insideUntranslatedBreakable = false;

  /// True if a label is used to break to an outer switch-statement.
  bool hasJumpThoughOuterLabel = false;

  /// True if there is a catch-handler protected by a finally with no enclosing
  /// catch-handlers.
  bool needsRethrow = false;

  /// Buffer for collecting translated statements belonging to the same switch
  /// case.
  List<js.Statement> currentStatementBuffer;

  // Labels will become cases in the big switch expression, and `goto label`
  // is expressed by assigning to the switch key [gotoName] and breaking out of
  // the switch.

  int newLabel([String comment]) {
    int result = _currentLabel;
    _currentLabel++;
    if (comment != null) {
      labelComments[result] = comment;
    }
    return result;
  }

  /// Begins outputting statements to a new buffer with label [label].
  ///
  /// Each buffer ends up as its own case part in the big state-switch.
  void beginLabel(int label) {
    assert(!labelledParts.containsKey(label));
    currentStatementBuffer = new List<js.Statement>();
    labelledParts[label] = currentStatementBuffer;
    addStatement(new js.Comment(labelComments[label]));
  }

  /// Returns a statement assigning to the variable named [gotoName].
  /// This should be followed by a break for the goto to be executed. Use
  /// [gotoWithBreak] or [addGoto] for this.
  js.Statement setGotoVariable(int label) {
    return js.js.statement('# = #;', [goto, js.number(label)]);
  }

  /// Returns a block that has a goto to [label] including the break.
  ///
  /// Also inserts a comment describing the label if available.
  js.Block gotoAndBreak(int label) {
    List<js.Statement> statements = new List<js.Statement>();
    if (labelComments.containsKey(label)) {
      statements.add(new js.Comment("goto ${labelComments[label]}"));
    }
    statements.add(setGotoVariable(label));
    if (insideUntranslatedBreakable) {
      hasJumpThoughOuterLabel = true;
      statements.add(new js.Break(outerLabelName));
    } else {
      statements.add(new js.Break(null));
    }
    return new js.Block(statements);
  }

  /// Adds a goto to [label] including the break.
  ///
  /// Also inserts a comment describing the label if available.
  void addGoto(int label) {
    if (labelComments.containsKey(label)) {
      addStatement(new js.Comment("goto ${labelComments[label]}"));
    }
    addStatement(setGotoVariable(label));

    addBreak();
  }

  void addStatement(js.Statement node) {
    currentStatementBuffer.add(node);
  }

  void addExpressionStatement(js.Expression node) {
    addStatement(new js.ExpressionStatement(node));
  }

  /// True if there is an await or yield in [node] or some subexpression.
  bool shouldTransform(js.Node node) {
    return analysis.hasAwaitOrYield.contains(node);
  }

  void unsupported(js.Node node) {
    throw new UnsupportedError(
        "Node $node cannot be transformed by the await-sync transformer");
  }

  void unreachable(js.Node node) {
    diagnosticListener.internalError(
        spannable, "Internal error, trying to visit $node");
  }

  visitStatement(js.Statement node) {
    node.accept(this);
  }

  /// Visits [node] to ensure its sideeffects are performed, but throwing away
  /// the result.
  ///
  /// If the return value of visiting [node] is an expression guaranteed to have
  /// no side effect, it is dropped.
  void visitExpressionIgnoreResult(js.Expression node) {
    js.Expression result = node.accept(this);
    if (!(result is js.Literal || result is js.VariableUse)) {
      addExpressionStatement(result);
    }
  }

  js.Expression visitExpression(js.Expression node) {
    return node.accept(this);
  }


  /// Calls [fn] with the value of evaluating [node1] and [node2].
  ///
  /// Both nodes are evaluated in order.
  ///
  /// If node2 must be transformed (see [shouldTransform]), then the evaluation
  /// of node1 is added to the current statement-list and the result is stored
  /// in a temporary variable. The evaluation of node2 is then free to emit
  /// statements without affecting the result of node1.
  ///
  /// This is necessary, because await or yield expressions have to emit
  /// statements, and these statements could affect the value of node1.
  ///
  /// For example:
  ///
  /// - _storeIfNecessary(someLiteral) returns someLiteral.
  /// - _storeIfNecessary(someVariable)
  ///   inserts: var tempX = someVariable
  ///   returns: tempX
  ///   where tempX is a fresh temporary variable.
  js.Expression _storeIfNecessary(js.Expression result) {
    // Note that RegExes, js.ArrayInitializer and js.ObjectInitializer are not
    // [js.Literal]s.
    if (result is js.Literal) return result;

    js.Expression tempVar = useTempVar(allocateTempVar());
    addStatement(js.js.statement('# = #;', [tempVar, result]));
    return tempVar;
  }

  // TODO(sigurdm): This is obsolete - all calls use store: false. Replace with
  // visitExpression(node);
  withExpression(js.Expression node, fn(js.Expression result), {bool store}) {
    int oldTempVarIndex = currentTempVarIndex;
    js.Expression visited = visitExpression(node);
    if (store) {
      visited = _storeIfNecessary(visited);
    }
    var result = fn(visited);
    currentTempVarIndex = oldTempVarIndex;
    return result;
  }

  /// Calls [fn] with the result of evaluating [node]. Taking special care of
  /// property accesses.
  ///
  /// If [store] is true the result of evaluating [node] is stored in a
  /// temporary.
  ///
  /// We cannot rewrite `<receiver>.m()` to:
  ///     temp = <receiver>.m;
  ///     temp();
  /// Because this leaves `this` unbound in the call. But because of dart
  /// evaluation order we can write:
  ///     temp = <receiver>;
  ///     temp.m();
  withCallTargetExpression(js.Expression node,
                           fn(js.Expression result), {bool store}) {
    int oldTempVarIndex = currentTempVarIndex;
    js.Expression visited = visitExpression(node);
    js.Expression selector;
    js.Expression storedIfNeeded;
    if (store) {
      if (visited is js.PropertyAccess) {
        js.PropertyAccess propertyAccess = visited;
        selector = propertyAccess.selector;
        visited = propertyAccess.receiver;
      }
      storedIfNeeded = _storeIfNecessary(visited);
    } else {
      storedIfNeeded = visited;
    }
    js.Expression result;
    if (selector == null) {
      result = fn(storedIfNeeded);
    } else {
      result = fn(new js.PropertyAccess(storedIfNeeded, selector));
    }
    currentTempVarIndex = oldTempVarIndex;
    return result;
  }


  /// Calls [fn] with the value of evaluating [node1] and [node2].
  ///
  /// If `shouldTransform(node2)` the first expression is stored in a temporary
  /// variable.
  ///
  /// This is because node1 must be evaluated before visiting node2,
  /// because the evaluation of an await or yield cannot be expressed as
  /// an expression, visiting node2 it will output statements that
  /// might have an influence on the value of node1.
  withExpression2(js.Expression node1, js.Expression node2,
      fn(js.Expression result1, js.Expression result2)) {
    int oldTempVarIndex = currentTempVarIndex;
    js.Expression r1 = visitExpression(node1);
    if (shouldTransform(node2)) {
      r1 = _storeIfNecessary(r1);
    }
    js.Expression r2 = visitExpression(node2);
    var result = fn(r1, r2);
    currentTempVarIndex = oldTempVarIndex;
    return result;
  }

  /// Calls [fn] with the value of evaluating all [nodes].
  ///
  /// All results before the last node where `shouldTransform(node)` are stored
  /// in temporary variables.
  ///
  /// See more explanation on [withExpression2].
  ///
  /// If any of the nodes are null, they are ignored, and a null is passed to
  /// [fn] in that place.
  withExpressions(List<js.Expression> nodes, fn(List<js.Expression> results)) {
    int oldTempVarIndex = currentTempVarIndex;
    // Find last occurence of a 'transform' expression in [nodes].
    // All expressions before that must be stored in temp-vars.
    int lastTransformIndex = 0;
    for (int i = nodes.length - 1; i >= 0; --i) {
      if (nodes[i] == null) continue;
      if (shouldTransform(nodes[i])) {
        lastTransformIndex = i;
        break;
      }
    }
    List<js.Node> visited = nodes.take(lastTransformIndex).map((js.Node node) {
      return (node == null) ? null : _storeIfNecessary(visitExpression(node));
    }).toList();
    visited.addAll(nodes.skip(lastTransformIndex).map((js.Node node) {
      return (node == null) ? null : visitExpression(node);
    }));
    var result = fn(visited);
    currentTempVarIndex = oldTempVarIndex;
    return result;
  }

  /// Emits the return block that all returns jump to (after going
  /// through all the enclosing finally blocks). The jump to here is made in
  /// [visitReturn].
  void addSuccesExit();

  /// Emits the block that control flows to if an error has been thrown
  /// but not caught. (after going through all the enclosing finally blocks).
  void addErrorExit();

  void addFunctionExits() {
    addSuccesExit();
    addErrorExit();
  }

  /// Returns the rewritten function.
  js.Fun finishFunction(List<js.Parameter> parameters,
                          js.Statement rewrittenBody,
                          js.VariableDeclarationList variableDeclarations);

  Iterable<js.VariableInitialization> variableInitializations();

  /// Rewrites an async/sync*/async* function to a normal Javascript function.
  ///
  /// The control flow is flattened by simulating 'goto' using a switch in a
  /// loop and a state variable [goto] inside a nested function [body]
  /// that can be called back by [asyncStarHelper]/[asyncStarHelper]/the
  /// [Iterator].
  ///
  /// Local variables are hoisted outside the helper.
  ///
  /// Awaits in async/async* are translated to code that remembers the current
  /// location (so the function can resume from where it was) followed by a
  /// [awaitStatement]. The helper sets up the waiting for the awaited
  /// value and returns a future which is immediately returned by the
  /// [awaitStatement].
  ///
  /// Yields in sync*/async* are translated to a calls to helper functions.
  /// (see [visitYield])
  ///
  /// Simplified examples (not the exact translation, but intended to show the
  /// ideas):
  ///
  /// function (x, y, z) async {
  ///   var p = await foo();
  ///   return bar(p);
  /// }
  ///
  /// Becomes (without error handling):
  ///
  /// function(x, y, z) {
  ///   var goto = 0, returnValue, completer = new Completer(), p;
  ///   function body(result) {
  ///     while (true) {
  ///       switch (goto) {
  ///         case 0:
  ///           goto = 1 // Remember where to continue when the future succeeds.
  ///           return thenHelper(foo(), helper, completer);
  ///         case 1:
  ///           p = result;
  ///           returnValue = bar(p);
  ///           goto = 2;
  ///           break;
  ///         case 2:
  ///           return thenHelper(returnValue, null, completer)
  ///       }
  ///     }
  ///     return thenHelper(null, helper, completer);
  ///   }
  /// }
  ///
  /// Try/catch is implemented by maintaining [handler] to contain the label
  /// of the current handler. If [body] throws, the caller should catch the
  /// error and recall [body] with first argument [error_codes.ERROR] and
  /// second argument the error.
  ///
  /// A `finally` clause is compiled similar to normal code, with the additional
  /// complexity that `finally` clauses need to know where to jump to after the
  /// clause is done. In the translation, each flow-path that enters a `finally`
  /// sets up the variable [next] with a stack of finally-blocks and a final
  /// jump-target (exit, catch, ...).
  ///
  /// function(x, y, z) async {
  ///   try {
  ///     try {
  ///       throw "error";
  ///     } finally {
  ///       finalize1();
  ///     }
  ///   } catch (e) {
  ///     handle(e);
  ///   } finally {
  ///     finalize2();
  ///   }
  /// }
  ///
  /// Translates into (besides the fact that structures not containing
  /// await/yield/yield* are left intact):
  ///
  /// function(x, y, z) {
  ///   var goto = 0;
  ///   var returnValue;
  ///   var completer = new Completer();
  ///   var handler = 8; // Outside try-blocks go to the rethrow label.
  ///   var p;
  ///   var currentError;
  ///   // The result can be either the result of an awaited future, or an
  ///   // error if the future completed with an error.
  ///   function body(errorCode, result) {
  ///     if (errorCode == 1) {
  ///       currentError = result;
  ///       goto = handler;
  ///     }
  ///     while (true) {
  ///       switch (goto) {
  ///         case 0:
  ///           handler = 4; // The outer catch-handler
  ///           handler = 1; // The inner (implicit) catch-handler
  ///           throw "error";
  ///           next = [3];
  ///           // After the finally (2) continue normally after the try.
  ///           goto = 2;
  ///           break;
  ///         case 1: // (implicit) catch handler for inner try.
  ///           next = [3]; // destination after the finally.
  ///           // fall-though to the finally handler.
  ///         case 2: // finally for inner try
  ///           handler = 4; // catch-handler for outer try.
  ///           finalize1();
  ///           goto = next.pop();
  ///           break;
  ///         case 3: // exiting inner try.
  ///           next = [6];
  ///           goto = 5; // finally handler for outer try.
  ///           break;
  ///         case 4: // catch handler for outer try.
  ///           handler = 5; // If the handler throws, do the finally ..
  ///           next = [8] // ... and rethrow.
  ///           e = storedError;
  ///           handle(e);
  ///           // Fall through to finally.
  ///         case 5: // finally handler for outer try.
  ///           handler = null;
  ///           finalize2();
  ///           goto = next.pop();
  ///           break;
  ///         case 6: // Exiting outer try.
  ///         case 7: // return
  ///           return thenHelper(returnValue, 0, completer);
  ///         case 8: // Rethrow
  ///           return thenHelper(currentError, 1, completer);
  ///       }
  ///     }
  ///     return thenHelper(null, helper, completer);
  ///   }
  /// }
  ///
  @override
  js.Expression visitFun(js.Fun node) {
    beginLabel(newLabel("Function start"));
    // AsyncStar needs a returnlabel for its handling of cancelation. See
    // [visitDartYield].
    exitLabel = (analysis.hasExplicitReturns || isAsyncStar)
        ? newLabel("return")
        : null;
    rethrowLabel = newLabel("rethrow");
    handlerLabels[node] = rethrowLabel;
    js.Statement body = node.body;
    jumpTargets.add(node);
    visitStatement(body);
    jumpTargets.removeLast();
    addFunctionExits();

    List<js.SwitchClause> clauses = labelledParts.keys.map((label) {
      return new js.Case(js.number(label), new js.Block(labelledParts[label]));
    }).toList();
    js.Statement rewrittenBody =
        new js.Switch(goto, clauses);
    if (hasJumpThoughOuterLabel) {
      rewrittenBody = new js.LabeledStatement(outerLabelName, rewrittenBody);
    }
    rewrittenBody = js.js.statement('while (true) {#}', rewrittenBody);
    List<js.VariableInitialization> variables =
        new List<js.VariableInitialization>();

    variables.add(_makeVariableInitializer(goto, js.number(0)));
    variables.addAll(variableInitializations());
    variables.add(
        _makeVariableInitializer(handler, js.number(rethrowLabel)));
    variables.add(_makeVariableInitializer(currentError, null));
    if (analysis.hasFinally || (isAsyncStar && analysis.hasYield)) {
      variables.add(_makeVariableInitializer(next,
          new js.ArrayInitializer(<js.Expression>[])));
    }
    if (analysis.hasThis && !isSyncStar) {
      // Sync* functions must remember `this` on the level of the outer
      // function.
      variables.add(_makeVariableInitializer(self, js.js('this')));
    }
    variables.addAll(localVariables.map(
        (js.VariableDeclaration declaration) {
      return new js.VariableInitialization(declaration, null);
    }));
    variables.addAll(new Iterable.generate(tempVarHighWaterMark,
        (int i) => _makeVariableInitializer(useTempVar(i + 1).name, null)));
    js.VariableDeclarationList variableDeclarations =
        new js.VariableDeclarationList(variables);

    return finishFunction(node.params, rewrittenBody, variableDeclarations);
  }

  @override
  js.Expression visitAccess(js.PropertyAccess node) {
    return withExpression2(node.receiver, node.selector,
        (receiver, selector) => js.js('#[#]', [receiver, selector]));
  }

  @override
  js.Expression visitArrayHole(js.ArrayHole node) {
    return node;
  }

  @override
  js.Expression visitArrayInitializer(js.ArrayInitializer node) {
    return withExpressions(node.elements, (elements) {
      return new js.ArrayInitializer(elements);
    });
  }

  @override
  js.Expression visitAssignment(js.Assignment node) {
    if (!shouldTransform(node)) {
      return new js.Assignment.compound(visitExpression(node.leftHandSide),
          node.op, visitExpression(node.value));
    }
    js.Expression leftHandSide = node.leftHandSide;
    if (leftHandSide is js.VariableUse) {
      return withExpression(node.value, (js.Expression value) {
        return new js.Assignment(leftHandSide, value);
      }, store: false);
    } else if (leftHandSide is js.PropertyAccess) {
      return withExpressions([
        leftHandSide.receiver,
        leftHandSide.selector,
        node.value
      ], (evaluated) {
        return new js.Assignment.compound(
            new js.PropertyAccess(evaluated[0], evaluated[1]), node.op,
            evaluated[2]);
      });
    } else {
      throw "Unexpected assignment left hand side $leftHandSide";
    }
  }

  js.Statement awaitStatement(js.Expression value);

  /// An await is translated to an [awaitStatement].
  ///
  /// See the comments of [visitFun] for an example.
  @override
  js.Expression visitAwait(js.Await node) {
    assert(isAsync || isAsyncStar);
    int afterAwait = newLabel("returning from await.");
    withExpression(node.expression, (js.Expression value) {
      addStatement(setGotoVariable(afterAwait));
      addStatement(awaitStatement(value));
    }, store: false);
    beginLabel(afterAwait);
    return result;
  }

  /// Checks if [node] is the variable named [resultName].
  ///
  /// [result] is used to hold the result of a transformed computation
  /// for example the result of awaiting, or the result of a conditional or
  /// short-circuiting expression.
  /// If the subexpression of some transformed node already is transformed and
  /// visiting it returns [result], it is not redundantly assigned to itself
  /// again.
  bool isResult(js.Expression node) {
    return node is js.VariableUse && node.name == resultName;
  }

  @override
  js.Expression visitBinary(js.Binary node) {
    if (shouldTransform(node.right) && (node.op == "||" || node.op == "&&")) {
      int thenLabel = newLabel("then");
      int joinLabel = newLabel("join");
      withExpression(node.left, (js.Expression left) {
        js.Statement assignLeft = isResult(left)
            ? new js.Block.empty()
            : js.js.statement('# = #;', [result, left]);
        if (node.op == "&&") {
          addStatement(js.js.statement('if (#) {#} else #',
              [left, gotoAndBreak(thenLabel), assignLeft]));
        } else {
          assert(node.op == "||");
          addStatement(js.js.statement('if (#) {#} else #',
              [left, assignLeft, gotoAndBreak(thenLabel)]));
        }
      }, store: true);
      addGoto(joinLabel);
      beginLabel(thenLabel);
      withExpression(node.right, (js.Expression value) {
        if (!isResult(value)) {
          addStatement(js.js.statement('# = #;', [result, value]));
        }
      }, store: false);
      beginLabel(joinLabel);
      return result;
    }

    return withExpression2(node.left, node.right,
        (left, right) => new js.Binary(node.op, left, right));
  }

  @override
  void visitBlock(js.Block node) {
    for (js.Statement statement in node.statements) {
      visitStatement(statement);
    }
  }

  @override
  void visitBreak(js.Break node) {
    js.Node target = analysis.targets[node];
    if (!shouldTransform(target)) {
      addStatement(node);
      return;
    }
    translateJump(target, breakLabels[target]);
  }

  @override
  js.Expression visitCall(js.Call node) {
    bool storeTarget = node.arguments.any(shouldTransform);
    return withCallTargetExpression(node.target, (target) {
      return withExpressions(node.arguments, (List<js.Expression> arguments) {
        return new js.Call(target, arguments);
      });
    }, store: storeTarget);
  }

  @override
  void visitCase(js.Case node) {
    return unreachable(node);
  }

  @override
  void visitCatch(js.Catch node) {
    return unreachable(node);
  }

  @override
  void visitComment(js.Comment node) {
    addStatement(node);
  }

  @override
  js.Expression visitConditional(js.Conditional node) {
    if (!shouldTransform(node.then) && !shouldTransform(node.otherwise)) {
      return withExpression(node.condition, (js.Expression condition) {
        return js.js('# ? # : #', [condition, node.then, node.otherwise]);
      }, store: false);
    }
    int thenLabel = newLabel("then");
    int joinLabel = newLabel("join");
    int elseLabel = newLabel("else");
    withExpression(node.condition, (js.Expression condition) {
      addStatement(js.js.statement('# = # ? # : #;',
          [goto, condition, js.number(thenLabel), js.number(elseLabel)]));
    }, store: false);
    addBreak();
    beginLabel(thenLabel);
    withExpression(node.then, (js.Expression value) {
      if (!isResult(value)) {
        addStatement(js.js.statement('# = #;', [result, value]));
      }
    }, store: false);
    addGoto(joinLabel);
    beginLabel(elseLabel);
    withExpression(node.otherwise, (js.Expression value) {
      if (!isResult(value)) {
        addStatement(js.js.statement('# = #;', [result, value]));
      }
    }, store: false);
    beginLabel(joinLabel);
    return result;
  }

  @override
  void visitContinue(js.Continue node) {
    js.Node target = analysis.targets[node];
    if (!shouldTransform(target)) {
      addStatement(node);
      return;
    }
    translateJump(target, continueLabels[target]);
  }

  /// Emits a break statement that exits the big switch statement.
  void addBreak() {
    if (insideUntranslatedBreakable) {
      hasJumpThoughOuterLabel = true;
      addStatement(new js.Break(outerLabelName));
    } else {
      addStatement(new js.Break(null));
    }
  }

  /// Common code for handling break, continue, return.
  ///
  /// It is necessary to run all nesting finally-handlers between the jump and
  /// the target. For that [next] is used as a stack of places to go.
  ///
  /// See also [visitFun].
  void translateJump(js.Node target, int targetLabel) {
    // Compute a stack of all the 'finally' nodes that must be visited before
    // the jump.
    // The bottom of the stack is the label where the jump goes to.
    List<int> jumpStack = new List<int>();
    for (js.Node node in jumpTargets.reversed) {
      if (finallyLabels[node] != null) {
        jumpStack.add(finallyLabels[node]);
      } else if (node == target) {
        jumpStack.add(targetLabel);
        break;
      }
      // Ignore other nodes.
    }
    jumpStack = jumpStack.reversed.toList();
    // As the program jumps directly to the top of the stack, it is taken off
    // now.
    int firstTarget = jumpStack.removeLast();
    if (jumpStack.isNotEmpty) {
      js.Expression jsJumpStack = new js.ArrayInitializer(
          jumpStack.map((int label) => js.number(label)).toList());
      addStatement(js.js.statement("# = #;", [next, jsJumpStack]));
    }
    addGoto(firstTarget);
  }

  @override
  void visitDefault(js.Default node) => unreachable(node);

  @override
  void visitDo(js.Do node) {
    if (!shouldTransform(node)) {
      bool oldInsideUntranslatedBreakable = insideUntranslatedBreakable;
      insideUntranslatedBreakable = true;
      withExpression(node.condition, (js.Expression condition) {
        addStatement(js.js.statement('do {#} while (#)',
                                     [node.body, condition]));
      }, store: false);
      insideUntranslatedBreakable = oldInsideUntranslatedBreakable;
      return;
    }
    int startLabel = newLabel("do body");

    int continueLabel = newLabel("do condition");
    continueLabels[node] = continueLabel;

    int afterLabel = newLabel("after do");
    breakLabels[node] = afterLabel;

    beginLabel(startLabel);

    jumpTargets.add(node);
    visitStatement(node.body);
    jumpTargets.removeLast();

    beginLabel(continueLabel);
    withExpression(node.condition, (js.Expression condition) {
      addStatement(js.js.statement('if (#) #',
          [condition, gotoAndBreak(startLabel)]));
    }, store: false);
    beginLabel(afterLabel);
  }

  @override
  void visitEmptyStatement(js.EmptyStatement node) {
    addStatement(node);
  }


  @override
  void visitExpressionStatement(js.ExpressionStatement node) {
    visitExpressionIgnoreResult(node.expression);
  }

  @override
  void visitFor(js.For node) {
    if (!shouldTransform(node)) {
      bool oldInsideUntranslated = insideUntranslatedBreakable;
      insideUntranslatedBreakable = true;
      // Note that node.init, node.condition, node.update all can be null, but
      // withExpressions handles that.
      withExpressions([
        node.init,
        node.condition,
        node.update
      ], (List<js.Expression> transformed) {
        addStatement(new js.For(transformed[0], transformed[1], transformed[2],
             translateInBlock(node.body)));
      });
      insideUntranslatedBreakable = oldInsideUntranslated;
      return;
    }

    if (node.init != null) {
      addExpressionStatement(visitExpression(node.init));
    }
    int startLabel = newLabel("for condition");
    // If there is no update, continuing the loop is the same as going to the
    // start.
    int continueLabel =
        (node.update == null) ? startLabel : newLabel("for update");
    continueLabels[node] = continueLabel;
    int afterLabel = newLabel("after for");
    breakLabels[node] = afterLabel;
    beginLabel(startLabel);
    js.Expression condition = node.condition;
    if (condition == null ||
        (condition is js.LiteralBool && condition.value == true)) {
      addStatement(new js.Comment("trivial condition"));
    } else {
      withExpression(condition, (js.Expression condition) {
        addStatement(new js.If.noElse(
            new js.Prefix("!", condition), gotoAndBreak(afterLabel)));
      }, store: false);
    }
    jumpTargets.add(node);
    visitStatement(node.body);
    jumpTargets.removeLast();
    if (node.update != null) {
      beginLabel(continueLabel);
      visitExpressionIgnoreResult(node.update);
    }
    addGoto(startLabel);
    beginLabel(afterLabel);
  }

  @override
  void visitForIn(js.ForIn node) {
    // The dart output currently never uses for-in loops.
    throw "Javascript for-in not implemented yet in the await transformation";
  }

  @override
  void visitFunctionDeclaration(js.FunctionDeclaration node) {
    unsupported(node);
  }

  // Only used for code where `!shouldTransform(node)`.
  js.Block translateInBlock(js.Statement node) {
    assert(!shouldTransform(node));
    List<js.Statement> oldBuffer = currentStatementBuffer;
    currentStatementBuffer = new List();
    List<js.Statement> resultBuffer = currentStatementBuffer;
    visitStatement(node);
    currentStatementBuffer = oldBuffer;
    return new js.Block(resultBuffer);
  }

  @override
  void visitIf(js.If node) {
    if (!shouldTransform(node.then) && !shouldTransform(node.otherwise)) {
      withExpression(node.condition, (js.Expression condition) {
        addStatement(new js.If(condition, translateInBlock(node.then),
            translateInBlock(node.otherwise)));
      }, store: false);
      return;
    }
    int thenLabel = newLabel("then");
    int joinLabel = newLabel("join");
    int elseLabel = (node.otherwise is js.EmptyStatement)
        ? joinLabel
        : newLabel("else");

    withExpression(node.condition, (js.Expression condition) {
      addExpressionStatement(
          new js.Assignment(
              goto,
              new js.Conditional(
                  condition,
                  js.number(thenLabel),
                  js.number(elseLabel))));
    }, store: false);
    addBreak();
    beginLabel(thenLabel);
    visitStatement(node.then);
    if (node.otherwise is! js.EmptyStatement) {
      addGoto(joinLabel);
      beginLabel(elseLabel);
      visitStatement(node.otherwise);
    }
    beginLabel(joinLabel);
  }

  @override
  visitInterpolatedExpression(js.InterpolatedExpression node) {
    return unsupported(node);
  }

  @override
  visitInterpolatedDeclaration(js.InterpolatedDeclaration node) {
    return unsupported(node);
  }

  @override
  visitInterpolatedLiteral(js.InterpolatedLiteral node) => unsupported(node);

  @override
  visitInterpolatedParameter(js.InterpolatedParameter node) {
    return unsupported(node);
  }

  @override
  visitInterpolatedSelector(js.InterpolatedSelector node) {
    return unsupported(node);
  }

  @override
  visitInterpolatedStatement(js.InterpolatedStatement node) {
    return unsupported(node);
  }

  @override
  void visitLabeledStatement(js.LabeledStatement node) {
    if (!shouldTransform(node)) {
      addStatement(
          new js.LabeledStatement(node.label, translateInBlock(node.body)));
      return;
    }
    // `continue label` is really continuing the nested loop.
    // This is set up in [PreTranslationAnalysis.visitContinue].
    // Here we only need a breakLabel:
    int breakLabel = newLabel("break ${node.label}");
    breakLabels[node] = breakLabel;

    jumpTargets.add(node);
    visitStatement(node.body);
    jumpTargets.removeLast();
    beginLabel(breakLabel);
  }

  @override
  js.Expression visitLiteralBool(js.LiteralBool node) => node;

  @override
  visitLiteralExpression(js.LiteralExpression node) => unsupported(node);

  @override
  js.Expression visitLiteralNull(js.LiteralNull node) => node;

  @override
  js.Expression visitLiteralNumber(js.LiteralNumber node) => node;

  @override
  visitLiteralStatement(js.LiteralStatement node) => unsupported(node);

  @override
  js.Expression visitLiteralString(js.LiteralString node) => node;

  @override
  visitNamedFunction(js.NamedFunction node) {
    unsupported(node);
  }

  @override
  js.Expression visitNew(js.New node) {
    bool storeTarget = node.arguments.any(shouldTransform);
    return withCallTargetExpression(node.target, (target) {
      return withExpressions(node.arguments, (List<js.Expression> arguments) {
        return new js.New(target, arguments);
      });
    }, store: storeTarget);
  }

  @override
  js.Expression visitObjectInitializer(js.ObjectInitializer node) {
    return withExpressions(
        node.properties.map((js.Property property) => property.value).toList(),
        (List<js.Node> values) {
      List<js.Property> properties = new List.generate(values.length, (int i) {
        return new js.Property(node.properties[i].name, values[i]);
      });
      return new js.ObjectInitializer(properties);
    });
  }

  @override
  visitParameter(js.Parameter node) => unreachable(node);

  @override
  js.Expression visitPostfix(js.Postfix node) {
    if (node.op == "++" || node.op == "--") {
      js.Expression argument = node.argument;
      if (argument is js.VariableUse) {
        return new js.Postfix(node.op, argument);
      } else if (argument is js.PropertyAccess) {
        return withExpression2(argument.receiver, argument.selector,
            (receiver, selector) {
          return new js.Postfix(
              node.op, new js.PropertyAccess(receiver, selector));
        });
      } else {
        throw "Unexpected postfix ${node.op} "
            "operator argument ${node.argument}";
      }
    }
    return withExpression(node.argument,
        (js.Expression argument) => new js.Postfix(node.op, argument),
        store: false);
  }

  @override
  js.Expression visitPrefix(js.Prefix node) {
    if (node.op == "++" || node.op == "--") {
      js.Expression argument = node.argument;
      if (argument is js.VariableUse) {
        return new js.Prefix(node.op, argument);
      } else if (argument is js.PropertyAccess) {
        return withExpression2(argument.receiver, argument.selector,
            (receiver, selector) {
          return new js.Prefix(
              node.op, new js.PropertyAccess(receiver, selector));
        });
      } else {
        throw "Unexpected prefix ${node.op} operator "
            "argument ${node.argument}";
      }
    }
    return withExpression(node.argument,
        (js.Expression argument) => new js.Prefix(node.op, argument),
        store: false);
  }

  @override
  visitProgram(js.Program node) => unsupported(node);

  @override
  js.Property visitProperty(js.Property node) {
    return withExpression(
        node.value, (js.Expression value) => new js.Property(node.name, value),
        store: false);
  }

  @override
  js.Expression visitRegExpLiteral(js.RegExpLiteral node) => node;

  @override
  void visitReturn(js.Return node) {
    assert(node.value == null || (!isSyncStar && !isAsyncStar));
    js.Node target = analysis.targets[node];
    if (node.value != null) {
      withExpression(node.value, (js.Expression value) {
        addStatement(js.js.statement("# = #;", [returnValue, value]));
      }, store: false);
    }
    translateJump(target, exitLabel);
  }

  @override
  void visitSwitch(js.Switch node) {
    if (!node.cases.any(shouldTransform)) {
      // If only the key has an await, translation can be simplified.
      bool oldInsideUntranslated = insideUntranslatedBreakable;
      insideUntranslatedBreakable = true;
      withExpression(node.key, (js.Expression key) {
        List<js.SwitchClause> cases = node.cases.map((js.SwitchClause clause) {
          if (clause is js.Case) {
            return new js.Case(
                clause.expression, translateInBlock(clause.body));
          } else if (clause is js.Default) {
            return new js.Default(translateInBlock(clause.body));
          }
        }).toList();
        addStatement(new js.Switch(key, cases));
      }, store: false);
      insideUntranslatedBreakable = oldInsideUntranslated;
      return;
    }
    int before = newLabel("switch");
    int after = newLabel("after switch");
    breakLabels[node] = after;

    beginLabel(before);
    List<int> labels = new List<int>(node.cases.length);

    bool anyCaseExpressionTransformed = node.cases.any(
        (js.SwitchClause x) => x is js.Case && shouldTransform(x.expression));
    if (anyCaseExpressionTransformed) {
      int defaultIndex = null; // Null means no default was found.
      // If there is an await in one of the keys, a chain of ifs has to be used.

      withExpression(node.key, (js.Expression key) {
        int i = 0;
        for (js.SwitchClause clause in node.cases) {
          if (clause is js.Default) {
            // The goto for the default case is added after all non-default
            // clauses have been handled.
            defaultIndex = i;
            labels[i] = newLabel("default");
            continue;
          } else if (clause is js.Case) {
            labels[i] = newLabel("case");
            withExpression(clause.expression, (expression) {
              addStatement(new js.If.noElse(
                  new js.Binary("===", key, expression),
                  gotoAndBreak(labels[i])));
            }, store: false);
          }
          i++;
        }
      }, store: true);

      if (defaultIndex == null) {
        addGoto(after);
      } else {
        addGoto(labels[defaultIndex]);
      }
    } else {
      bool hasDefault = false;
      int i = 0;
      List<js.SwitchClause> clauses = new List<js.SwitchClause>();
      for (js.SwitchClause clause in node.cases) {
        if (clause is js.Case) {
          labels[i] = newLabel("case");
          clauses.add(new js.Case(clause.expression, gotoAndBreak(labels[i])));
        } else if (clause is js.Default) {
          labels[i] = newLabel("default");
          clauses.add(new js.Default(gotoAndBreak(labels[i])));
          hasDefault = true;
        } else {
          diagnosticListener.internalError(
              spannable, "Unknown clause type $clause");
        }
        i++;
      }
      if (!hasDefault) {
        clauses.add(new js.Default(gotoAndBreak(after)));
      }
      withExpression(node.key, (js.Expression key) {
        addStatement(new js.Switch(key, clauses));
      }, store: false);

      addBreak();
    }

    jumpTargets.add(node);
    for (int i = 0; i < labels.length; i++) {
      beginLabel(labels[i]);
      visitStatement(node.cases[i].body);
    }
    beginLabel(after);
    jumpTargets.removeLast();
  }

  @override
  js.Expression visitThis(js.This node) {
    return self;
  }

  @override
  void visitThrow(js.Throw node) {
    withExpression(node.expression, (js.Expression expression) {
      addStatement(new js.Throw(expression));
    }, store: false);
  }

  setErrorHandler([int errorHandler]) {
    js.Expression label = (errorHandler == null)
        ? currentErrorHandler
        : js.number(errorHandler);
    addStatement(js.js.statement('# = #;',[handler, label]));
  }

  List<int> _finalliesUpToAndEnclosingHandler() {
    List<int> result = new List<int>();
    for (int i = jumpTargets.length - 1; i >= 0; i--) {
      js.Node node = jumpTargets[i];
      int handlerLabel = handlerLabels[node];
      if (handlerLabel != null) {
        result.add(handlerLabel);
        break;
      }
      int finallyLabel = finallyLabels[node];
      if (finallyLabel != null) {
        result.add(finallyLabel);
      }
    }
    return result.reversed.toList();
  }

  /// See the comments of [visitFun] for more explanation.
  void visitTry(js.Try node) {
    if (!shouldTransform(node)) {
      js.Block body = translateInBlock(node.body);
      js.Catch catchPart = (node.catchPart == null)
          ? null
          : new js.Catch(node.catchPart.declaration,
              translateInBlock(node.catchPart.body));
      js.Block finallyPart = (node.finallyPart == null)
          ? null
          : translateInBlock(node.finallyPart);
      addStatement(new js.Try(body, catchPart, finallyPart));
      return;
    }

    hasTryBlocks = true;
    int uncaughtLabel = newLabel("uncaught");
    int handlerLabel = (node.catchPart == null)
        ? uncaughtLabel
        : newLabel("catch");

    int finallyLabel = newLabel("finally");
    int afterFinallyLabel = newLabel("after finally");
    if (node.finallyPart != null) {
      finallyLabels[node.finallyPart] = finallyLabel;
      jumpTargets.add(node.finallyPart);
    }

    handlerLabels[node] = handlerLabel;
    jumpTargets.add(node);

    // Set the error handler here. It must be cleared on every path out;
    // normal and error exit.
    setErrorHandler();

    visitStatement(node.body);

    js.Node last = jumpTargets.removeLast();
    assert(last == node);

    if (node.finallyPart == null) {
      setErrorHandler();
      addGoto(afterFinallyLabel);
    } else {
      // The handler is reset as the first thing in the finally block.
      addStatement(
          js.js.statement("#.push(#);", [next, js.number(afterFinallyLabel)]));
      addGoto(finallyLabel);
    }

    if (node.catchPart != null) {
      beginLabel(handlerLabel);
      // [uncaughtLabel] is the handler for the code in the catch-part.
      // It ensures that [nextName] is set up to run the right finally blocks.
      handlerLabels[node.catchPart] = uncaughtLabel;
      jumpTargets.add(node.catchPart);
      setErrorHandler();
      // The catch declaration name can shadow outer variables, so a fresh name
      // is needed to avoid collisions.  See Ecma 262, 3rd edition,
      // section 12.14.
      String errorRename = freshName(node.catchPart.declaration.name);
      localVariables.add(new js.VariableDeclaration(errorRename));
      variableRenamings
          .add(new Pair(node.catchPart.declaration.name, errorRename));
      addStatement(js.js.statement("# = #;", [errorRename, currentError]));
      visitStatement(node.catchPart.body);
      variableRenamings.removeLast();
      if (node.finallyPart != null) {
        // The error has been caught, so after the finally, continue after the
        // try.
        addStatement(
            js.js.statement("#.push(#);",
                            [next, js.number(afterFinallyLabel)]));
        addGoto(finallyLabel);
      } else {
        addGoto(afterFinallyLabel);
      }
      js.Node last = jumpTargets.removeLast();
      assert(last == node.catchPart);
    }

    // The "uncaught"-handler tells the finally-block to continue with
    // the enclosing finally-blocks until the current catch-handler.
    beginLabel(uncaughtLabel);

    List<int> enclosingFinallies = _finalliesUpToAndEnclosingHandler();

    int nextLabel = enclosingFinallies.removeLast();
    if (enclosingFinallies.isNotEmpty) {
      // [enclosingFinallies] can be empty if there is no surrounding finally
      // blocks. Then [nextLabel] will be [rethrowLabel].
      addStatement(
          js.js.statement("# = #;", [next, new js.ArrayInitializer(
              enclosingFinallies.map(js.number).toList())]));
    }
    if (node.finallyPart == null) {
      // The finally-block belonging to [node] will be visited because of
      // fallthrough. If it does not exist, add an explicit goto.
      addGoto(nextLabel);
    }
    if (node.finallyPart != null) {
      js.Node last = jumpTargets.removeLast();
      assert(last == node.finallyPart);

      beginLabel(finallyLabel);
      setErrorHandler();
      visitStatement(node.finallyPart);
      addStatement(new js.Comment("// goto the next finally handler"));
      addStatement(js.js.statement("# = #.pop();", [goto, next]));
      addBreak();
    }
    beginLabel(afterFinallyLabel);
  }

  @override
  visitVariableDeclaration(js.VariableDeclaration node) {
    unreachable(node);
  }

  @override
  js.Expression visitVariableDeclarationList(js.VariableDeclarationList node) {
    List<js.Assignment> initializations = new List<js.Assignment>();

    // Declaration of local variables is hoisted outside the helper but the
    // initialization is done here.
    for (js.VariableInitialization initialization in node.declarations) {
      js.VariableDeclaration declaration = initialization.declaration;
      localVariables.add(declaration);
      if (initialization.value != null) {
        withExpression(initialization.value, (js.Expression value) {
          initializations.add(
              new js.Assignment(new js.VariableUse(declaration.name), value));
        }, store: false);
      }
    }
    if (initializations.isEmpty) {
      // Dummy expression. Will be dropped by [visitExpressionIgnoreResult].
      return js.number(0);
    } else {
      return initializations.reduce(
          (js.Expression first, js.Expression second) {
        return new js.Binary(",", first, second);
      });
    }
  }

  @override
  void visitVariableInitialization(js.VariableInitialization node) {
    unreachable(node);
  }

  @override
  js.Expression visitVariableUse(js.VariableUse node) {
    Pair<String, String> renaming = variableRenamings.lastWhere(
        (Pair renaming) => renaming.a == node.name, orElse: () => null);
    if (renaming == null) return node;
    return new js.VariableUse(renaming.b);
  }

  @override
  void visitWhile(js.While node) {
    if (!shouldTransform(node)) {
      bool oldInsideUntranslated = insideUntranslatedBreakable;
      insideUntranslatedBreakable = true;
      withExpression(node.condition, (js.Expression condition) {
        addStatement(new js.While(condition, translateInBlock(node.body)));
      }, store: false);
      insideUntranslatedBreakable = oldInsideUntranslated;
      return;
    }
    int continueLabel = newLabel("while condition");
    continueLabels[node] = continueLabel;
    beginLabel(continueLabel);

    int afterLabel = newLabel("after while");
    breakLabels[node] = afterLabel;
    js.Expression condition = node.condition;
    // If the condition is `true`, a test is not needed.
    if (!(condition is js.LiteralBool && condition.value == true)) {
      withExpression(node.condition, (js.Expression condition) {
        addStatement(new js.If.noElse(
            new js.Prefix("!", condition), gotoAndBreak(afterLabel)));
      }, store: false);
    }
    jumpTargets.add(node);
    visitStatement(node.body);
    jumpTargets.removeLast();
    addGoto(continueLabel);
    beginLabel(afterLabel);
  }

  addYield(js.DartYield node, js.Expression expression);

  @override
  void visitDartYield(js.DartYield node) {
    assert(isSyncStar || isAsyncStar);
    int label = newLabel("after yield");
    // Don't do a break here for the goto, but instead a return in either
    // addSynYield or addAsyncYield.
    withExpression(node.expression, (js.Expression expression) {
      addStatement(setGotoVariable(label));
      addYield(node, expression);
    }, store: false);
    beginLabel(label);
  }
}

js.VariableInitialization
    _makeVariableInitializer(dynamic variable, js.Expression initValue) {
  js.VariableDeclaration declaration;
  if (variable is js.VariableUse) {
    declaration = new js.VariableDeclaration(variable.name);
  } else if (variable is String) {
    declaration = new js.VariableDeclaration(variable);
  } else {
    assert(variable is js.VariableDeclaration);
    declaration = variable;
  }
  return new js.VariableInitialization(declaration, initValue);
}

class AsyncRewriter extends AsyncRewriterBase {

  bool get isAsync => true;

  /// The Completer that will finish an async function.
  ///
  /// Not used for sync* or async* functions.
  String completerName;
  js.VariableUse get completer => new js.VariableUse(completerName);

  /// The function called by an async function to simulate an await or return.
  ///
  /// For an await it is called with:
  ///
  /// - The value to await
  /// - The body function [bodyName]
  /// - The completer object [completer]
  ///
  /// For a return it is called with:
  ///
  /// - The value to complete the completer with.
  /// - [error_codes.SUCCESS]
  /// - The completer object [completer]
  ///
  /// For a throw it is called with:
  ///
  /// - The error to complete the completer with.
  /// - [error_codes.ERROR]
  /// - The completer object [completer]
  final js.Expression asyncHelper;

  /// Contructor used to initialize the [completer] variable.
  ///
  /// Specific to async methods.
  final js.Expression newCompleter;


  AsyncRewriter(DiagnosticListener diagnosticListener,
                spannable,
                {this.asyncHelper,
                 this.newCompleter,
                 safeVariableName})
        : super(diagnosticListener,
                spannable,
                safeVariableName);

  @override
  void addYield(js.DartYield node, js.Expression expression) {
    diagnosticListener.internalError(spannable,
        "Yield in non-generating async function");
  }

  void addErrorExit() {
    beginLabel(rethrowLabel);
    addStatement(js.js.statement(
        "return #thenHelper(#currentError, #errorCode, #completer);", {
          "thenHelper": asyncHelper,
          "errorCode": js.number(error_codes.ERROR),
          "currentError": currentError,
          "completer": completer}));
  }

  /// Returning from an async method calls [asyncStarHelper] with the result.
  /// (the result might have been stored in [returnValue] by some finally
  /// block).
  void addSuccesExit() {
    if (analysis.hasExplicitReturns) {
      beginLabel(exitLabel);
    } else {
      addStatement(new js.Comment("implicit return"));
    }
    addStatement(js.js.statement(
        "return #runtimeHelper(#returnValue, #successCode, "
            "#completer, null);", {
         "runtimeHelper": asyncHelper,
         "successCode": js.number(error_codes.SUCCESS),
         "returnValue": analysis.hasExplicitReturns
             ? returnValue
             : new js.LiteralNull(),
         "completer": completer}));
  }

  @override
  Iterable<js.VariableInitialization> variableInitializations() {
    List<js.VariableInitialization> variables =
        new List<js.VariableInitialization>();
    variables.add(_makeVariableInitializer(completer,
                                        new js.New(newCompleter, [])));
    if (analysis.hasExplicitReturns) {
      variables.add(_makeVariableInitializer(returnValue, null));
    }
    return variables;
  }

  @override
  void initializeNames() {
    completerName = freshName("completer");
  }

  @override
  js.Statement awaitStatement(js.Expression value) {
    return js.js.statement("""
          return #asyncHelper(#value,
                              #body,
                              #completer);
          """, {
            "asyncHelper": asyncHelper,
            "value": value,
            "body": body,
            "completer": completer});
  }

  @override
  js.Fun finishFunction(List<js.Parameter> parameters,
                        js.Statement rewrittenBody,
                        js.VariableDeclarationList variableDeclarations) {
    return js.js("""
        function (#parameters) {
          #variableDeclarations;
          function #bodyName(#errorCode, #result) {
            if (#errorCode === #ERROR) {
                #currentError = #result;
                #goto = #handler;
            }
            #rewrittenBody;
          }
          return #asyncHelper(null, #bodyName, #completer, null);
        }""", {
          "parameters": parameters,
          "variableDeclarations": variableDeclarations,
          "ERROR": js.number(error_codes.ERROR),
          "rewrittenBody": rewrittenBody,
          "bodyName": bodyName,
          "currentError": currentError,
          "goto": goto,
          "handler": handler,
          "errorCode": errorCodeName,
          "result": resultName,
          "asyncHelper": asyncHelper,
          "completer": completer,
        });
  }
}

class SyncStarRewriter extends AsyncRewriterBase {

  bool get isSyncStar => true;

  /// Contructor creating the Iterable for a sync* method. Called with
  /// [bodyName].
  final js.Expression newIterable;

  /// A JS Expression that creates a marker showing that iteration is over.
  ///
  /// Called without arguments.
  final js.Expression endOfIteration;

  /// A JS Expression that creates a marker indication a 'yield*' statement.
  ///
  /// Called with the stream to yield from.
  final js.Expression yieldStarExpression;

  /// Used by sync* functions to throw exeptions.
  final js.Expression uncaughtErrorExpression;

  SyncStarRewriter(DiagnosticListener diagnosticListener,
                spannable,
                {this.endOfIteration,
                 this.newIterable,
                 this.yieldStarExpression,
                 this.uncaughtErrorExpression,
                 safeVariableName})
        : super(diagnosticListener,
                spannable,
                safeVariableName);

  /// Translates a yield/yield* in an sync*.
  ///
  /// `yield` in a sync* function just returns [value].
  /// `yield*` wraps [value] in a [yieldStarExpression] and returns it.
  @override
  void addYield(js.DartYield node, js.Expression expression) {
    if (node.hasStar) {
      addStatement(
          new js.Return(new js.Call(yieldStarExpression, [expression])));
    } else {
      addStatement(new js.Return(expression));
    }
  }

  @override
  js.Fun finishFunction(List<js.Parameter> parameters,
                        js.Statement rewrittenBody,
                        js.VariableDeclarationList variableDeclarations) {
    // Each iterator invocation on the iterable should work on its own copy of
    // the parameters.
    // TODO(sigurdm): We only need to do this copying for parameters that are
    // mutated.
    List<js.VariableInitialization> declarations =
        new List<js.VariableInitialization>();
    List<js.Parameter> renamedParameters = new List<js.Parameter>();
    for (js.Parameter parameter in parameters) {
      String name = parameter.name;
      String renamedName = freshName(name);
      renamedParameters.add(new js.Parameter(renamedName));
      declarations.add(
          new js.VariableInitialization(new js.VariableDeclaration(name),
                                        new js.VariableUse(renamedName)));
    }
    js.VariableDeclarationList copyParameters =
        new js.VariableDeclarationList(declarations);
    return js.js("""
          function (#renamedParameters) {
            if (#needsThis)
              var #self = this;
            return new #newIterable(function () {
              if (#hasParameters) {
                #copyParameters;
              }
              #varDecl;
              return function #body(#errorCode, #result) {
                if (#errorCode === #ERROR) {
                    #currentError = #result;
                    #goto = #handler;
                }
                #helperBody;
              };
            });
          }
          """, {
            "renamedParameters": renamedParameters,
            "needsThis": analysis.hasThis,
            "helperBody": rewrittenBody,
            "hasParameters": parameters.isNotEmpty,
            "copyParameters": copyParameters,
            "varDecl": variableDeclarations,
            "errorCode": errorCodeName,
            "newIterable": newIterable,
            "body": bodyName,
            "self": selfName,
            "result": resultName,
            "goto": goto,
            "handler": handler,
            "currentError": currentErrorName,
            "ERROR": js.number(error_codes.ERROR),
          });
  }

  void addErrorExit() {
    beginLabel(rethrowLabel);
    addStatement(js.js.statement('return #(#);',
                 [uncaughtErrorExpression, currentError]));
  }

  /// Returning from a sync* function returns an [endOfIteration] marker.
  void addSuccesExit() {
    if (analysis.hasExplicitReturns) {
      beginLabel(exitLabel);
    } else {
      addStatement(new js.Comment("implicit return"));
    }
    addStatement(js.js.statement('return #();', [endOfIteration]));
  }

  @override
  Iterable<js.VariableInitialization> variableInitializations() {
    List<js.VariableInitialization> variables =
        new List<js.VariableInitialization>();
    return variables;
  }

  @override
  js.Statement awaitStatement(js.Expression value) {
    throw diagnosticListener.internalError(spannable,
        "Sync* functions cannot contain await statements.");
  }

  @override
  void initializeNames() {}
}

class AsyncStarRewriter extends AsyncRewriterBase {

  bool get isAsyncStar => true;

  /// The stack of labels of finally blocks to assign to [next] if the
  /// async* [StreamSubscription] was canceled during a yield.
  js.VariableUse get nextWhenCanceled {
    return new js.VariableUse(nextWhenCanceledName);
  }
  String nextWhenCanceledName;

  /// The StreamController that controls an async* function.
  String controllerName;
  js.VariableUse get controller => new js.VariableUse(controllerName);

  /// The function called by an async* function to simulate an await, yield or
  /// yield*.
  ///
  /// For an await/yield/yield* it is called with:
  ///
  /// - The value to await/yieldExpression(value to yield)/
  /// yieldStarExpression(stream to yield)
  /// - The body function [bodyName]
  /// - The controller object [controllerName]
  ///
  /// For a return it is called with:
  ///
  /// - null
  /// - null
  /// - The [controllerName]
  /// - null.
  final js.Expression asyncStarHelper;

  /// Contructor used to initialize the [controllerName] variable.
  ///
  /// Specific to async* methods.
  final js.Expression newController;

  /// Used to get the `Stream` out of the [controllerName] variable.
  final js.Expression streamOfController;

  /// A JS Expression that creates a marker indicating a 'yield' statement.
  ///
  /// Called with the value to yield.
  final js.Expression yieldExpression;

  /// A JS Expression that creates a marker indication a 'yield*' statement.
  ///
  /// Called with the stream to yield from.
  final js.Expression yieldStarExpression;

  AsyncStarRewriter(DiagnosticListener diagnosticListener,
                spannable,
                {this.asyncStarHelper,
                 this.streamOfController,
                 this.newController,
                 this.yieldExpression,
                 this.yieldStarExpression,
                 String safeVariableName(String original)})
        : super(diagnosticListener,
                spannable,
                safeVariableName);


  /// Translates a yield/yield* in an async* function.
  ///
  /// yield/yield* in an async* function is translated much like the `await` is
  /// translated in [visitAwait], only the object is wrapped in a
  /// [yieldExpression]/[yieldStarExpression] to let [asyncStarHelper]
  /// distinguish them.
  /// Also [nextWhenCanceled] is set up to contain the finally blocks that
  /// must be run in case the stream was canceled.
  @override
  void addYield(js.DartYield node, js.Expression expression) {
    // Find all the finally blocks that should be performed if the stream is
    // canceled during the yield.
    // At the bottom of the stack is the return label.
    List<int> enclosingFinallyLabels = <int>[exitLabel];
    enclosingFinallyLabels.addAll(jumpTargets
        .where((js.Node node) => finallyLabels[node] != null)
        .map((js.Block node) => finallyLabels[node]));
    addStatement(js.js.statement("# = #;",
        [nextWhenCanceled, new js.ArrayInitializer(
            enclosingFinallyLabels.map(js.number).toList())]));
    addStatement(js.js.statement("""
        return #asyncStarHelper(#yieldExpression(#expression), #body,
            #controller);""", {
      "asyncStarHelper": asyncStarHelper,
      "yieldExpression": node.hasStar ? yieldStarExpression : yieldExpression,
      "expression": expression,
      "body": body,
      "controller": controllerName,
    }));
  }

  @override
  js.Fun finishFunction(List<js.Parameter> parameters,
                        js.Statement rewrittenBody,
                        js.VariableDeclarationList variableDeclarations) {
    return js.js("""
        function (#parameters) {
          #variableDeclarations;
          function #bodyName(#errorCode, #result) {
            if (#hasYield) {
              switch (#errorCode) {
                case #STREAM_WAS_CANCELED:
                  #next = #nextWhenCanceled;
                  #goto = #next.pop();
                  break;
                case #ERROR:
                  #currentError = #result;
                  #goto = #handler;
              }
            } else {
              if (#errorCode === #ERROR) {
                #currentError = #result;
                #goto = #handler;
              }
            }
            #rewrittenBody;
          }
          return #streamOfController(#controller);
        }""", {
          "parameters": parameters,
          "variableDeclarations": variableDeclarations,
          "STREAM_WAS_CANCELED": js.number(error_codes.STREAM_WAS_CANCELED),
          "ERROR": js.number(error_codes.ERROR),
          "hasYield": analysis.hasYield,
          "rewrittenBody": rewrittenBody,
          "bodyName": bodyName,
          "currentError": currentError,
          "goto": goto,
          "handler": handler,
          "next": next,
          "nextWhenCanceled": nextWhenCanceled,
          "errorCode": errorCodeName,
          "result": resultName,
          "streamOfController": streamOfController,
          "controller": controllerName,
        });
  }

  @override
  void addErrorExit() {
    beginLabel(rethrowLabel);
    addStatement(js.js.statement(
        "return #asyncHelper(#currentError, #errorCode, #controller);", {
          "asyncHelper": asyncStarHelper,
          "errorCode": js.number(error_codes.ERROR),
          "currentError": currentError,
          "controller": controllerName}));
  }

  /// Returning from an async* function calls the [streamHelper] with an
  /// [endOfIteration] marker.
  @override
  void addSuccesExit() {
    beginLabel(exitLabel);

    addStatement(js.js.statement(
      "return #streamHelper(null, #successCode, #controller);", {
      "streamHelper": asyncStarHelper,
      "successCode": js.number(error_codes.SUCCESS),
      "controller": controllerName}));
  }

  @override
  Iterable<js.VariableInitialization> variableInitializations() {
    List<js.VariableInitialization> variables =
        new List<js.VariableInitialization>();
    variables.add(_makeVariableInitializer(controller,
                         js.js('#(#)', [newController, bodyName])));
    if (analysis.hasYield) {
      variables.add(_makeVariableInitializer(nextWhenCanceled, null));
    }
    return variables;
  }

  @override
  void initializeNames() {
    controllerName = freshName("controller");
    nextWhenCanceledName = freshName("nextWhenCanceled");
  }

  @override
  js.Statement awaitStatement(js.Expression value) {
    return js.js.statement("""
          return #asyncHelper(#value,
                              #body,
                              #controller);
          """, {
            "asyncHelper": asyncStarHelper,
            "value": value,
            "body": body,
            "controller": controllerName});
  }
}

/// Finds out
///
/// - which expressions have yield or await nested in them.
/// - targets of jumps
/// - a set of used names.
/// - if any [This]-expressions are used.
class PreTranslationAnalysis extends js.NodeVisitor<bool> {
  Set<js.Node> hasAwaitOrYield = new Set<js.Node>();

  Map<js.Node, js.Node> targets = new Map<js.Node, js.Node>();
  List<js.Node> loopsAndSwitches = new List<js.Node>();
  List<js.LabeledStatement> labelledStatements =
      new List<js.LabeledStatement>();
  Set<String> usedNames = new Set<String>();

  bool hasExplicitReturns = false;

  bool hasThis = false;

  bool hasYield = false;

  bool hasFinally = false;

  // The function currently being analyzed.
  js.Fun currentFunction;

  // For error messages.
  final Function unsupported;

  PreTranslationAnalysis(void this.unsupported(js.Node node));

  bool visit(js.Node node) {
    bool containsAwait = node.accept(this);
    if (containsAwait) {
      hasAwaitOrYield.add(node);
    }
    return containsAwait;
  }

  analyze(js.Fun node) {
    currentFunction = node;
    node.params.forEach(visit);
    visit(node.body);
  }

  @override
  bool visitAccess(js.PropertyAccess node) {
    bool receiver = visit(node.receiver);
    bool selector = visit(node.selector);
    return receiver || selector;
  }

  @override
  bool visitArrayHole(js.ArrayHole node) {
    return false;
  }

  @override
  bool visitArrayInitializer(js.ArrayInitializer node) {
    bool containsAwait = false;
    for (js.Expression element in node.elements) {
      if (visit(element)) containsAwait = true;
    }
    return containsAwait;
  }

  @override
  bool visitAssignment(js.Assignment node) {
    bool leftHandSide = visit(node.leftHandSide);
    bool value = (node.value == null) ? false : visit(node.value);
    return leftHandSide || value;
  }

  @override
  bool visitAwait(js.Await node) {
    visit(node.expression);
    return true;
  }

  @override
  bool visitBinary(js.Binary node) {
    bool left = visit(node.left);
    bool right = visit(node.right);
    return left || right;
  }

  @override
  bool visitBlock(js.Block node) {
    bool containsAwait = false;
    for (js.Statement statement in node.statements) {
      if (visit(statement)) containsAwait = true;
    }
    return containsAwait;
  }

  @override
  bool visitBreak(js.Break node) {
    if (node.targetLabel != null) {
      targets[node] = labelledStatements.lastWhere(
          (js.LabeledStatement statement) {
        return statement.label == node.targetLabel;
      });
    } else {
      targets[node] = loopsAndSwitches.last;
    }
    return false;
  }

  @override
  bool visitCall(js.Call node) {
    bool containsAwait = visit(node.target);
    for (js.Expression argument in node.arguments) {
      if (visit(argument)) containsAwait = true;
    }
    return containsAwait;
  }

  @override
  bool visitCase(js.Case node) {
    bool expression = visit(node.expression);
    bool body = visit(node.body);
    return expression || body;
  }

  @override
  bool visitCatch(js.Catch node) {
    bool declaration = visit(node.declaration);
    bool body = visit(node.body);
    return declaration || body;
  }

  @override
  bool visitComment(js.Comment node) {
    return false;
  }

  @override
  bool visitConditional(js.Conditional node) {
    bool condition = visit(node.condition);
    bool then = visit(node.then);
    bool otherwise = visit(node.otherwise);
    return condition || then || otherwise;
  }

  @override
  bool visitContinue(js.Continue node) {
    if (node.targetLabel != null) {
      js.LabeledStatement targetLabel = labelledStatements.lastWhere(
          (js.LabeledStatement stm) => stm.label == node.targetLabel);
      js.Loop targetStatement = targetLabel.body;
      targets[node] = targetStatement;
    } else {
      targets[node] =
          loopsAndSwitches.lastWhere((js.Node node) => node is! js.Switch);
    }
    assert(() {
      js.Node target = targets[node];
      return target is js.Loop ||
          (target is js.LabeledStatement && target.body is js.Loop);
    });
    return false;
  }

  @override
  bool visitDefault(js.Default node) {
    return visit(node.body);
  }

  @override
  bool visitDo(js.Do node) {
    loopsAndSwitches.add(node);
    bool body = visit(node.body);
    bool condition = visit(node.condition);
    loopsAndSwitches.removeLast();
    return body || condition;
  }

  @override
  bool visitEmptyStatement(js.EmptyStatement node) {
    return false;
  }

  @override
  bool visitExpressionStatement(js.ExpressionStatement node) {
    return visit(node.expression);
  }

  @override
  bool visitFor(js.For node) {
    bool init = (node.init == null) ? false : visit(node.init);
    bool condition = (node.condition == null) ? false : visit(node.condition);
    bool update = (node.update == null) ? false : visit(node.update);
    loopsAndSwitches.add(node);
    bool body = visit(node.body);
    loopsAndSwitches.removeLast();
    return init || condition || update || body;
  }

  @override
  bool visitForIn(js.ForIn node) {
    bool object = visit(node.object);
    loopsAndSwitches.add(node);
    bool body = visit(node.body);
    loopsAndSwitches.removeLast();
    return object || body;
  }

  @override
  bool visitFun(js.Fun node) {
    return false;
  }

  @override
  bool visitFunctionDeclaration(js.FunctionDeclaration node) {
    return false;
  }

  @override
  bool visitIf(js.If node) {
    bool condition = visit(node.condition);
    bool then = visit(node.then);
    bool otherwise = visit(node.otherwise);
    return condition || then || otherwise;
  }

  @override
  bool visitInterpolatedExpression(js.InterpolatedExpression node) {
    return unsupported(node);
  }

  @override
  bool visitInterpolatedDeclaration(js.InterpolatedDeclaration node) {
    return unsupported(node);
  }

  @override
  bool visitInterpolatedLiteral(js.InterpolatedLiteral node) {
    return unsupported(node);
  }

  @override
  bool visitInterpolatedParameter(js.InterpolatedParameter node) {
    return unsupported(node);
  }

  @override
  bool visitInterpolatedSelector(js.InterpolatedSelector node) {
    return unsupported(node);
  }

  @override
  bool visitInterpolatedStatement(js.InterpolatedStatement node) {
    return unsupported(node);
  }

  @override
  bool visitLabeledStatement(js.LabeledStatement node) {
    usedNames.add(node.label);
    labelledStatements.add(node);
    bool containsAwait = visit(node.body);
    labelledStatements.removeLast();
    return containsAwait;
  }

  @override
  bool visitLiteralBool(js.LiteralBool node) {
    return false;
  }

  @override
  bool visitLiteralExpression(js.LiteralExpression node) {
    return unsupported(node);
  }

  @override
  bool visitLiteralNull(js.LiteralNull node) {
    return false;
  }

  @override
  bool visitLiteralNumber(js.LiteralNumber node) {
    return false;
  }

  @override
  bool visitLiteralStatement(js.LiteralStatement node) {
    return unsupported(node);
  }

  @override
  bool visitLiteralString(js.LiteralString node) {
    return false;
  }

  @override
  bool visitNamedFunction(js.NamedFunction node) {
    return false;
  }

  @override
  bool visitNew(js.New node) {
    return visitCall(node);
  }

  @override
  bool visitObjectInitializer(js.ObjectInitializer node) {
    bool containsAwait = false;
    for (js.Property property in node.properties) {
      if (visit(property)) containsAwait = true;
    }
    return containsAwait;
  }

  @override
  bool visitParameter(js.Parameter node) {
    usedNames.add(node.name);
    return false;
  }

  @override
  bool visitPostfix(js.Postfix node) {
    return visit(node.argument);
  }

  @override
  bool visitPrefix(js.Prefix node) {
    return visit(node.argument);
  }

  @override
  bool visitProgram(js.Program node) {
    throw "Unexpected";
  }

  @override
  bool visitProperty(js.Property node) {
    return visit(node.value);
  }

  @override
  bool visitRegExpLiteral(js.RegExpLiteral node) {
    return false;
  }

  @override
  bool visitReturn(js.Return node) {
    hasExplicitReturns = true;
    targets[node] = currentFunction;
    if (node.value == null) return false;
    return visit(node.value);
  }

  @override
  bool visitSwitch(js.Switch node) {
    loopsAndSwitches.add(node);
    // If the key has an `await` expression, do not transform the
    // body of the switch.
    visit(node.key);
    bool result = false;
    for (js.SwitchClause clause in node.cases) {
      if (visit(clause)) result = true;
    }
    loopsAndSwitches.removeLast();
    return result;
  }

  @override
  bool visitThis(js.This node) {
    hasThis = true;
    return false;
  }

  @override
  bool visitThrow(js.Throw node) {
    return visit(node.expression);
  }

  @override
  bool visitTry(js.Try node) {
    bool body = visit(node.body);
    bool catchPart = (node.catchPart == null) ? false : visit(node.catchPart);
    bool finallyPart =
        (node.finallyPart == null) ? false : visit(node.finallyPart);
    if (finallyPart != null) hasFinally = true;
    return body || catchPart || finallyPart;
  }

  @override
  bool visitVariableDeclaration(js.VariableDeclaration node) {
    usedNames.add(node.name);
    return false;
  }

  @override
  bool visitVariableDeclarationList(js.VariableDeclarationList node) {
    bool result = false;
    for (js.VariableInitialization init in node.declarations) {
      if (visit(init)) result = true;
    }
    return result;
  }

  @override
  bool visitVariableInitialization(js.VariableInitialization node) {
    return visitAssignment(node);
  }

  @override
  bool visitVariableUse(js.VariableUse node) {
    usedNames.add(node.name);
    return false;
  }

  @override
  bool visitWhile(js.While node) {
    loopsAndSwitches.add(node);
    bool condition = visit(node.condition);
    bool body = visit(node.body);
    loopsAndSwitches.removeLast();
    return condition || body;
  }

  @override
  bool visitDartYield(js.DartYield node) {
    hasYield = true;
    visit(node.expression);
    return true;
  }
}
