/*
 * Copyright 2008 Google Inc.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package com.google.gwt.dev.jjs.impl;

import com.google.gwt.core.ext.PropertyOracle;
import com.google.gwt.core.ext.linker.CastableTypeMap;
import com.google.gwt.core.ext.linker.impl.StandardCastableTypeMap;
import com.google.gwt.core.ext.linker.impl.StandardSymbolData;
import com.google.gwt.dev.jjs.HasSourceInfo;
import com.google.gwt.dev.jjs.InternalCompilerException;
import com.google.gwt.dev.jjs.JsOutputOption;
import com.google.gwt.dev.jjs.SourceInfo;
import com.google.gwt.dev.jjs.SourceOrigin;
import com.google.gwt.dev.jjs.ast.Context;
import com.google.gwt.dev.jjs.ast.HasEnclosingType;
import com.google.gwt.dev.jjs.ast.HasName;
import com.google.gwt.dev.jjs.ast.JAbsentArrayDimension;
import com.google.gwt.dev.jjs.ast.JAbstractMethodBody;
import com.google.gwt.dev.jjs.ast.JArrayLength;
import com.google.gwt.dev.jjs.ast.JArrayRef;
import com.google.gwt.dev.jjs.ast.JArrayType;
import com.google.gwt.dev.jjs.ast.JAssertStatement;
import com.google.gwt.dev.jjs.ast.JBinaryOperation;
import com.google.gwt.dev.jjs.ast.JBinaryOperator;
import com.google.gwt.dev.jjs.ast.JBlock;
import com.google.gwt.dev.jjs.ast.JBreakStatement;
import com.google.gwt.dev.jjs.ast.JCaseStatement;
import com.google.gwt.dev.jjs.ast.JCastOperation;
import com.google.gwt.dev.jjs.ast.JClassLiteral;
import com.google.gwt.dev.jjs.ast.JClassType;
import com.google.gwt.dev.jjs.ast.JConditional;
import com.google.gwt.dev.jjs.ast.JConstructor;
import com.google.gwt.dev.jjs.ast.JContinueStatement;
import com.google.gwt.dev.jjs.ast.JDeclarationStatement;
import com.google.gwt.dev.jjs.ast.JDeclaredType;
import com.google.gwt.dev.jjs.ast.JDoStatement;
import com.google.gwt.dev.jjs.ast.JExpression;
import com.google.gwt.dev.jjs.ast.JExpressionStatement;
import com.google.gwt.dev.jjs.ast.JField;
import com.google.gwt.dev.jjs.ast.JFieldRef;
import com.google.gwt.dev.jjs.ast.JForStatement;
import com.google.gwt.dev.jjs.ast.JGwtCreate;
import com.google.gwt.dev.jjs.ast.JIfStatement;
import com.google.gwt.dev.jjs.ast.JInstanceOf;
import com.google.gwt.dev.jjs.ast.JInterfaceType;
import com.google.gwt.dev.jjs.ast.JLabel;
import com.google.gwt.dev.jjs.ast.JLabeledStatement;
import com.google.gwt.dev.jjs.ast.JLocal;
import com.google.gwt.dev.jjs.ast.JLocalRef;
import com.google.gwt.dev.jjs.ast.JLongLiteral;
import com.google.gwt.dev.jjs.ast.JMethod;
import com.google.gwt.dev.jjs.ast.JMethodBody;
import com.google.gwt.dev.jjs.ast.JMethodCall;
import com.google.gwt.dev.jjs.ast.JNameOf;
import com.google.gwt.dev.jjs.ast.JNewArray;
import com.google.gwt.dev.jjs.ast.JNewInstance;
import com.google.gwt.dev.jjs.ast.JNode;
import com.google.gwt.dev.jjs.ast.JNullLiteral;
import com.google.gwt.dev.jjs.ast.JNumericEntry;
import com.google.gwt.dev.jjs.ast.JParameter;
import com.google.gwt.dev.jjs.ast.JParameterRef;
import com.google.gwt.dev.jjs.ast.JPostfixOperation;
import com.google.gwt.dev.jjs.ast.JPrefixOperation;
import com.google.gwt.dev.jjs.ast.JProgram;
import com.google.gwt.dev.jjs.ast.JReboundEntryPoint;
import com.google.gwt.dev.jjs.ast.JReferenceType;
import com.google.gwt.dev.jjs.ast.JReturnStatement;
import com.google.gwt.dev.jjs.ast.JSeedIdOf;
import com.google.gwt.dev.jjs.ast.JStatement;
import com.google.gwt.dev.jjs.ast.JSwitchStatement;
import com.google.gwt.dev.jjs.ast.JThisRef;
import com.google.gwt.dev.jjs.ast.JThrowStatement;
import com.google.gwt.dev.jjs.ast.JTryStatement;
import com.google.gwt.dev.jjs.ast.JType;
import com.google.gwt.dev.jjs.ast.JTypeOracle;
import com.google.gwt.dev.jjs.ast.JUnaryOperator;
import com.google.gwt.dev.jjs.ast.JVariable;
import com.google.gwt.dev.jjs.ast.JVisitor;
import com.google.gwt.dev.jjs.ast.JWhileStatement;
import com.google.gwt.dev.jjs.ast.js.JDebuggerStatement;
import com.google.gwt.dev.jjs.ast.js.JMultiExpression;
import com.google.gwt.dev.jjs.ast.js.JsCastMap;
import com.google.gwt.dev.jjs.ast.js.JsCastMap.JsQueryType;
import com.google.gwt.dev.jjs.ast.js.JsniClassLiteral;
import com.google.gwt.dev.jjs.ast.js.JsniFieldRef;
import com.google.gwt.dev.jjs.ast.js.JsniMethodBody;
import com.google.gwt.dev.jjs.ast.js.JsniMethodRef;
import com.google.gwt.dev.jjs.ast.js.JsonArray;
import com.google.gwt.dev.jjs.ast.js.JsonObject;
import com.google.gwt.dev.jjs.ast.js.JsonObject.JsonPropInit;
import com.google.gwt.dev.js.JsInliner;
import com.google.gwt.dev.js.JsParser;
import com.google.gwt.dev.js.JsStackEmulator;
import com.google.gwt.dev.js.ast.JsArrayAccess;
import com.google.gwt.dev.js.ast.JsArrayLiteral;
import com.google.gwt.dev.js.ast.JsBinaryOperation;
import com.google.gwt.dev.js.ast.JsBinaryOperator;
import com.google.gwt.dev.js.ast.JsBlock;
import com.google.gwt.dev.js.ast.JsBreak;
import com.google.gwt.dev.js.ast.JsCase;
import com.google.gwt.dev.js.ast.JsCatch;
import com.google.gwt.dev.js.ast.JsConditional;
import com.google.gwt.dev.js.ast.JsContext;
import com.google.gwt.dev.js.ast.JsContinue;
import com.google.gwt.dev.js.ast.JsDebugger;
import com.google.gwt.dev.js.ast.JsDefault;
import com.google.gwt.dev.js.ast.JsDoWhile;
import com.google.gwt.dev.js.ast.JsEmpty;
import com.google.gwt.dev.js.ast.JsExprStmt;
import com.google.gwt.dev.js.ast.JsExpression;
import com.google.gwt.dev.js.ast.JsFor;
import com.google.gwt.dev.js.ast.JsFunction;
import com.google.gwt.dev.js.ast.JsIf;
import com.google.gwt.dev.js.ast.JsInvocation;
import com.google.gwt.dev.js.ast.JsLabel;
import com.google.gwt.dev.js.ast.JsModVisitor;
import com.google.gwt.dev.js.ast.JsName;
import com.google.gwt.dev.js.ast.JsNameOf;
import com.google.gwt.dev.js.ast.JsNameRef;
import com.google.gwt.dev.js.ast.JsNew;
import com.google.gwt.dev.js.ast.JsNode;
import com.google.gwt.dev.js.ast.JsNormalScope;
import com.google.gwt.dev.js.ast.JsNullLiteral;
import com.google.gwt.dev.js.ast.JsNumberLiteral;
import com.google.gwt.dev.js.ast.JsNumericEntry;
import com.google.gwt.dev.js.ast.JsObjectLiteral;
import com.google.gwt.dev.js.ast.JsParameter;
import com.google.gwt.dev.js.ast.JsPostfixOperation;
import com.google.gwt.dev.js.ast.JsPrefixOperation;
import com.google.gwt.dev.js.ast.JsProgram;
import com.google.gwt.dev.js.ast.JsPropertyInitializer;
import com.google.gwt.dev.js.ast.JsReturn;
import com.google.gwt.dev.js.ast.JsRootScope;
import com.google.gwt.dev.js.ast.JsScope;
import com.google.gwt.dev.js.ast.JsSeedIdOf;
import com.google.gwt.dev.js.ast.JsStatement;
import com.google.gwt.dev.js.ast.JsSwitch;
import com.google.gwt.dev.js.ast.JsSwitchMember;
import com.google.gwt.dev.js.ast.JsThisRef;
import com.google.gwt.dev.js.ast.JsThrow;
import com.google.gwt.dev.js.ast.JsTry;
import com.google.gwt.dev.js.ast.JsUnaryOperation;
import com.google.gwt.dev.js.ast.JsUnaryOperator;
import com.google.gwt.dev.js.ast.JsVars;
import com.google.gwt.dev.js.ast.JsVars.JsVar;
import com.google.gwt.dev.js.ast.JsWhile;
import com.google.gwt.dev.util.DefaultTextOutput;
import com.google.gwt.dev.util.Pair;
import com.google.gwt.dev.util.StringInterner;
import com.google.gwt.dev.util.TextOutput;
import com.google.gwt.dev.util.collect.IdentityHashSet;
import com.google.gwt.dev.util.collect.Maps;
import com.google.gwt.dev.util.collect.Lists;
import com.google.gwt.dev.util.collect.Sets;
import com.google.gwt.thirdparty.guava.common.collect.LinkedHashMultimap;
import com.google.gwt.thirdparty.guava.common.collect.Multimap;

import java.io.StringReader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.HashSet;
import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.Stack;
import java.util.TreeMap;

/**
 * Creates a JavaScript AST from a <code>JProgram</code> node.
 */
public class GenerateJavaScriptAST {

  /**
   * The GWT Java AST might contain different local variables with the same name in the same
   * scope. This fixup pass renames variables in the case they clash in a scope.
   */
  private static class FixNameClashesVisitor extends JVisitor {

    /**
     * Represents the scope tree defined by nested statement blocks. It is a temporary
     * structure to track local variable lifetimes.
     */
    private static class Scope {
      private Scope parent;

      // Keeps track what names are used in children.
      private Set<String> usedInChildScope = new HashSet<String>();

      // Keeps track what names have this scope as its lifetime.
      private Set<String> namesInThisScope = new HashSet<String>();

      /**
       * The depth at which this scope is in the tree.
       */
      private int level;

      private Scope() {
        this.parent = null;
        this.level = 0;
      }

      private Scope(Scope parent) {
        this.parent = parent;
        this.level = parent.level + 1;
      }

      private static Scope getInnermostEnclosingScope(Scope thisScope, Scope thatScope) {
        if (thisScope == null) {
          return thatScope;
        }

        if (thatScope == null) {
          return thisScope;
        }

        if (thisScope == thatScope) {
          return thisScope;
        }

        if (thisScope.level > thatScope.level) {
          return getInnermostEnclosingScope(thatScope, thisScope);
        }

        if (thisScope.level == thatScope.level) {
          return getInnermostEnclosingScope(thisScope.parent, thatScope.parent);
        }
        return getInnermostEnclosingScope(thisScope, thatScope.parent);
      }

      private void addChildUsage(String name) {
        usedInChildScope.add(name);
        if (parent != null) {
          parent.addChildUsage(name);
       }
      }

      protected void addUsedName(String name) {
        namesInThisScope.add(name);
        if (parent != null) {
          parent.addChildUsage(name);
        }
      }

      private boolean isUsedInParent(String name) {
        return namesInThisScope.contains(name) ||
            (parent != null && parent.isUsedInParent(name));
      }

      protected boolean isConflictingName(String name) {
        return usedInChildScope.contains(name) || isUsedInParent(name);
      }
    }

    private Scope currentScope;
    private Map<JLocal, Scope> scopesByLocal;
    private Multimap<String, JLocal> localsByName;

    @Override
    public boolean visit(JMethodBody x, Context ctx) {
      // Start constructing the scope tree.
      currentScope = new Scope();
      scopesByLocal = new HashMap<JLocal, Scope>();
      localsByName = LinkedHashMultimap.create();
      return true;
    }

    @Override
    public boolean visit(JBlock x, Context ctx) {
      currentScope = new Scope(currentScope);
      return true;
    }

    @Override
    public void endVisit(JBlock x, Context ctx) {
      currentScope = currentScope.parent;
    }

    @Override
    public void endVisit(JLocalRef x, Context ctx) {
      // We use the a block scope as a proxy for a lifetime which is safe to do albeit non optimal.
      //
      // Keep track of the scope that encloses a variable lifetime. E.g. assume the following code.
      // { // scope 1
      //   { // scope 1.1
      //     ... a... b...
      //     { // scope 1.1.1
      //        ... a ...
      //     }
      //   }
      //   { // scope 1.2
      //    ... b...
      //   }
      // }
      // Scope 1.1 is the innermost scope that encloses the lifetime of variable a and
      // scope 1 is the innermost scope that encloses the lifetime of variable b.
      JLocal local = x.getLocal();
      Scope oldVariableScope = scopesByLocal.get(local);
      Scope newVariableScope =  Scope.getInnermostEnclosingScope(oldVariableScope, currentScope);
      newVariableScope.addUsedName(local.getName());
      if (newVariableScope != oldVariableScope) {
        scopesByLocal.put(local, newVariableScope);
      }
      localsByName.put(local.getName(), local);
    }

    @Override
    public void endVisit(JMethodBody x, Context ctx) {
      // Fix clashing variables here.  Two locals are clashing if they have the same name and their
      // computed lifetimes are intersecting. By using the scope to model lifetimes two variables
      // clash if their computed scopes are nested.
      for (String name : localsByName.keySet()) {
        Collection<JLocal> localSet = localsByName.get(name);
        if (localSet.size() == 1) {
          continue;
        }

        JLocal[] locals = localSet.toArray(new JLocal[localSet.size()]);
        // TODO(rluble): remove n^2 behaviour in conflict checking.
        // In practice each method has only a handful of locals so this process is not expected
        // to be a performance problem.
        for (int i = 0; i < locals.length; i++ ) {
          // See if local i conflicts with any local j > i
          for (int j = i + 1; j < locals.length; j++ ) {
            Scope iLocalScope = scopesByLocal.get(locals[i]);
            Scope jLocalScope = scopesByLocal.get(locals[j]);
            Scope commonAncestor = Scope.getInnermostEnclosingScope(iLocalScope, jLocalScope);
            if (commonAncestor != iLocalScope && commonAncestor != jLocalScope) {
              // no conflict
              continue;
            }
            // conflicting locals => find a unique name rename local i to it;
            int n = 0;
            String baseName = locals[i].getName();
            String newName;
            do {
              // The active namer will clean up these potentially long names.
              newName = baseName + n++;
            } while (iLocalScope.isConflictingName(newName));
            locals[i].setName(newName);
            iLocalScope.addUsedName(newName);
            // There is no need to update the localsByNameMap as newNames are always guaranteed to
            // be clash free.
            break;
          }
        }
      }

      // Only valid for the duration of one method body visit/endVisit pair.
      currentScope = null;
      scopesByLocal = null;
      localsByName = null;
    }
  }

  private class CreateNamesAndScopesVisitor extends JVisitor {

    /**
     * Cache of computed Java source file names to URI strings for symbol
     * export. By using a cache we also ensure the miminum number of String
     * instances are serialized.
     */
    private final Map<String, String> fileNameToUriString = new HashMap<String, String>();

    private final Stack<JsScope> scopeStack = new Stack<JsScope>();


    @Override
    public void endVisit(JArrayType x, Context ctx) {
      JsName name = topScope.declareName(x.getName());
      names.put(x, name);
      recordSymbol(x, name);
    }

    @Override
    public void endVisit(JClassType x, Context ctx) {
      pop();
    }

    @Override
    public void endVisit(JsCastMap x, Context ctx) {
      /*
       * Intern JsCastMaps, at this stage, they are only present in Array initialization,
       * so we always intern them even if they occur once, since every array initialization
       * makes a copy.
       */
      internedCastMap.add(castMapToString(x));
    }

    @Override
    public void endVisit(JField x, Context ctx) {
      String name = x.getName();
      String mangleName = mangleName(x);
      if (x.isStatic()) {
        JsName jsName = topScope.declareName(mangleName, name);
        names.put(x, jsName);
        recordSymbol(x, jsName);
      } else {
        JsName jsName;
        if (specialObfuscatedFields.containsKey(x)) {
          jsName = peek().declareName(mangleNameSpecialObfuscate(x));
          jsName.setObfuscatable(false);
        } else {
          jsName = peek().declareName(mangleName, name);
        }
        names.put(x, jsName);
        recordSymbol(x, jsName);
      }
    }

    @Override
    public void endVisit(JInterfaceType x, Context ctx) {
      pop();
    }

    @Override
    public void endVisit(JLabel x, Context ctx) {
      if (names.get(x) != null) {
        return;
      }
      names.put(x, peek().declareName(x.getName()));
    }

    @Override
    public void endVisit(JLocal x, Context ctx) {
      // locals can conflict, that's okay just reuse the same variable
      JsScope scope = peek();
      JsName jsName = scope.declareName(x.getName());
      names.put(x, jsName);
    }

    @Override
    public void endVisit(JMethod x, Context ctx) {
      pop();
    }

    @Override
    public void endVisit(JParameter x, Context ctx) {
      names.put(x, peek().declareName(x.getName()));
    }

    @Override
    public void endVisit(JProgram x, Context ctx) {
      /*
       * put the null method and field into objectScope since they can be
       * referenced as instance on null-types (as determined by type flow)
       */
      JMethod nullMethod = x.getNullMethod();
      polymorphicNames.put(nullMethod, objectScope.declareName(nullMethod.getName()));
      JField nullField = x.getNullField();
      JsName nullFieldName = objectScope.declareName(nullField.getName());
      names.put(nullField, nullFieldName);

      /*
       * put nullMethod in the global scope, too; it's the replacer for clinits
       */
      nullFunc = createGlobalFunction("function " + nullMethod.getName() + "(){}");
      names.put(nullMethod, nullFunc.getName());

      /*
       * Create names for instantiable array types since JProgram.traverse()
       * doesn't iterate over them.
       */
      for (JArrayType arrayType : program.getAllArrayTypes()) {
        if (typeOracle.isInstantiatedType(arrayType)) {
          accept(arrayType);
        }
      }

      // Generate symbolic names for all query type ids.
      if (!output.shouldMinimize()) {
        setupSymbolicCastMaps();
      }
    }

    @Override
    public boolean visit(JClassType x, Context ctx) {
      // have I already been visited as a super type?
      JsScope myScope = classScopes.get(x);
      if (myScope != null) {
        push(myScope);
        return false;
      }

      // My seed function name
      JsName jsName = topScope.declareName(getNameString(x), x.getShortName());
      names.put(x, jsName);
      recordSymbol(x, jsName);

      // My class scope
      if (x.getSuperClass() == null) {
        myScope = objectScope;
      } else {
        JsScope parentScope = classScopes.get(x.getSuperClass());
        // Run my superclass first!
        if (parentScope == null) {
          accept(x.getSuperClass());
        }
        parentScope = classScopes.get(x.getSuperClass());
        assert (parentScope != null);
        /*
         * WEIRD: we wedge the global interface scope in between object and all
         * of its subclasses; this ensures that interface method names trump all
         * (except Object method names)
         */
        if (parentScope == objectScope) {
          parentScope = interfaceScope;
        }
        myScope = new JsNormalScope(parentScope, "class " + x.getShortName());
      }
      classScopes.put(x, myScope);

      push(myScope);
      return true;
    }

    @Override
    public boolean visit(JInterfaceType x, Context ctx) {
      // interfaces have no name at run time
      push(interfaceScope);
      return true;
    }

    @Override
    public boolean visit(JMethod x, Context ctx) {
      // my polymorphic name
      String name = x.getName();
      if (x.needsVtable()) {
        if (polymorphicNames.get(x) == null) {
          JsName polyName;
          if (x.isPrivate()) {
            polyName = interfaceScope.declareName(mangleNameForPrivatePoly(x), name);
          } else if (specialObfuscatedMethodSigs.containsKey(x.getSignature())) {
            polyName = interfaceScope.declareName(mangleNameSpecialObfuscate(x));
            polyName.setObfuscatable(false);
          } else {
            polyName = interfaceScope.declareName(mangleNameForPoly(x), name);
          }
          polymorphicNames.put(x, polyName);
        }
      }

      if (x.isAbstract()) {
        // just push a dummy scope that we can pop in endVisit
        push(null);
        return false;
      }

      // my global name
      JsName globalName = null;
      assert x.getEnclosingType() != null;
      String mangleName = mangleNameForGlobal(x);

      if (JProgram.isClinit(x)) {
        name = name + "_" + x.getEnclosingType().getShortName();
      }

      /*
       * Only allocate a name for a function if it is native, not polymorphic,
       * or stack-stripping is disabled.
       */
      if (!stripStack || !polymorphicNames.containsKey(x) || x.isNative()) {
        globalName = topScope.declareName(mangleName, name);
        names.put(x, globalName);
        recordSymbol(x, globalName);
      }
      JsFunction jsFunction;
      if (x.isNative()) {
        // set the global name of the JSNI peer
        JsniMethodBody body = (JsniMethodBody) x.getBody();
        jsFunction = body.getFunc();
        jsFunction.setName(globalName);
      } else {
        /*
         * It would be more correct here to check for an inline assignment, such
         * as var foo = function blah() {} and introduce a separate scope for
         * the function's name according to EcmaScript-262, but this would mess
         * up stack traces by allowing two inner scope function names to
         * obfuscate to the same identifier, making function names no longer a
         * 1:1 mapping to obfuscated symbols. Leaving them in global scope
         * causes no harm.
         */
        jsFunction = new JsFunction(x.getSourceInfo(), topScope, globalName, true);
      }
      if (polymorphicNames.containsKey(x)) {
        polymorphicJsFunctions.add(jsFunction);
      }
      methodBodyMap.put(x.getBody(), jsFunction);
      push(jsFunction.getScope());

      if (program.getIndexedMethods().contains(x)) {
        indexedFunctions =
            Maps.put(indexedFunctions, x.getEnclosingType().getShortName() + "." + x.getName(),
                jsFunction);
      }

      return true;
    }

    @Override
    public boolean visit(JTryStatement x, Context ctx) {
      accept(x.getTryBlock());
      for (JTryStatement.CatchClause clause : x.getCatchClauses()) {
        JLocalRef arg = clause.getArg();
        JBlock catchBlock = clause.getBlock();
        JsCatch jsCatch = new JsCatch(x.getSourceInfo(), peek(), arg.getTarget().getName());
        JsParameter jsParam = jsCatch.getParameter();
        names.put(arg.getTarget(), jsParam.getName());
        catchMap.put(catchBlock, jsCatch);
        catchParamIdentifiers.add(jsParam.getName());

        push(jsCatch.getScope());
        accept(catchBlock);
        pop();
      }

      // TODO: normalize this so it's never null?
      if (x.getFinallyBlock() != null) {
        accept(x.getFinallyBlock());
      }
      return false;
    }

    private JsFunction createGlobalFunction(String code) {
      try {
        List<JsStatement> stmts =
            JsParser.parse(SourceOrigin.UNKNOWN, topScope, new StringReader(code));
        assert stmts.size() == 1;
        JsExprStmt stmt = (JsExprStmt) stmts.get(0);
        List<JsStatement> globalStmts = jsProgram.getGlobalBlock().getStatements();
        globalStmts.add(0, stmt);
        return (JsFunction) stmt.getExpression();
      } catch (Exception e) {
        throw new InternalCompilerException("Unexpected exception parsing '" + code + "'", e);
      }
    }

    /**
     * Generate a file name URI string for a source info, for symbol data
     * export.
     */
    private String makeUriString(HasSourceInfo x) {
      String fileName = x.getSourceInfo().getFileName();
      if (fileName == null) {
        return null;
      }
      String uriString = fileNameToUriString.get(fileName);
      if (uriString == null) {
        uriString = StandardSymbolData.toUriString(fileName);
        fileNameToUriString.put(fileName, uriString);
      }
      return uriString;
    }

    private JsScope peek() {
      return scopeStack.peek();
    }

    private void pop() {
      scopeStack.pop();
    }

    private void push(JsScope scope) {
      scopeStack.push(scope);
    }

    private void recordSymbol(JReferenceType x, JsName jsName) {
      StringBuilder sb = new StringBuilder();
      sb.append('{');
      JsCastMap castMap = program.getCastMap(x);
      if (castMap != null) {
        boolean isFirst = true;
        for (JExpression expr : castMap.getExprs()) {
          JsQueryType queryType = (JsQueryType) expr;
          if (isFirst) {
            isFirst = false;
          } else {
            sb.append(',');
          }
          sb.append(queryType.getQueryId());
          sb.append(":1");
        }
      }
      sb.append('}');
      CastableTypeMap castableTypeMap = new StandardCastableTypeMap(sb.toString());

      StandardSymbolData symbolData =
          StandardSymbolData.forClass(x.getName(), x.getSourceInfo().getFileName(), x
              .getSourceInfo().getStartLine(), program.getQueryId(x), castableTypeMap,
              x instanceof JClassType || x instanceof JArrayType ? getSeedId(x) : -1);
      assert !symbolTable.containsKey(symbolData);
      symbolTable.put(symbolData, jsName);
    }

    private <T extends HasEnclosingType & HasName & HasSourceInfo> void recordSymbol(T x,
        JsName jsName) {
      /*
       * NB: The use of x.getName() can produce confusion in cases where a type
       * has both polymorphic and static dispatch for a method, because you
       * might see HashSet::$add() and HashSet::add(). Logically, these methods
       * should be treated equally, however they will be implemented with
       * separate global functions and must be recorded independently.
       * 
       * Automated systems that process the symbol information can easily map
       * the statically-dispatched function by looking for method names that
       * begin with a dollar-sign and whose first parameter is the enclosing
       * type.
       */

      String methodSig;
      if (x instanceof JMethod) {
        StringBuilder sb = new StringBuilder();
        sb.append('(');
        JMethod method = ((JMethod) x);
        for (JType t : method.getOriginalParamTypes()) {
          sb.append(t.getJsniSignatureName());
        }
        sb.append(')');
        sb.append(method.getOriginalReturnType().getJsniSignatureName());
        methodSig = StringInterner.get().intern(sb.toString());
      } else {
        methodSig = null;
      }

      StandardSymbolData symbolData =
          StandardSymbolData.forMember(x.getEnclosingType().getName(), x.getName(), methodSig,
              makeUriString(x), x.getSourceInfo().getStartLine());
      assert !symbolTable.containsKey(symbolData) : "Duplicate symbol " + "recorded "
          + jsName.getIdent() + " for " + x.getName() + " and key " + symbolData.getJsniIdent();
      symbolTable.put(symbolData, jsName);
    }

    /**
     * Create more readable output by generating symbolic constants for query
     * ids.
     */
    private void setupSymbolicCastMaps() {
      namesByQueryId = new ArrayList<JsName>();

      for (JReferenceType type : program.getTypesByQueryId()) {
        String shortName;
        String longName;
        if (type instanceof JArrayType) {
          JArrayType arrayType = (JArrayType) type;
          JType leafType = arrayType.getLeafType();
          if (leafType instanceof JReferenceType) {
            shortName = ((JReferenceType) leafType).getShortName();
          } else {
            shortName = leafType.getName();
          }
          shortName += "_$" + arrayType.getDims();
          longName = getNameString(leafType) + "_$" + arrayType.getDims();
        } else {
          shortName = type.getShortName();
          longName = getNameString(type);
        }
        JsName name = topScope.declareName("Q$" + longName, "Q$" + shortName);
        namesByQueryId.add(name);
      }
      // TODO(cromwellian): see about moving this into an immortal type
      StringBuilder sb = new StringBuilder();
      sb.append("function makeCastMap(a) {");
      sb.append("  var result = {};");
      sb.append("  for (var i = 0, c = a.length; i < c; ++i) {");
      sb.append("    result[a[i]] = 1;");
      sb.append("  }");
      sb.append("  return result;");
      sb.append("}");
      makeMapFunction = createGlobalFunction(sb.toString());
    }
  }

  private class GenerateJavaScriptVisitor extends GenerateJavaScriptLiterals {

    private final Set<JClassType> alreadyRan = new HashSet<JClassType>();

    private final JsName arrayLength = objectScope.declareName("length");

    private final Set<String> castMapSeen = new HashSet<String>();

    private final Map<JClassType, JsFunction> clinitMap = new HashMap<JClassType, JsFunction>();

    private JMethod currentMethod = null;

    /**
     * The JavaScript functions corresponding to the entry methods of the
     * program ({@link JProgram#getEntryMethods()}).
     */
    private JsFunction[] entryFunctions;

    /**
     * A reverse index for the entry methods of the program (
     * {@link JProgram#getEntryMethods()}). Each entry method is mapped to its
     * integer index.
     */
    private Map<JMethod, Integer> entryMethodToIndex;

    private final JsName globalTemp = topScope.declareName("_");

    private final JsName prototype = objectScope.declareName("prototype");

    // Methods where inlining hasn't happened yet because they are native or
    // contain calls to native methods.
    Set<JMethod> methodsForJsInlining = new HashSet<JMethod>();

    // JavaScript functions that arise from methods that were not inlined in the Java AST
    // NOTE: We use a LinkedHashSet to preserve the order of insertion. So that the following passes
    // that use this result are deterministic.
    private final Set<JsNode> functionsForJsInlining = new LinkedHashSet<JsNode>();

    {
      globalTemp.setObfuscatable(false);
      prototype.setObfuscatable(false);
      arrayLength.setObfuscatable(false);
    }

    public GenerateJavaScriptVisitor(Set<JMethod> methodsForJsInlining) {
      this.methodsForJsInlining = methodsForJsInlining;
    }
    
    @Override
    public void endVisit(JAbsentArrayDimension x, Context ctx) {
      throw new InternalCompilerException("Should not get here.");
    }

    @Override
    public void endVisit(JArrayLength x, Context ctx) {
      assert x.getInstance() != null : "Can't access the length of a null array";
      JsExpression qualifier = (JsExpression) pop();
      JsNameRef ref = arrayLength.makeRef(x.getSourceInfo());
      ref.setQualifier(qualifier);
      push(ref);
    }

    @Override
    public void endVisit(JArrayRef x, Context ctx) {
      JsArrayAccess jsArrayAccess = new JsArrayAccess(x.getSourceInfo());
      jsArrayAccess.setIndexExpr((JsExpression) pop());
      jsArrayAccess.setArrayExpr((JsExpression) pop());
      push(jsArrayAccess);
    }

    @Override
    public void endVisit(JAssertStatement x, Context ctx) {
      throw new InternalCompilerException("Should not get here.");
    }

    @Override
    public void endVisit(JBinaryOperation x, Context ctx) {
      JsExpression rhs = (JsExpression) pop(); // rhs
      JsExpression lhs = (JsExpression) pop(); // lhs
      JsBinaryOperator myOp = JavaToJsOperatorMap.get(x.getOp());

      /*
       * Use === and !== on reference types, or else you can get wrong answers
       * when Object.toString() == 'some string'.
       */
      if (myOp == JsBinaryOperator.EQ && x.getLhs().getType() instanceof JReferenceType
          && x.getRhs().getType() instanceof JReferenceType) {
        myOp = JsBinaryOperator.REF_EQ;
      } else if (myOp == JsBinaryOperator.NEQ && x.getLhs().getType() instanceof JReferenceType
          && x.getRhs().getType() instanceof JReferenceType) {
        myOp = JsBinaryOperator.REF_NEQ;
      }

      push(new JsBinaryOperation(x.getSourceInfo(), myOp, lhs, rhs));
    }

    @Override
    public void endVisit(JBlock x, Context ctx) {
      JsBlock jsBlock = new JsBlock(x.getSourceInfo());
      List<JsStatement> stmts = jsBlock.getStatements();
      popList(stmts, x.getStatements().size()); // stmts
      Iterator<JsStatement> iterator = stmts.iterator();
      while (iterator.hasNext()) {
        JsStatement stmt = iterator.next();
        if (stmt instanceof JsEmpty) {
          iterator.remove();
        }
      }
      push(jsBlock);
    }

    @Override
    public void endVisit(JBreakStatement x, Context ctx) {
      JsNameRef labelRef = null;
      if (x.getLabel() != null) {
        JsLabel label = (JsLabel) pop(); // label
        labelRef = label.getName().makeRef(x.getSourceInfo());
      }
      push(new JsBreak(x.getSourceInfo(), labelRef));
    }

    @Override
    public void endVisit(JCaseStatement x, Context ctx) {
      if (x.getExpr() == null) {
        push(new JsDefault(x.getSourceInfo()));
      } else {
        JsCase jsCase = new JsCase(x.getSourceInfo());
        jsCase.setCaseExpr((JsExpression) pop()); // expr
        push(jsCase);
      }
    }

    @Override
    public void endVisit(JCastOperation x, Context ctx) {
      // These are left in when cast checking is disabled.
    }

    @Override
    public void endVisit(JClassLiteral x, Context ctx) {
      JsName classLit = names.get(x.getField());
      push(classLit.makeRef(x.getSourceInfo()));
    }

    @Override
    public void endVisit(JClassType x, Context ctx) {
      if (alreadyRan.contains(x)) {
        return;
      }

      if (program.getTypeClassLiteralHolder() == x) {
        // Handled in generateClassLiterals.
        return;
      }

      if (program.immortalCodeGenTypes.contains(x)) {
        // Handled in generateImmortalTypes
        return;
      }

      alreadyRan.add(x);

      List<JsFunction> jsFuncs = popList(x.getMethods().size()); // methods
      List<JsNode> jsFields = popList(x.getFields().size()); // fields

      if (x.getClinitTarget() == x) {
        JsFunction superClinit = clinitMap.get(x.getSuperClass());
        JsFunction myClinit = jsFuncs.get(0);
        handleClinit(myClinit, superClinit);
        clinitMap.put(x, myClinit);
      } else {
        jsFuncs.set(0, null);
      }

      List<JsStatement> globalStmts = jsProgram.getGlobalBlock().getStatements();

      // declare all methods into the global scope
      for (int i = 0; i < jsFuncs.size(); ++i) {
        JsFunction func = jsFuncs.get(i);

        // don't add polymorphic JsFuncs, inline decl into vtable assignment
        if (func != null && !polymorphicJsFunctions.contains(func)) {
          globalStmts.add(func.makeStmt());
        }
      }

      if (typeOracle.isInstantiatedType(x) && !program.isJavaScriptObject(x)) {
        generateClassSetup(x, globalStmts);
      }

      // setup fields
      JsVars vars = new JsVars(x.getSourceInfo());
      for (int i = 0; i < jsFields.size(); ++i) {
        JsNode node = jsFields.get(i);
        if (node instanceof JsVar) {
          vars.add((JsVar) node);
        } else {
          assert (node instanceof JsStatement);
          JsStatement stmt = (JsStatement) node;
          globalStmts.add(stmt);
          typeForStatMap.put(stmt, x);
        }
      }

      if (!vars.isEmpty()) {
        globalStmts.add(vars);
      }

      for (JNode node : x.getArtificialRescues()) {
        if (node instanceof JMethod) {
          JsName jsName = names.get(node);
          if (jsName != null) {
            JsFunction func = (JsFunction) jsName.getStaticRef();
            func.setArtificiallyRescued(true);
          }
        }
      }
      
      // TODO(zundel): Check that each unique method has a unique
      // name / poly name.
    }

    @Override
    public void endVisit(JConditional x, Context ctx) {
      JsExpression elseExpr = (JsExpression) pop(); // elseExpr
      JsExpression thenExpr = (JsExpression) pop(); // thenExpr
      JsExpression ifTest = (JsExpression) pop(); // ifTest
      push(new JsConditional(x.getSourceInfo(), ifTest, thenExpr, elseExpr));
    }

    @Override
    public void endVisit(JContinueStatement x, Context ctx) {
      JsNameRef labelRef = null;
      if (x.getLabel() != null) {
        JsLabel label = (JsLabel) pop(); // label
        labelRef = label.getName().makeRef(x.getSourceInfo());
      }
      push(new JsContinue(x.getSourceInfo(), labelRef));
    }

    @Override
    public void endVisit(JDebuggerStatement x, Context ctx) {
      push(new JsDebugger(x.getSourceInfo()));
    }

    @Override
    public void endVisit(JDeclarationStatement x, Context ctx) {
      if (x.getInitializer() == null) {
        pop(); // variableRef
        /*
         * Declaration statements can only appear in blocks, so it's okay to
         * push null instead of an empty statement
         */
        push(null);
        return;
      }

      JsExpression initializer = (JsExpression) pop(); // initializer
      JsNameRef localRef = (JsNameRef) pop(); // localRef

      JVariable target = x.getVariableRef().getTarget();
      if (target instanceof JField) {
        JField field = (JField) target;
        if (initializeAtTopScope(field)) {
          // Will initialize at top scope; no need to double-initialize.
          push(null);
          return;
        }
      }

      JsBinaryOperation binOp =
          new JsBinaryOperation(x.getSourceInfo(), JsBinaryOperator.ASG, localRef, initializer);

      push(binOp.makeStmt());
    }

    @Override
    public void endVisit(JDoStatement x, Context ctx) {
      JsDoWhile stmt = new JsDoWhile(x.getSourceInfo());
      if (x.getBody() != null) {
        stmt.setBody((JsStatement) pop()); // body
      } else {
        stmt.setBody(new JsEmpty(x.getSourceInfo()));
      }
      stmt.setCondition((JsExpression) pop()); // testExpr
      push(stmt);
    }

    @Override
    public void endVisit(JExpressionStatement x, Context ctx) {
      JsExpression expr = (JsExpression) pop(); // expr
      push(expr.makeStmt());
    }

    @Override
    public void endVisit(JField x, Context ctx) {
      // if we need an initial value, create an assignment
      if (initializeAtTopScope(x)) {
        // setup the constant value
        accept(x.getLiteralInitializer());
      } else if (x.getEnclosingType() == program.getTypeJavaLangObject()) {
        // Special fields whose initialization is done somewhere else.
        push(null);
      } else if (x.getType().getDefaultValue() == JNullLiteral.INSTANCE) {
        // Fields whose default value is null are left uninitialized and will
        // have a JS value of undefined.
        push(null);
      } else {
        // setup the default value, see Issue 380
        accept(x.getType().getDefaultValue());
      }
      JsExpression rhs = (JsExpression) pop();
      JsName name = names.get(x);

      if (program.getIndexedFields().contains(x)) {
        indexedFields =
            Maps.put(indexedFields, x.getEnclosingType().getShortName() + "." + x.getName(), name);
      }

      if (x.isStatic()) {
        // setup a var for the static
        JsVar var = new JsVar(x.getSourceInfo(), name);
        var.setInitExpr(rhs);
        push(var);
      } else {
        // for non-statics, only setup an assignment if needed
        if (rhs != null) {
          JsNameRef fieldRef = name.makeRef(x.getSourceInfo());
          fieldRef.setQualifier(globalTemp.makeRef(x.getSourceInfo()));
          JsExpression asg = createAssignment(fieldRef, rhs);
          push(new JsExprStmt(x.getSourceInfo(), asg));
        } else {
          push(null);
        }
      }
    }

    @Override
    public void endVisit(JFieldRef x, Context ctx) {
      JField field = x.getField();
      JsName jsFieldName = names.get(field);
      JsNameRef nameRef = jsFieldName.makeRef(x.getSourceInfo());
      JsExpression curExpr = nameRef;

      /*
       * Note: the comma expressions here would cause an illegal tree state if
       * the result expression ended up on the lhs of an assignment. A hack in
       * in endVisit(JBinaryOperation) rectifies the situation.
       */

      // See if we need a clinit
      JsInvocation jsInvocation = maybeCreateClinitCall(field);
      if (jsInvocation != null) {
        curExpr = createCommaExpression(jsInvocation, curExpr);
      }

      if (x.getInstance() != null) {
        JsExpression qualifier = (JsExpression) pop();
        if (field.isStatic()) {
          // unnecessary qualifier, create a comma expression
          curExpr = createCommaExpression(qualifier, curExpr);
        } else {
          // necessary qualifier, qualify the name ref
          nameRef.setQualifier(qualifier);
        }
      }

      push(curExpr);
    }

    @Override
    public void endVisit(JForStatement x, Context ctx) {
      JsFor jsFor = new JsFor(x.getSourceInfo());

      // body
      if (x.getBody() != null) {
        jsFor.setBody((JsStatement) pop());
      } else {
        jsFor.setBody(new JsEmpty(x.getSourceInfo()));
      }

      // increments
      if (x.getIncrements() != null) {
        jsFor.setIncrExpr((JsExpression) pop());
      }

      // condition
      if (x.getCondition() != null) {
        jsFor.setCondition((JsExpression) pop());
      }

      // initializers
      JsExpression initExpr = null;
      List<JsExprStmt> initStmts = popList(x.getInitializers().size());
      for (int i = 0; i < initStmts.size(); ++i) {
        JsExprStmt initStmt = initStmts.get(i);
        if (initStmt != null) {
          initExpr = createCommaExpression(initExpr, initStmt.getExpression());
        }
      }
      jsFor.setInitExpr(initExpr);

      push(jsFor);
    }

    @Override
    public void endVisit(JGwtCreate x, Context ctx) {
      throw new InternalCompilerException("Should not get here.");
    }

    @Override
    public void endVisit(JIfStatement x, Context ctx) {
      JsIf stmt = new JsIf(x.getSourceInfo());

      if (x.getElseStmt() != null) {
        stmt.setElseStmt((JsStatement) pop()); // elseStmt
      }

      if (x.getThenStmt() != null) {
        stmt.setThenStmt((JsStatement) pop()); // thenStmt
      } else {
        stmt.setThenStmt(new JsEmpty(x.getSourceInfo()));
      }

      stmt.setIfExpr((JsExpression) pop()); // ifExpr
      push(stmt);
    }

    @Override
    public void endVisit(JInstanceOf x, Context ctx) {
      throw new InternalCompilerException("Should not get here.");
    }

    @Override
    public void endVisit(JInterfaceType x, Context ctx) {
      List<JsFunction> jsFuncs = popList(x.getMethods().size()); // methods
      List<JsVar> jsFields = popList(x.getFields().size()); // fields
      List<JsStatement> globalStmts = jsProgram.getGlobalBlock().getStatements();

      if (x.getClinitTarget() == x) {
        JsFunction clinitFunc = jsFuncs.get(0);
        handleClinit(clinitFunc, null);
        globalStmts.add(clinitFunc.makeStmt());
      }

      // setup fields
      JsVars vars = new JsVars(x.getSourceInfo());
      for (int i = 0; i < jsFields.size(); ++i) {
        vars.add(jsFields.get(i));
      }
      if (!vars.isEmpty()) {
        globalStmts.add(vars);
      }
    }

    @Override
    public void endVisit(JLabel x, Context ctx) {
      push(new JsLabel(x.getSourceInfo(), names.get(x)));
    }

    @Override
    public void endVisit(JLabeledStatement x, Context ctx) {
      JsStatement body = (JsStatement) pop(); // body
      JsLabel label = (JsLabel) pop(); // label
      label.setStmt(body);
      push(label);
    }

    @Override
    public void endVisit(JLocal x, Context ctx) {
      push(names.get(x).makeRef(x.getSourceInfo()));
    }

    @Override
    public void endVisit(JLocalRef x, Context ctx) {
      push(names.get(x.getTarget()).makeRef(x.getSourceInfo()));
    }

    @Override
    public void endVisit(JLongLiteral x, Context ctx) {
      super.endVisit(x, ctx);
      JsExpression longLiteralAllocation = pop();

      // My seed function name
      String nameString = Long.toString(x.getValue(), 16);
      if (nameString.charAt(0) == '-') {
        nameString = "N" + nameString.substring(1);
      } else {
        nameString = "P" + nameString;
      }
      nameString += "_longLit";
      JsName longLit = topScope.declareName(nameString);
      longLits.put(x.getValue(), longLit);
      longObjects.put(longLit, longLiteralAllocation);
      push(longLit.makeRef(x.getSourceInfo()));
    }

    @Override
    public void endVisit(JMethod x, Context ctx) {
      if (x.isAbstract()) {
        push(null);
        return;
      }

      JsFunction jsFunc = (JsFunction) pop(); // body

      // Collect the resulting function to be considered by the JsInliner.
      if (methodsForJsInlining.contains(x)) {
        functionsForJsInlining.add(jsFunc);
      }

      List<JsParameter> params = popList(x.getParams().size()); // params

      if (!x.isNative()) {
        // Setup params on the generated function. A native method already got
        // its jsParams set in BuildTypeMap.
        // TODO: Do we really need to do that in BuildTypeMap?
        List<JsParameter> jsParams = jsFunc.getParameters();
        for (int i = 0; i < params.size(); ++i) {
          JsParameter param = params.get(i);
          jsParams.add(param);
        }
      }

      JsInvocation jsInvocation = maybeCreateClinitCall(x);
      if (jsInvocation != null) {
        jsFunc.getBody().getStatements().add(0, jsInvocation.makeStmt());
      }

      if (x.isTrace()) {
        jsFunc.setTrace();
      }

      push(jsFunc);
      Integer entryIndex = entryMethodToIndex.get(x);
      if (entryIndex != null) {
        entryFunctions[entryIndex] = jsFunc;
      }
      currentMethod = null;
    }

    @Override
    public void endVisit(JMethodBody x, Context ctx) {

      JsBlock body = (JsBlock) pop();
      List<JsNameRef> locals = popList(x.getLocals().size()); // locals

      JsFunction jsFunc = methodBodyMap.get(x);
      jsFunc.setBody(body); // body

      /*
       * Emit a statement to declare the method's complete set of local
       * variables. JavaScript doesn't have the same concept of lexical scoping
       * as Java, so it's okay to just predeclare all local vars at the top of
       * the function, which saves us having to use the "var" keyword over and
       * over.
       * 
       * Note: it's fine to use the same JS ident to represent two different
       * Java locals of the same name since they could never conflict with each
       * other in Java. We use the alreadySeen set to make sure we don't declare
       * the same-named local var twice.
       */
      JsVars vars = new JsVars(x.getSourceInfo());
      Set<String> alreadySeen = new HashSet<String>();
      for (int i = 0; i < locals.size(); ++i) {
        JsName name = names.get(x.getLocals().get(i));
        String ident = name.getIdent();
        if (!alreadySeen.contains(ident)
            // Catch block params don't need var declarations
            && !catchParamIdentifiers.contains(name)) {
          alreadySeen.add(ident);
          vars.add(new JsVar(x.getSourceInfo(), name));
        }
      }

      if (!vars.isEmpty()) {
        jsFunc.getBody().getStatements().add(0, vars);
      }

      push(jsFunc);
    }

    @Override
    public void endVisit(JMethodCall x, Context ctx) {
      JMethod method = x.getTarget();
      JsInvocation jsInvocation = new JsInvocation(x.getSourceInfo());

      popList(jsInvocation.getArguments(), x.getArgs().size()); // args

      if (JProgram.isClinit(method)) {
        /*
         * It is possible for clinits to be referenced here that have actually
         * been retargeted (see {@link
         * JTypeOracle.recomputeAfterOptimizations}). Most of the time, these
         * will get cleaned up by other optimization passes prior to this point,
         * but it's not guaranteed. In this case we need to replace the method
         * call with the replaced clinit, unless the replacement is null, in
         * which case we generate a JsNullLiteral as a place-holder expression.
         */
        JDeclaredType type = method.getEnclosingType();
        JDeclaredType clinitTarget = type.getClinitTarget();
        if (clinitTarget == null) {
          if (x.getInstance() != null) {
            pop(); // instance
          }
          // generate a null expression, which will get optimized out
          push(JsNullLiteral.INSTANCE);
          return;
        } else if (type != clinitTarget) {
          // replace the method with its retargeted clinit
          method = clinitTarget.getClinitMethod();
        }
      }

      JsNameRef qualifier;
      JsExpression unnecessaryQualifier = null;
      if (method.isStatic()) {
        if (x.getInstance() != null) {
          unnecessaryQualifier = (JsExpression) pop(); // instance
        }
        qualifier = names.get(method).makeRef(x.getSourceInfo());
      } else {
        if (x.isStaticDispatchOnly()) {
          /*
           * Dispatch statically (odd case). This happens when a call that must
           * be static is targeting an instance method that could not be
           * transformed into a static. Super/this constructor calls work this
           * way. Have to use a "call" construct.
           */
          JsName callName = objectScope.declareName("call");
          callName.setObfuscatable(false);
          qualifier = callName.makeRef(x.getSourceInfo());
          qualifier.setQualifier(names.get(method).makeRef(x.getSourceInfo()));
          jsInvocation.getArguments().add(0, (JsExpression) pop()); // instance
        } else {
          // Dispatch polymorphically (normal case).
          qualifier = polymorphicNames.get(method).makeRef(x.getSourceInfo());
          qualifier.setQualifier((JsExpression) pop()); // instance
        }
      }
      jsInvocation.setQualifier(qualifier);
      push(createCommaExpression(unnecessaryQualifier, jsInvocation));
    }

    @Override
    public void endVisit(JMultiExpression x, Context ctx) {
      List<JsExpression> exprs = popList(x.getNumberOfExpressions());
      JsExpression cur = null;
      for (int i = 0; i < exprs.size(); ++i) {
        JsExpression next = exprs.get(i);
        cur = createCommaExpression(cur, next);
      }
      if (cur == null) {
        // the multi-expression was empty; use undefined
        cur = new JsNameRef(x.getSourceInfo(), JsRootScope.INSTANCE.getUndefined());
      }
      push(cur);
    }

    @Override
    public void endVisit(JNameOf x, Context ctx) {
      JsName name = names.get(x.getNode());
      assert name != null : "Missing JsName for " + x.getNode().getName();
      push(new JsNameOf(x.getSourceInfo(), name));
    }

    @Override
    public void endVisit(JNewArray x, Context ctx) {
      throw new InternalCompilerException("Should not get here.");
    }

    @Override
    public void endVisit(JNewInstance x, Context ctx) {
      JsNameRef nameRef = names.get(x.getTarget()).makeRef(x.getSourceInfo());
      JsNew newOp = new JsNew(x.getSourceInfo(), nameRef);
      popList(newOp.getArguments(), x.getArgs().size()); // args
      push(newOp);
    }
    
    @Override
    public void endVisit(JNumericEntry x, Context ctx) {
      push(new JsNumericEntry(x.getSourceInfo(), x.getKey(), x.getValue()));
    }
    
    @Override
    public void endVisit(JParameter x, Context ctx) {
      push(new JsParameter(x.getSourceInfo(), names.get(x)));
    }

    @Override
    public void endVisit(JParameterRef x, Context ctx) {
      push(names.get(x.getTarget()).makeRef(x.getSourceInfo()));
    }

    @Override
    public void endVisit(JPostfixOperation x, Context ctx) {
      JsUnaryOperation op =
          new JsPostfixOperation(x.getSourceInfo(), JavaToJsOperatorMap.get(x.getOp()),
              ((JsExpression) pop())); // arg
      push(op);
    }

    @Override
    public void endVisit(JPrefixOperation x, Context ctx) {
      JsUnaryOperation op =
          new JsPrefixOperation(x.getSourceInfo(), JavaToJsOperatorMap.get(x.getOp()),
              ((JsExpression) pop())); // arg
      push(op);
    }

    @Override
    public void endVisit(JProgram x, Context ctx) {
      List<JsStatement> globalStmts = jsProgram.getGlobalBlock().getStatements();

      // Generate entry methods
      generateGwtOnLoad(Lists.create(entryFunctions), globalStmts);

      // Add a few things onto the beginning.

      // Reserve the "_" identifier.
      JsVars vars = new JsVars(jsProgram.getSourceInfo());
      vars.add(new JsVar(jsProgram.getSourceInfo(), globalTemp));
      globalStmts.add(0, vars);

      // Long lits must go at the top, they can be constant field initializers.
      generateLongLiterals(vars);
      generateImmortalTypes(vars);
      generateQueryIdConstants(vars);
      generateInternedCastMapLiterals(vars);
     
      // Class objects, but only if there are any.
      if (x.getDeclaredTypes().contains(x.getTypeClassLiteralHolder())) {
        // TODO: perhaps they could be constant field initializers also?
        vars = new JsVars(jsProgram.getSourceInfo());
        generateClassLiterals(vars);
        if (!vars.isEmpty()) {
          globalStmts.add(vars);
        }
      }

      if (program.getRunAsyncs().size() > 0) {
        // Prevent onLoad from being pruned.
        JMethod onLoadMethod = program.getIndexedMethod("AsyncFragmentLoader.onLoad");
        JsName name = names.get(onLoadMethod);
        assert name != null;
        JsFunction func = (JsFunction) name.getStaticRef();
        func.setArtificiallyRescued(true);
      }
    }

    @Override
    public void endVisit(JReboundEntryPoint x, Context ctx) {
      throw new InternalCompilerException("Should not get here.");
    }

    @Override
    public void endVisit(JReturnStatement x, Context ctx) {
      if (x.getExpr() != null) {
        push(new JsReturn(x.getSourceInfo(), (JsExpression) pop())); // expr
      } else {
        push(new JsReturn(x.getSourceInfo()));
      }
    }

    @Override
    public void endVisit(JSeedIdOf x, Context ctx) {
      JsName name = names.get(x.getNode());
      push(new JsSeedIdOf(x.getSourceInfo(), name, getSeedId((JReferenceType) x.getNode())));
    }

    @Override
    public void endVisit(JsCastMap x, Context ctx) {
      super.endVisit(x, ctx);
      JsArrayLiteral arrayLit = (JsArrayLiteral) pop();
      SourceInfo sourceInfo = x.getSourceInfo();
      if (namesByQueryId == null || x.getExprs().size() == 0) {
        String stringMap = castMapToString(x);
        // if interned, use variable reference
        if (namesByCastMap.containsKey(stringMap)) {
          push(namesByCastMap.get(stringMap).makeRef(x.getSourceInfo()));
        } else if (internedCastMap.contains(stringMap)) {
          // interned variable hasn't been created yet
          String internName = "CM$";
          boolean first = true;
          for (JExpression expr : x.getExprs()) {
            if (first) {
              first = false;
            } else {
              internName += "_";
            }
            // Name is CM$queryId_queryId_queryId
            internName += ((JsQueryType) expr).getQueryId();
          }
          JsName internedCastMapName = topScope.declareName(internName, internName);
          namesByCastMap.put(stringMap, internedCastMapName);
          castMapByString.put(stringMap, castMapToObjectLiteral(arrayLit, sourceInfo));
          push(internedCastMapName.makeRef(x.getSourceInfo()));
        } else {
          push(castMapToObjectLiteral(arrayLit, sourceInfo));
        }
      } else {
        // makeMap([Q_Object, Q_Foo, Q_Bar]);
        JsInvocation inv = new JsInvocation(sourceInfo);
        inv.setQualifier(makeMapFunction.getName().makeRef(sourceInfo));
        inv.getArguments().add(arrayLit);
        push(inv);
      }
    }

    @Override
    public void endVisit(JsniMethodRef x, Context ctx) {
      JMethod method = x.getTarget();
      JsNameRef nameRef = names.get(method).makeRef(x.getSourceInfo());
      push(nameRef);
    }

    @Override
    public void endVisit(JsonArray x, Context ctx) {
      JsArrayLiteral jsArrayLiteral = new JsArrayLiteral(x.getSourceInfo());
      popList(jsArrayLiteral.getExpressions(), x.getExprs().size());
      push(jsArrayLiteral);
    }

    @Override
    public void endVisit(JsonObject x, Context ctx) {
      JsObjectLiteral jsObjectLiteral = new JsObjectLiteral(x.getSourceInfo());
      popList(jsObjectLiteral.getPropertyInitializers(), x.propInits.size());
      push(jsObjectLiteral);
    }

    @Override
    public void endVisit(JsonPropInit init, Context ctx) {
      JsExpression valueExpr = (JsExpression) pop();
      JsExpression labelExpr = (JsExpression) pop();
      push(new JsPropertyInitializer(init.getSourceInfo(), labelExpr, valueExpr));
    }

    @Override
    public void endVisit(JsQueryType x, Context ctx) {
      if (namesByQueryId == null || x.getQueryId() < 0) {
        super.endVisit(x, ctx);
      } else {
        JsName name = namesByQueryId.get(x.getQueryId());
        push(name.makeRef(x.getSourceInfo()));
      }
    }

    @Override
    public void endVisit(JThisRef x, Context ctx) {
      push(new JsThisRef(x.getSourceInfo()));
    }

    @Override
    public void endVisit(JThrowStatement x, Context ctx) {
      push(new JsThrow(x.getSourceInfo(), (JsExpression) pop())); // expr
    }

    @Override
    public void endVisit(JTryStatement x, Context ctx) {
      JsTry jsTry = new JsTry(x.getSourceInfo());

      if (x.getFinallyBlock() != null) {
        JsBlock finallyBlock = (JsBlock) pop(); // finallyBlock
        if (finallyBlock.getStatements().size() > 0) {
          jsTry.setFinallyBlock(finallyBlock);
        }
      }

      int size = x.getCatchClauses().size();
      assert (size < 2);
      if (size == 1) {
        JsBlock catchBlock = (JsBlock) pop(); // catchBlocks
        pop(); // catchArgs
        JsCatch jsCatch = catchMap.get(x.getCatchClauses().get(0).getBlock());
        jsCatch.setBody(catchBlock);
        jsTry.getCatches().add(jsCatch);
      }

      jsTry.setTryBlock((JsBlock) pop()); // tryBlock

      push(jsTry);
    }

    @Override
    public void endVisit(JWhileStatement x, Context ctx) {
      JsWhile stmt = new JsWhile(x.getSourceInfo());
      if (x.getBody() != null) {
        stmt.setBody((JsStatement) pop()); // body
      } else {
        stmt.setBody(new JsEmpty(x.getSourceInfo()));
      }
      stmt.setCondition((JsExpression) pop()); // testExpr
      push(stmt);
    }

    @Override
    public boolean visit(JClassType x, Context ctx) {
      if (alreadyRan.contains(x)) {
        return false;
      }

      if (program.getTypeClassLiteralHolder() == x) {
        // Handled in generateClassLiterals.
        return false;
      }

      if (program.immortalCodeGenTypes.contains(x)) {
        // Handled in generateImmortalTypes
        return false;
      }

      // force super type to generate code first, this is required for prototype
      // chaining to work properly
      if (x.getSuperClass() != null && !alreadyRan.contains(x)) {
        accept(x.getSuperClass());
      }
      
      return super.visit(x, ctx);
    }

    @Override
    public boolean visit(JDeclaredType x, Context ctx) {
      checkForDupMethods(x);
      return true;
    }

    @Override
    public boolean visit(JMethod x, Context ctx) {
      if (x.isAbstract()) {
        return false;
      }
      currentMethod = x;
      return true;
    }

    @Override
    public boolean visit(JProgram x, Context ctx) {
      /*
       * Arrange for entryFunctions to be filled in as functions are visited.
       * See their Javadoc comments for more details.
       */
      List<JMethod> entryMethods = x.getEntryMethods();
      entryFunctions = new JsFunction[entryMethods.size()];
      entryMethodToIndex = new IdentityHashMap<JMethod, Integer>();
      for (int i = 0; i < entryMethods.size(); i++) {
        entryMethodToIndex.put(entryMethods.get(i), i);
      }

      for (JDeclaredType type : x.getDeclaredTypes()) {
        if (program.typeOracle.isInstantiatedType(type)) {
          internCastMap(program.getCastMap(type));
        }
      }
      return true;
    }

    @Override
    public boolean visit(JsniMethodBody x, Context ctx) {
      final Map<String, JNode> jsniMap = new HashMap<String, JNode>();
      for (JsniClassLiteral ref : x.getClassRefs()) {
        jsniMap.put(ref.getIdent(), ref.getField());
      }
      for (JsniFieldRef ref : x.getJsniFieldRefs()) {
        jsniMap.put(ref.getIdent(), ref.getField());
      }
      for (JsniMethodRef ref : x.getJsniMethodRefs()) {
        jsniMap.put(ref.getIdent(), ref.getTarget());
      }

      final JsFunction jsFunc = x.getFunc();

      // replace all JSNI idents with a real JsName now that we know it
      new JsModVisitor() {

        /**
         * Marks a ctor that is a direct child of an invocation. Instead of
         * replacing the ctor with a tear-off, we replace the invocation with a
         * new operation.
         */
        private JsNameRef dontReplaceCtor;

        @Override
        public void endVisit(JsInvocation x, JsContext ctx) {
          // Replace invocation to ctor with a new op.
          if (x.getQualifier() instanceof JsNameRef) {
            JsNameRef ref = (JsNameRef) x.getQualifier();
            String ident = ref.getIdent();
            if (isJsniIdent(ident)) {
              JNode node = jsniMap.get(ident);
              assert node instanceof JConstructor;
              assert ref.getQualifier() == null;
              JsName jsName = names.get(node);
              assert (jsName != null);
              ref.resolve(jsName);
              JsNew jsNew = new JsNew(x.getSourceInfo(), ref);
              jsNew.getArguments().addAll(x.getArguments());
              ctx.replaceMe(jsNew);
            }
          }
        }

        @Override
        public void endVisit(JsNameRef x, JsContext ctx) {
          String ident = x.getIdent();
          if (isJsniIdent(ident)) {
            JNode node = jsniMap.get(ident);
            assert (node != null);
            if (node instanceof JField) {
              JField field = (JField) node;
              JsName jsName = names.get(field);
              assert (jsName != null);
              x.resolve(jsName);

              // See if we need to add a clinit call to a static field ref
              JsInvocation clinitCall = maybeCreateClinitCall(field);
              if (clinitCall != null) {
                JsExpression commaExpr = createCommaExpression(clinitCall, x);
                ctx.replaceMe(commaExpr);
              }
            } else if (node instanceof JConstructor) {
              if (x == dontReplaceCtor) {
                // Do nothing, parent will handle.
              } else {
                // Replace with a local closure function.
                // function(a,b,c){return new Obj(a,b,c);}
                JConstructor ctor = (JConstructor) node;
                JsName jsName = names.get(ctor);
                assert (jsName != null);
                x.resolve(jsName);
                SourceInfo info = x.getSourceInfo();
                JsFunction closureFunc = new JsFunction(info, jsFunc.getScope());
                for (JParameter p : ctor.getParams()) {
                  JsName name = closureFunc.getScope().declareName(p.getName());
                  closureFunc.getParameters().add(new JsParameter(info, name));
                }
                JsNew jsNew = new JsNew(info, x);
                for (JsParameter p : closureFunc.getParameters()) {
                  jsNew.getArguments().add(p.getName().makeRef(info));
                }
                JsBlock block = new JsBlock(info);
                block.getStatements().add(new JsReturn(info, jsNew));
                closureFunc.setBody(block);
                ctx.replaceMe(closureFunc);
              }
            } else {
              JMethod method = (JMethod) node;
              if (x.getQualifier() == null) {
                JsName jsName = names.get(method);
                assert (jsName != null);
                x.resolve(jsName);
              } else {
                JsName jsName = polymorphicNames.get(method);
                if (jsName == null) {
                  // this can occur when JSNI references an instance method on a
                  // type that was never actually instantiated.
                  jsName = nullFunc.getName();
                }
                x.resolve(jsName);
              }
            }
          }
        }

        @Override
        public boolean visit(JsInvocation x, JsContext ctx) {
          if (x.getQualifier() instanceof JsNameRef) {
            dontReplaceCtor = (JsNameRef) x.getQualifier();
          }
          return true;
        }

        private boolean isJsniIdent(String ident) {
          return ident.charAt(0) == '@';
        }
      }.accept(jsFunc);

      push(jsFunc);

      // Do NOT visit JsniMethodRefs/JsniFieldRefs.
      return false;
    }

    @Override
    public boolean visit(JSwitchStatement x, Context ctx) {
      /*
       * What a pain.. JSwitchStatement and JsSwitch are modeled completely
       * differently. Here we try to resolve those differences.
       */
      JsSwitch jsSwitch = new JsSwitch(x.getSourceInfo());
      accept(x.getExpr());
      jsSwitch.setExpr((JsExpression) pop()); // expr

      List<JStatement> bodyStmts = x.getBody().getStatements();
      if (bodyStmts.size() > 0) {
        List<JsStatement> curStatements = null;
        for (int i = 0; i < bodyStmts.size(); ++i) {
          JStatement stmt = bodyStmts.get(i);
          accept(stmt);
          if (stmt instanceof JCaseStatement) {
            // create a new switch member
            JsSwitchMember switchMember = (JsSwitchMember) pop(); // stmt
            jsSwitch.getCases().add(switchMember);
            curStatements = switchMember.getStmts();
          } else {
            // add to statements for current case
            assert (curStatements != null);
            JsStatement newStmt = (JsStatement) pop(); // stmt
            if (newStmt != null) {
              // Empty JDeclarationStatement produces a null
              curStatements.add(newStmt);
            }
          }
        }
      }

      push(jsSwitch);
      return false;
    }

    private JsObjectLiteral castMapToObjectLiteral(JsArrayLiteral arrayLit, SourceInfo sourceInfo) {
      JsObjectLiteral objLit = new JsObjectLiteral(sourceInfo);
      List<JsPropertyInitializer> props = objLit.getPropertyInitializers();
      JsNumberLiteral one = new JsNumberLiteral(sourceInfo, 1);
      for (JsExpression expr : arrayLit.getExpressions()) {
        JsPropertyInitializer prop = new JsPropertyInitializer(sourceInfo, expr, one);
        props.add(prop);
      }
      return objLit;
    }

    private void checkForDupMethods(JDeclaredType x) {
      // Sanity check to see that all methods are uniquely named.
      List<JMethod> methods = x.getMethods();
      Set<String> methodSignatures = Sets.create();
      for (JMethod method : methods) {
        String sig = method.getSignature();
        if (methodSignatures.contains(sig)) {
          throw new InternalCompilerException("Signature collision in Type " + x.getName()
              + " for method " + sig);
        }
        methodSignatures = Sets.add(methodSignatures, sig);
      }
    }

    private JsExpression createAssignment(JsExpression lhs, JsExpression rhs) {
      return new JsBinaryOperation(lhs.getSourceInfo(), JsBinaryOperator.ASG, lhs, rhs);
    }

    private JsExpression createCommaExpression(JsExpression lhs, JsExpression rhs) {
      if (lhs == null) {
        return rhs;
      } else if (rhs == null) {
        return lhs;
      }
      return new JsBinaryOperation(lhs.getSourceInfo(), JsBinaryOperator.COMMA, lhs, rhs);
    }

    private JsNameRef createNativeToStringRef(JsExpression qualifier) {
      JsName toStringName = objectScope.declareName("toString");
      toStringName.setObfuscatable(false);
      JsNameRef toStringRef = toStringName.makeRef(qualifier.getSourceInfo());
      toStringRef.setQualifier(qualifier);
      return toStringRef;
    }

    private JsExpression generateCastableTypeMap(JClassType x) {
      JsCastMap castMap = program.getCastMap(x);
      if (castMap != null) {
        JField castableTypeMapField = program.getIndexedField("Object.castableTypeMap");
        JsName castableTypeMapName = names.get(castableTypeMapField);
        if (castableTypeMapName == null) {
          // Was pruned; this compilation must have no dynamic casts.
          return new JsObjectLiteral(SourceOrigin.UNKNOWN);
        }

        accept(castMap);
        return (JsExpression) pop();
      }
      return new JsObjectLiteral(SourceOrigin.UNKNOWN);
    }

    private void generateClassLiteral(JDeclarationStatement decl, JsVars vars) {
      JField field = (JField) decl.getVariableRef().getTarget();
      JsName jsName = names.get(field);
      this.accept(decl.getInitializer());
      JsExpression classObjectAlloc = pop();
      JsVar var = new JsVar(decl.getSourceInfo(), jsName);
      var.setInitExpr(classObjectAlloc);
      vars.add(var);
    }

    private void generateClassLiterals(JsVars vars) {
      /*
       * Must execute in clinit statement order, NOT field order, so that back
       * refs to super classes are preserved.
       */
      JMethodBody clinitBody =
          (JMethodBody) program.getTypeClassLiteralHolder().getClinitMethod().getBody();
      for (JStatement stmt : clinitBody.getStatements()) {
        if (stmt instanceof JDeclarationStatement) {
          generateClassLiteral((JDeclarationStatement) stmt, vars);
        }
      }
    }

    private void generateClassSetup(JClassType x, List<JsStatement> globalStmts) {
      generateSeedFuncAndPrototype(x, globalStmts);
      generateVTables(x, globalStmts);

      if (x == program.getTypeJavaLangObject()) {
        // special: setup a "toString" alias for java.lang.Object.toString()
        generateToStringAlias(x, globalStmts);
        // special: setup the identifying typeMarker field
        generateTypeMarker(globalStmts);
      }
    }

    private void generateGwtOnLoad(List<JsFunction> entryFuncs, List<JsStatement> globalStmts) {
      /**
       * <pre>
       * var $entry = Impl.registerEntry();
       * function gwtOnLoad(errFn, modName, modBase, softPermutationId){
       *   $moduleName = modName;
       *   $moduleBase = modBase;
       *   CollapsedPropertyHolder.permutationId = softPermutationId;
       *   if (errFn) {
       *     try {
       *       $entry(init)();
       *     } catch(e) {
       *       errFn(modName);
       *     }
       *   } else {
       *     $entry(init)();
       *   }
       * }
       * </pre>
       */
      SourceInfo sourceInfo = SourceOrigin.UNKNOWN;

      JsName entryName = topScope.declareName("$entry");
      JsVar entryVar = new JsVar(sourceInfo, entryName);
      JsInvocation registerEntryCall = new JsInvocation(sourceInfo);
      JsFunction registerEntryFunction = indexedFunctions.get("Impl.registerEntry");
      registerEntryCall.setQualifier(registerEntryFunction.getName().makeRef(sourceInfo));
      entryVar.setInitExpr(registerEntryCall);
      JsVars entryVars = new JsVars(sourceInfo);
      entryVars.add(entryVar);
      globalStmts.add(entryVars);

      JsName gwtOnLoadName = topScope.declareName("gwtOnLoad");
      gwtOnLoadName.setObfuscatable(false);
      JsFunction gwtOnLoad = new JsFunction(sourceInfo, topScope, gwtOnLoadName, true);
      gwtOnLoad.setArtificiallyRescued(true);
      globalStmts.add(gwtOnLoad.makeStmt());
      JsBlock body = new JsBlock(sourceInfo);
      gwtOnLoad.setBody(body);
      JsScope fnScope = gwtOnLoad.getScope();
      List<JsParameter> params = gwtOnLoad.getParameters();
      JsName errFn = fnScope.declareName("errFn");
      JsName modName = fnScope.declareName("modName");
      JsName modBase = fnScope.declareName("modBase");
      JsName softPermutationId = fnScope.declareName("softPermutationId");
      params.add(new JsParameter(sourceInfo, errFn));
      params.add(new JsParameter(sourceInfo, modName));
      params.add(new JsParameter(sourceInfo, modBase));
      params.add(new JsParameter(sourceInfo, softPermutationId));
      JsExpression asg =
          createAssignment(topScope.findExistingUnobfuscatableName("$moduleName").makeRef(
              sourceInfo), modName.makeRef(sourceInfo));
      body.getStatements().add(asg.makeStmt());
      asg =
          createAssignment(topScope.findExistingUnobfuscatableName("$moduleBase").makeRef(
              sourceInfo), modBase.makeRef(sourceInfo));
      body.getStatements().add(asg.makeStmt());

      // Assignment to CollapsedPropertyHolder.permutationId only if it's used
      JsName permutationIdFieldName =
          names.get(program.getIndexedField("CollapsedPropertyHolder.permutationId"));
      if (permutationIdFieldName != null) {
        asg =
            createAssignment(permutationIdFieldName.makeRef(sourceInfo), softPermutationId
                .makeRef(sourceInfo));
        body.getStatements().add(asg.makeStmt());
      }

      JsIf jsIf = new JsIf(sourceInfo);
      body.getStatements().add(jsIf);
      jsIf.setIfExpr(errFn.makeRef(sourceInfo));
      JsTry jsTry = new JsTry(sourceInfo);
      jsIf.setThenStmt(jsTry);
      JsBlock callBlock = new JsBlock(sourceInfo);
      jsIf.setElseStmt(callBlock);
      jsTry.setTryBlock(callBlock);
      for (JsFunction func : entryFuncs) {
        if (func == registerEntryFunction) {
          continue;
        } else if (func != null) {
          JsInvocation call = new JsInvocation(sourceInfo);
          call.setQualifier(entryName.makeRef(sourceInfo));
          call.getArguments().add(func.getName().makeRef(sourceInfo));
          JsInvocation entryCall = new JsInvocation(sourceInfo);
          entryCall.setQualifier(call);
          callBlock.getStatements().add(entryCall.makeStmt());
        }
      }
      JsCatch jsCatch = new JsCatch(sourceInfo, fnScope, "e");
      jsTry.getCatches().add(jsCatch);
      JsBlock catchBlock = new JsBlock(sourceInfo);
      jsCatch.setBody(catchBlock);
      JsInvocation errCall = new JsInvocation(sourceInfo);
      catchBlock.getStatements().add(errCall.makeStmt());
      errCall.setQualifier(errFn.makeRef(sourceInfo));
      errCall.getArguments().add(modName.makeRef(sourceInfo));
    }

    private void generateImmortalTypes(JsVars globals) {
      List<JsStatement> globalStmts = jsProgram.getGlobalBlock().getStatements();
      List<JClassType> immortalTypes = new ArrayList<JClassType>(
          program.immortalCodeGenTypes);
      // visit in reverse order since insertions start at head
      Collections.reverse(immortalTypes);
      JMethod createObjMethod = program.getIndexedMethod("JavaScriptObject.createObject");
      JMethod createArrMethod = program.getIndexedMethod("JavaScriptObject.createArray");

      for (JClassType x : immortalTypes) {
        // should not be pruned
        assert x.getMethods().size() > 0;
        // insert all static methods
        for (JMethod method : x.getMethods()) {
          /*
           * Skip virtual methods and constructors. Even in cases where there is no constructor
           * defined, the compiler will synthesize a default constructor which invokes
           * a synthensized $init() method. We must skip both of these inserted methods.
           */
          if (method.needsVtable() || method instanceof JConstructor) {
            continue;
          }
          if (JProgram.isClinit(method)) {
            /**
             * Emit empty clinits that will be pruned. If a type B extends A, then even if
             * B and A have no fields to initialize, there will be a call inserted in B's clinit
             * to invoke A's clinit. Likewise, if you have a static field initialized to
             * JavaScriptObject.createObject(), the clinit() will include this initializer code,
             * which we don't want.
             */
            JsFunction func = new JsFunction(x.getSourceInfo(), topScope,
                topScope.declareName(mangleNameForGlobal(method)), true);
            func.setBody(new JsBlock(method.getBody().getSourceInfo()));
            push(func);
          } else {
            accept(method);
          }
          // add after var declaration, but before everything else
          JsFunction func = (JsFunction) pop();
          assert func.getName() != null;
          globalStmts.add(1, func.makeStmt());
        }

        // insert fields into global var declaration
        for (JField field : x.getFields()) {
          assert field.isStatic() : "All fields on immortal types must be static.";
          accept(field);
          JsNode node = pop();
          assert node instanceof JsVar;
          JsVar fieldVar = (JsVar) node;
          JExpression init = field.getInitializer();
          if (init != null
              && field.getLiteralInitializer() == null) {
            // no literal, but it could be a JavaScriptObject
            if (init.getType() == program.getJavaScriptObject()) {
              assert init instanceof JMethodCall;
              JMethod meth = ((JMethodCall) init).getTarget();
              // immortal types can only have non-primitive literal initializers of createArray,createObject
              if (meth == createObjMethod) {
                fieldVar.setInitExpr(new JsObjectLiteral(init.getSourceInfo()));
              } else if (meth == createArrMethod) {
                fieldVar.setInitExpr(new JsArrayLiteral(init.getSourceInfo()));
              } else {
                assert false : "Illegal initializer expression for immortal field " + field;
              }
            }
          }
          globals.add(fieldVar);
        }
      }
    }

    private void generateInternedCastMapLiterals(JsVars vars) {
      SourceInfo info = vars.getSourceInfo();
      int id = 0;
      for (Map.Entry<String, JsName> castMapEntry : namesByCastMap.entrySet()) {
        JsVar var = new JsVar(info, castMapEntry.getValue());
        var.setInitExpr(castMapByString.get(castMapEntry.getKey()));
        vars.add(var);
      }
    }

    private void generateLongLiterals(JsVars vars) {
      for (Entry<Long, JsName> entry : longLits.entrySet()) {
        JsName jsName = entry.getValue();
        JsExpression longObjectAlloc = longObjects.get(jsName);
        JsVar var = new JsVar(vars.getSourceInfo(), jsName);
        var.setInitExpr(longObjectAlloc);
        vars.add(var);
      }
    }

    private void generateQueryIdConstants(JsVars vars) {
      if (namesByQueryId != null) {
        SourceInfo info = vars.getSourceInfo();
        int id = 0;
        for (JsName jsName : namesByQueryId) {
          JsVar var = new JsVar(info, jsName);
          var.setInitExpr(new JsNumberLiteral(info, id++));
          vars.add(var);
        }
      }
    }



    private void generateSeedFuncAndPrototype(JClassType x, List<JsStatement> globalStmts) {
      SourceInfo sourceInfo = x.getSourceInfo();
      if (x != program.getTypeJavaLangString()) {
        JsInvocation defineSeed = new JsInvocation(x.getSourceInfo());
        JsName seedNameRef = indexedFunctions.get(
            "SeedUtil.defineSeed").getName();
        defineSeed.setQualifier(seedNameRef.makeRef(x.getSourceInfo()));
        int newSeed = getSeedId(x);
        assert newSeed > 0;
        JClassType superClass = x.getSuperClass();
        int superSeed = (superClass == null) ? -1 : getSeedId(x.getSuperClass());
        // SeedUtil.defineSeed(queryId, superId, castableMap, constructors)
        defineSeed.getArguments().add(new JsNumberLiteral(x.getSourceInfo(),
            newSeed));
        defineSeed.getArguments().add(new JsNumberLiteral(x.getSourceInfo(),
            superSeed));
        JsExpression castMap = generateCastableTypeMap(x);
        defineSeed.getArguments().add(castMap);
       
        // Chain assign the same prototype to every live constructor.
        for (JMethod method : x.getMethods()) {
          if (liveCtors.contains(method)) {
            defineSeed.getArguments().add(names.get(method).makeRef(
                sourceInfo));
          }
        }

        JsStatement tmpAsgStmt = defineSeed.makeStmt();
        globalStmts.add(tmpAsgStmt);
        typeForStatMap.put(tmpAsgStmt, x);
      } else {
        /*
         * MAGIC: java.lang.String is implemented as a JavaScript String
         * primitive with a modified prototype.
         */
        JsNameRef rhs = prototype.makeRef(sourceInfo);
        rhs.setQualifier(JsRootScope.INSTANCE.findExistingUnobfuscatableName("String").makeRef(
            sourceInfo));
        JsExpression tmpAsg = createAssignment(globalTemp.makeRef(sourceInfo), rhs);
        JsExprStmt tmpAsgStmt = tmpAsg.makeStmt();
        globalStmts.add(tmpAsgStmt);
        typeForStatMap.put(tmpAsgStmt, x);
        JField castableTypeMapField = program.getIndexedField("Object.castableTypeMap");
        JsName castableTypeMapName = names.get(castableTypeMapField);
        JsNameRef ctmRef = castableTypeMapName.makeRef(sourceInfo);
        ctmRef.setQualifier(globalTemp.makeRef(sourceInfo));
        JsExpression castMapLit = generateCastableTypeMap(x);
        JsExpression ctmAsg = createAssignment(ctmRef,
            castMapLit);
        JsExprStmt ctmAsgStmt = ctmAsg.makeStmt();
        globalStmts.add(ctmAsgStmt);
        typeForStatMap.put(ctmAsgStmt, x);
      }
    }

    private void generateToStringAlias(JClassType x, List<JsStatement> globalStmts) {
      JMethod toStringMeth = program.getIndexedMethod("Object.toString");
      if (x.getMethods().contains(toStringMeth)) {
        SourceInfo sourceInfo = x.getSourceInfo();
        // _.toString = function(){return this.java_lang_Object_toString();}

        // lhs
        JsNameRef lhs = createNativeToStringRef(globalTemp.makeRef(sourceInfo));

        // rhs
        JsInvocation call = new JsInvocation(sourceInfo);
        JsNameRef toStringRef = new JsNameRef(sourceInfo, polymorphicNames.get(toStringMeth));
        toStringRef.setQualifier(new JsThisRef(sourceInfo));
        call.setQualifier(toStringRef);
        JsReturn jsReturn = new JsReturn(sourceInfo, call);
        JsFunction rhs = new JsFunction(sourceInfo, topScope);
        JsBlock body = new JsBlock(sourceInfo);
        body.getStatements().add(jsReturn);
        rhs.setBody(body);

        // asg
        JsExpression asg = createAssignment(lhs, rhs);
        JsExprStmt stmt = asg.makeStmt();
        globalStmts.add(stmt);
        typeForStatMap.put(stmt, program.getTypeJavaLangObject());
      }
    }

    private void generateTypeMarker(List<JsStatement> globalStmts) {
      JField typeMarkerField = program.getIndexedField("Object.typeMarker");
      JsName typeMarkerName = names.get(typeMarkerField);
      if (typeMarkerName == null) {
        // Was pruned; this compilation must have no JSO instanceof tests.
        return;
      }
      SourceInfo sourceInfo = jsProgram.createSourceInfoSynthetic(GenerateJavaScriptAST.class);
      JsNameRef fieldRef = typeMarkerName.makeRef(sourceInfo);
      fieldRef.setQualifier(globalTemp.makeRef(sourceInfo));
      JsExpression asg = createAssignment(fieldRef, nullFunc.getName().makeRef(sourceInfo));
      JsExprStmt stmt = asg.makeStmt();
      globalStmts.add(stmt);
      typeForStatMap.put(stmt, program.getTypeJavaLangObject());
    }

    private void generateVTables(JClassType x, List<JsStatement> globalStmts) {
      boolean isString = (x == program.getTypeJavaLangString());
      for (JMethod method : x.getMethods()) {
        SourceInfo sourceInfo = method.getSourceInfo();
        if (method.needsVtable() && !method.isAbstract()) {
          JsNameRef lhs = polymorphicNames.get(method).makeRef(sourceInfo);
          lhs.setQualifier(globalTemp.makeRef(sourceInfo));

          JsExpression rhs;
          if (isString && "toString".equals(method.getName()))  {
            // special-case String.toString: alias to the native JS toString()
            rhs = createNativeToStringRef(globalTemp.makeRef(sourceInfo));
          } else {
            /*
             * Inline JsFunction rather than reference, e.g. _.vtableName =
             * function functionName() { ... }
             */
            rhs = methodBodyMap.get(method.getBody());
          }
          JsExpression asg = createAssignment(lhs, rhs);
          JsExprStmt asgStat = new JsExprStmt(x.getSourceInfo(), asg);
          globalStmts.add(asgStat);
          vtableInitForMethodMap.put(asgStat, method);
        }
      }
    }

    private void handleClinit(JsFunction clinitFunc, JsFunction superClinit) {
      clinitFunc.setExecuteOnce(true);
      clinitFunc.setImpliedExecute(superClinit);
      List<JsStatement> statements = clinitFunc.getBody().getStatements();
      SourceInfo sourceInfo = clinitFunc.getSourceInfo();
      // self-assign to the null method immediately (to prevent reentrancy)
      JsExpression asg =
          createAssignment(clinitFunc.getName().makeRef(sourceInfo), nullFunc.getName().makeRef(
              sourceInfo));
      statements.add(0, asg.makeStmt());
    }

    private void internCastMap(JsCastMap x) {
      String stringMap = castMapToString(x);
      if (castMapSeen.contains(stringMap)) {
        internedCastMap.add(stringMap);
      } else {
        castMapSeen.add(stringMap);
      }
    }

    private JsInvocation maybeCreateClinitCall(JField x) {
      if (!x.isStatic()) {
        return null;
      }

      JDeclaredType targetType = x.getEnclosingType().getClinitTarget();
      if (!currentMethod.getEnclosingType().checkClinitTo(targetType)) {
        return null;
      } else if (targetType.equals(program.getTypeClassLiteralHolder())) {
        return null;
      }

      JMethod clinitMethod = targetType.getClinitMethod();
      SourceInfo sourceInfo = x.getSourceInfo();
      JsInvocation jsInvocation = new JsInvocation(sourceInfo);
      jsInvocation.setQualifier(names.get(clinitMethod).makeRef(sourceInfo));
      return jsInvocation;
    }

    private JsInvocation maybeCreateClinitCall(JMethod x) {
      if (!crossClassTargets.contains(x)) {
        return null;
      }
      if (x.canBePolymorphic() || program.isStaticImpl(x)) {
        return null;
      }
      JDeclaredType enclosingType = x.getEnclosingType();
      if (enclosingType == null || !enclosingType.hasClinit()) {
        return null;
      }
      // avoid recursion sickness
      if (JProgram.isClinit(x)) {
        return null;
      }

      JMethod clinitMethod = enclosingType.getClinitTarget().getClinitMethod();
      SourceInfo sourceInfo = x.getSourceInfo();
      JsInvocation jsInvocation = new JsInvocation(sourceInfo);
      jsInvocation.setQualifier(names.get(clinitMethod).makeRef(sourceInfo));
      return jsInvocation;
    }

    /**
     * If a field is a literal, we can potentially treat it as immutable and assign it once on the
     * prototype, to be reused by all instances of the class, instead of re-assigning the same
     * literal in each constructor.
     * 
     * Technically, to match JVM semantics, we should only do this for final or static fields. For
     * non-final/non-static fields, a super class's cstr, when it calls a polymorphic method that is
     * overridden in the subclass, should actually see default values (not the literal initializer)
     * before the subclass's cstr runs.
     * 
     * However, cstr's calling polymorphic methods is admittedly an uncommon case, so we apply some
     * heuristics to see if we can initialize the field on the prototype anyway.
     */
    private boolean initializeAtTopScope(JField x) {
      if (x.getLiteralInitializer() == null) {
        return false;
      }
      if (x.isFinal() || x.isStatic()) {
        // we can definitely initialize at top-scope, as JVM does so as well
        return true;
      }
      // if the superclass can observe the field, we need to leave the default value
      JDeclaredType current = x.getEnclosingType().getSuperClass();
      while (current != null) {
        if (canObserveSubclassFields.contains(current)) {
          return false;
        }
        current = current.getSuperClass();
      }
      // should be safe to initialize at top-scope, as no one can observe the difference
      return true;
    }
  }

  private static class JavaToJsOperatorMap {
    private static final Map<JBinaryOperator, JsBinaryOperator> bOpMap =
        new EnumMap<JBinaryOperator, JsBinaryOperator>(JBinaryOperator.class);
    private static final Map<JUnaryOperator, JsUnaryOperator> uOpMap =
        new EnumMap<JUnaryOperator, JsUnaryOperator>(JUnaryOperator.class);

    static {
      bOpMap.put(JBinaryOperator.MUL, JsBinaryOperator.MUL);
      bOpMap.put(JBinaryOperator.DIV, JsBinaryOperator.DIV);
      bOpMap.put(JBinaryOperator.MOD, JsBinaryOperator.MOD);
      bOpMap.put(JBinaryOperator.ADD, JsBinaryOperator.ADD);
      bOpMap.put(JBinaryOperator.CONCAT, JsBinaryOperator.ADD);
      bOpMap.put(JBinaryOperator.SUB, JsBinaryOperator.SUB);
      bOpMap.put(JBinaryOperator.SHL, JsBinaryOperator.SHL);
      bOpMap.put(JBinaryOperator.SHR, JsBinaryOperator.SHR);
      bOpMap.put(JBinaryOperator.SHRU, JsBinaryOperator.SHRU);
      bOpMap.put(JBinaryOperator.LT, JsBinaryOperator.LT);
      bOpMap.put(JBinaryOperator.LTE, JsBinaryOperator.LTE);
      bOpMap.put(JBinaryOperator.GT, JsBinaryOperator.GT);
      bOpMap.put(JBinaryOperator.GTE, JsBinaryOperator.GTE);
      bOpMap.put(JBinaryOperator.EQ, JsBinaryOperator.EQ);
      bOpMap.put(JBinaryOperator.NEQ, JsBinaryOperator.NEQ);
      bOpMap.put(JBinaryOperator.BIT_AND, JsBinaryOperator.BIT_AND);
      bOpMap.put(JBinaryOperator.BIT_XOR, JsBinaryOperator.BIT_XOR);
      bOpMap.put(JBinaryOperator.BIT_OR, JsBinaryOperator.BIT_OR);
      bOpMap.put(JBinaryOperator.AND, JsBinaryOperator.AND);
      bOpMap.put(JBinaryOperator.OR, JsBinaryOperator.OR);
      bOpMap.put(JBinaryOperator.ASG, JsBinaryOperator.ASG);
      bOpMap.put(JBinaryOperator.ASG_ADD, JsBinaryOperator.ASG_ADD);
      bOpMap.put(JBinaryOperator.ASG_CONCAT, JsBinaryOperator.ASG_ADD);
      bOpMap.put(JBinaryOperator.ASG_SUB, JsBinaryOperator.ASG_SUB);
      bOpMap.put(JBinaryOperator.ASG_MUL, JsBinaryOperator.ASG_MUL);
      bOpMap.put(JBinaryOperator.ASG_DIV, JsBinaryOperator.ASG_DIV);
      bOpMap.put(JBinaryOperator.ASG_MOD, JsBinaryOperator.ASG_MOD);
      bOpMap.put(JBinaryOperator.ASG_SHL, JsBinaryOperator.ASG_SHL);
      bOpMap.put(JBinaryOperator.ASG_SHR, JsBinaryOperator.ASG_SHR);
      bOpMap.put(JBinaryOperator.ASG_SHRU, JsBinaryOperator.ASG_SHRU);
      bOpMap.put(JBinaryOperator.ASG_BIT_AND, JsBinaryOperator.ASG_BIT_AND);
      bOpMap.put(JBinaryOperator.ASG_BIT_OR, JsBinaryOperator.ASG_BIT_OR);
      bOpMap.put(JBinaryOperator.ASG_BIT_XOR, JsBinaryOperator.ASG_BIT_XOR);

      uOpMap.put(JUnaryOperator.INC, JsUnaryOperator.INC);
      uOpMap.put(JUnaryOperator.DEC, JsUnaryOperator.DEC);
      uOpMap.put(JUnaryOperator.NEG, JsUnaryOperator.NEG);
      uOpMap.put(JUnaryOperator.NOT, JsUnaryOperator.NOT);
      uOpMap.put(JUnaryOperator.BIT_NOT, JsUnaryOperator.BIT_NOT);
    }

    public static JsBinaryOperator get(JBinaryOperator op) {
      return bOpMap.get(op);
    }

    public static JsUnaryOperator get(JUnaryOperator op) {
      return uOpMap.get(op);
    }
  }

  /**
   * Determines which classes can potentially see uninitialized values of their subclasses' fields.
   * 
   * If a class can not observe subclass uninitialized fields then the initialization of those could
   * be hoisted to the prototype.
   */
  private class CanObserveSubclassUninitializedFieldsVisitor extends JVisitor {
    private JDeclaredType currentClass;

    @Override
    public boolean visit(JConstructor x, Context ctx) {
      // Only look at constructor bodies.
      assert currentClass == null;
      currentClass = x.getEnclosingType();
      return true;
    }

    @Override
    public void endVisit(JConstructor x, Context ctx) {
      currentClass = null;
    }

    @Override
    public boolean visit(JMethod x, Context ctx) {
      if (x.getName().equals("$$init")) {
        assert currentClass == null;
        currentClass = x.getEnclosingType();
        return true;
      }
      // Do not traverse the method body if it is not a constructor.
      return false;
    }

    @Override
    public void endVisit(JMethod x, Context ctx) {
      currentClass = null;
    }

    @Override
    public void endVisit(JMethodCall x, Context ctx) {
      // This is a method call inside a constructor.
      assert currentClass != null;
      // Calls to this/super constructors are okay, as they will also get examined
      if (x.getTarget().isConstructor() && x.getInstance() instanceof JThisRef) {
        return;
      }
      // Calls to the instance initializer are okay, as execution will not escape it
      if (x.getTarget().getName().equals("$$init")) {
        return;
      }
      // Calls to static methods with no arguments are safe, because they have no
      // way to trace back into our new instance.
      if (x.getTarget().isStatic() && x.getTarget().getOriginalParamTypes().size() == 0) {
        return;
      }
      // Technically we could get fancier about trying to track the "this" reference
      // through other variable assignments, field assignments, and methods calls, to
      // see if it calls a polymorphic method against ourself (which would let subclasses
      // observe their fields), but that gets tricky, so we'll use the above heuristics
      // for now.
      canObserveSubclassFields.add(currentClass);
    }
  }

  private class RecordCrossClassCallsAndJSInlinableMethods extends JVisitor {

    private JMethod currentMethod;

    // Java methods that would have not been already exploited for inline opportunities due to
    // either beign nativeor that contain classes to native methods are collected here.
    Set<JMethod> methodsForJsInlining = new HashSet<JMethod>();


    @Override
    public void endVisit(JMethod x, Context ctx) {
      if (x.isNative()) {
        methodsForJsInlining.add(x);
      }

      currentMethod = null;
    }

    @Override
    public void endVisit(JMethodCall x, Context ctx) {
      JDeclaredType sourceType = currentMethod.getEnclosingType();
      JDeclaredType targetType = x.getTarget().getEnclosingType();
      if (sourceType.checkClinitTo(targetType)) {
        crossClassTargets.add(x.getTarget());
      }
      if (x.getTarget().isNative()
          && ((JsniMethodBody) x.getTarget().getBody()).getFunc().getBody().getStatements().size()
          <= JsInliner.MAX_INLINE_FN_SIZE) {
        // currentMethod calls a jsni method, currentMethod
        // will be consider for JavaScript inlining
        methodsForJsInlining.add(currentMethod);
      }
    }

    @Override
    public void endVisit(JNewInstance x, Context ctx) {
      super.endVisit(x, ctx);
      liveCtors.add(x.getTarget());
    }

    @Override
    public void endVisit(JProgram x, Context ctx) {
      // Entry methods can be called externally, so they must run clinit.
      crossClassTargets.addAll(x.getEntryMethods());
    }

    @Override
    public void endVisit(JsniMethodRef x, Context ctx) {
      if (x.getTarget() instanceof JConstructor) {
        liveCtors.add((JConstructor) x.getTarget());
      }

      endVisit((JMethodCall) x, ctx);
    }

    @Override
    public boolean visit(JMethod x, Context ctx) {
      currentMethod = x;
      return true;
    }
  }

  private static class SortVisitor extends JVisitor {
    // TODO(rluble): this visitor seems to traverse statements innecessarily.
    private final HasNameSort hasNameSort = new HasNameSort();

    private final Comparator<JMethod> methodSort = new Comparator<JMethod>() {
      @Override
      public int compare(JMethod m1, JMethod m2) {
        return m1.getSignature().compareTo(m2.getSignature());
      }
    };

    @Override
    public void endVisit(JClassType x, Context ctx) {
      x.sortFields(hasNameSort);
      x.sortMethods(methodSort);
    }

    @Override
    public void endVisit(JInterfaceType x, Context ctx) {
      x.sortFields(hasNameSort);
      x.sortMethods(methodSort);
    }

    @Override
    public void endVisit(JMethodBody x, Context ctx) {
      x.sortLocals(hasNameSort);
    }

    @Override
    public void endVisit(JProgram x, Context ctx) {
      Collections.sort(x.getEntryMethods(), methodSort);
      Collections.sort(x.getDeclaredTypes(), hasNameSort);
    }
  }

  /**
   * This is the main entry point for the translation from Java to JavaScript. Starts from a
   * Java AST and constructs a JavaScript AST while collecting other useful information that
   * is used in subsequent passes.
   *
   * @param program           a Java AST
   * @param jsProgram         an (empty) JavaScript AST
   * @param outputOption      options that affect this transformation for this transformation
   *                          e.g. OBFUSCATED, etc.
   * @param symbolTable       an (empty) symbol table that will be populated here
   * @param propertyOracles   property oracles that correspond to the permutation being compiled.
   * @return A pair containing a JavaToJavaScriptMap and a Set of JsFunctions that need to be
   *         considered for inlining.
   */
  public static Pair<JavaToJavaScriptMap, Set<JsNode>> exec(JProgram program,
      JsProgram jsProgram, JsOutputOption outputOption, Map<StandardSymbolData, JsName> symbolTable,
      PropertyOracle[] propertyOracles) {
    GenerateJavaScriptAST generateJavaScriptAST =
        new GenerateJavaScriptAST(program, jsProgram, outputOption, symbolTable, propertyOracles);
    return generateJavaScriptAST.execImpl();
  }


  private Map<String, JsExpression> castMapByString = new HashMap<String, JsExpression>();

  private final Map<JBlock, JsCatch> catchMap = new IdentityHashMap<JBlock, JsCatch>();

  private final Set<JsName> catchParamIdentifiers = new HashSet<JsName>();

  private final Map<JClassType, JsScope> classScopes = new IdentityHashMap<JClassType, JsScope>();

  /**
   * A list of methods that are called from another class (ie might need to
   * clinit).
   */
  private final Set<JMethod> crossClassTargets = new HashSet<JMethod>();

  private Map<String, JsFunction> indexedFunctions = Maps.create();

  private Map<String, JsName> indexedFields = Maps.create();

  /**
   * Contains JsNames for all interface methods. A special scope is needed so
   * that independent classes will obfuscate their interface implementation
   * methods the same way.
   */
  private final JsScope interfaceScope;

  private final Set<String> internedCastMap = new HashSet<String>();

  private final JsProgram jsProgram;

  private final Set<JConstructor> liveCtors = new IdentityHashSet<JConstructor>();

  /**
   * Classes that could potentially see uninitialized values for fields that are initialized in the
   * declaration.
   */
  private final Set<JDeclaredType> canObserveSubclassFields = new HashSet<JDeclaredType>();

  /**
   * Sorted to avoid nondeterministic iteration.
   */
  private final Map<Long, JsName> longLits = new TreeMap<Long, JsName>();

  private final Map<JsName, JsExpression> longObjects = new IdentityHashMap<JsName, JsExpression>();
  private JsFunction makeMapFunction;
  private final Map<JAbstractMethodBody, JsFunction> methodBodyMap =
      new IdentityHashMap<JAbstractMethodBody, JsFunction>();
  private final Map<HasName, JsName> names = new IdentityHashMap<HasName, JsName>();
  private int nextSeedId = 1;
  private List<JsName> namesByQueryId;
  private Map<String, JsName> namesByCastMap = new HashMap<String, JsName>();
  private JsFunction nullFunc;

  /**
   * Contains JsNames for the Object instance methods, such as equals, hashCode,
   * and toString. All other class scopes have this scope as an ultimate parent.
   */
  private final JsScope objectScope;
  private final JsOutputOption output;
  private final Set<JsFunction> polymorphicJsFunctions = new IdentityHashSet<JsFunction>();
  private final Map<JMethod, JsName> polymorphicNames = new IdentityHashMap<JMethod, JsName>();
  private final JProgram program;

  /**
   * Map of class type to allocated seed id.
   */
  private final Map<JReferenceType, Integer> seedIdMap = new HashMap<JReferenceType, Integer>();

  /**
   * All of the fields in String and Array need special handling for interop.
   */
  private final Map<JField, String> specialObfuscatedFields = new HashMap<JField, String>();

  /**
   * All of the methods in String and Array need special handling for interop.
   */
  private final Map<String, String> specialObfuscatedMethodSigs = new HashMap<String, String>();

  /**
   * If true, polymorphic functions are made anonymous vtable declarations and
   * not assigned topScope identifiers.
   */
  private final boolean stripStack;

  /**
   * Maps JsNames to machine-usable identifiers.
   */
  private final Map<StandardSymbolData, JsName> symbolTable;

  /**
   * Contains JsNames for all globals, such as static fields and methods.
   */
  private final JsScope topScope;

  private final Map<JsStatement, JClassType> typeForStatMap =
      new HashMap<JsStatement, JClassType>();

  private final JTypeOracle typeOracle;

  private final Map<JsStatement, JMethod> vtableInitForMethodMap =
      new HashMap<JsStatement, JMethod>();

  private GenerateJavaScriptAST(JProgram program, JsProgram jsProgram, JsOutputOption output,
      Map<StandardSymbolData, JsName> symbolTable, PropertyOracle[] propertyOracles) {
    this.program = program;
    typeOracle = program.typeOracle;
    this.jsProgram = jsProgram;
    topScope = jsProgram.getScope();
    objectScope = jsProgram.getObjectScope();
    interfaceScope = new JsNormalScope(objectScope, "Interfaces");
    this.output = output;
    this.symbolTable = symbolTable;

    this.stripStack =
        JsStackEmulator.getStackMode(propertyOracles) == JsStackEmulator.StackMode.STRIP;

    /*
     * Because we modify the JavaScript String prototype, all fields and
     * polymorphic methods on String and super types need special handling.
     */

    // Object polymorphic
    Map<String, String> namesToIdents = new HashMap<String, String>();
    namesToIdents.put("getClass", "gC");
    namesToIdents.put("hashCode", "hC");
    namesToIdents.put("equals", "eQ");
    namesToIdents.put("toString", "tS");
    namesToIdents.put("finalize", "fZ");
    // String polymorphic
    namesToIdents.put("charAt", "cA");
    namesToIdents.put("compareTo", "cT");
    namesToIdents.put("length", "lN");
    namesToIdents.put("subSequence", "sS");

    List<JMethod> methods = new ArrayList<JMethod>(program.getTypeJavaLangObject().getMethods());
    methods.addAll(program.getIndexedType("Comparable").getMethods());
    methods.addAll(program.getIndexedType("CharSequence").getMethods());
    for (JMethod method : methods) {
      if (method.canBePolymorphic()) {
        String ident = namesToIdents.get(method.getName());
        assert ident != null;
        specialObfuscatedMethodSigs.put(method.getSignature(), ident);
      }
    }

    namesToIdents.clear();
    // Object fields
    namesToIdents.put("expando", "eX");
    namesToIdents.put("typeMarker", "tM");
    namesToIdents.put("castableTypeMap", "cM");
    namesToIdents.put("___clazz", "cZ");
    // Array magic field
    namesToIdents.put("queryId", "qI");

    List<JField> fields = new ArrayList<JField>(program.getTypeJavaLangObject().getFields());
    fields.addAll(program.getIndexedType("Array").getFields());
    for (JField field : fields) {
      if (!field.isStatic()) {
        String ident = namesToIdents.get(field.getName());
        assert ident != null;
        specialObfuscatedFields.put(field, ident);
      }
    }

    // force java.lang.Object,java.lang.String
    // to have seed ids 1,2
    getSeedId(program.getTypeJavaLangObject());
    getSeedId(program.getTypeJavaLangString());
  }

  String castMapToString(JsCastMap x) {
    if (x == null || x.getExprs() == null || x.getExprs().size() == 0) {
      return "{}";
    } else {
      TextOutput textOutput = new DefaultTextOutput(true);
      ToStringGenerationVisitor toStringer = new ToStringGenerationVisitor(textOutput);
      toStringer.accept(x);
      String stringMap = textOutput.toString();
      return stringMap;
    }
  }

  String getNameString(HasName hasName) {
    String s = hasName.getName().replaceAll("_", "_1").replace('.', '_');
    return s;
  }

  /**
   * Looks up or assigns a seed id for a type..
   */
  int getSeedId(JReferenceType type) {
    Integer val = seedIdMap.get(type);
    int seedId = val == null ? 0 : val;

    if (seedId == 0) {
      seedId = nextSeedId++;
      seedIdMap.put(type, seedId);
    }
    return seedId;
  }

  String mangleName(JField x) {
    String s = getNameString(x.getEnclosingType()) + '_' + getNameString(x);
    return s;
  }

  String mangleNameForGlobal(JMethod x) {
    String s = getNameString(x.getEnclosingType()) + '_' + getNameString(x) + "__";
    for (int i = 0; i < x.getOriginalParamTypes().size(); ++i) {
      JType type = x.getOriginalParamTypes().get(i);
      s += type.getJavahSignatureName();
    }
    s += x.getOriginalReturnType().getJavahSignatureName();
    return s;
  }

  String mangleNameForPoly(JMethod x) {
    assert !x.isPrivate() && !x.isStatic();
    StringBuffer sb = new StringBuffer();
    sb.append(getNameString(x));
    sb.append("__");
    for (int i = 0; i < x.getOriginalParamTypes().size(); ++i) {
      JType type = x.getOriginalParamTypes().get(i);
      sb.append(type.getJavahSignatureName());
    }
    sb.append(x.getOriginalReturnType().getJavahSignatureName());
    return sb.toString();
  }

  String mangleNameForPrivatePoly(JMethod x) {
    assert x.isPrivate() && !x.isStatic();
    StringBuffer sb = new StringBuffer();
    /*
     * Private instance methods in different classes should not override each
     * other, so they must have distinct polymorphic names. Therefore, add the
     * class name to the mangled name.
     */
    sb.append("private$");
    sb.append(getNameString(x.getEnclosingType()));
    sb.append("$");
    sb.append(getNameString(x));
    sb.append("__");
    for (int i = 0; i < x.getOriginalParamTypes().size(); ++i) {
      JType type = x.getOriginalParamTypes().get(i);
      sb.append(type.getJavahSignatureName());
    }
    sb.append(x.getOriginalReturnType().getJavahSignatureName());
    return sb.toString();
  }

  String mangleNameSpecialObfuscate(JField x) {
    assert (specialObfuscatedFields.containsKey(x));
    switch (output) {
      case OBFUSCATED:
        return specialObfuscatedFields.get(x);
      case PRETTY:
        return x.getName() + "$";
      case DETAILED:
        return mangleName(x) + "$";
    }
    throw new InternalCompilerException("Unknown output mode");
  }

  String mangleNameSpecialObfuscate(JMethod x) {
    assert (specialObfuscatedMethodSigs.containsKey(x.getSignature()));
    switch (output) {
      case OBFUSCATED:
        return specialObfuscatedMethodSigs.get(x.getSignature());
      case PRETTY:
        return x.getName() + "$";
      case DETAILED:
        return mangleNameForPoly(x) + "$";
    }
    throw new InternalCompilerException("Unknown output mode");
  }

  private Pair<JavaToJavaScriptMap, Set<JsNode>> execImpl() {
    new FixNameClashesVisitor().accept(program);
    CanObserveSubclassUninitializedFieldsVisitor canObserve =
        new CanObserveSubclassUninitializedFieldsVisitor();
    canObserve.accept(program);
    SortVisitor sorter = new SortVisitor();
    sorter.accept(program);
    RecordCrossClassCallsAndJSInlinableMethods recorder =
        new RecordCrossClassCallsAndJSInlinableMethods();
    recorder.accept(program);
    CreateNamesAndScopesVisitor creator = new CreateNamesAndScopesVisitor();
    creator.accept(program);
    GenerateJavaScriptVisitor generator =
        new GenerateJavaScriptVisitor(recorder.methodsForJsInlining);
    generator.accept(program);

    final Map<JsName, JMethod> nameToMethodMap = new HashMap<JsName, JMethod>();
    final HashMap<JsName, JField> nameToFieldMap = new HashMap<JsName, JField>();
    final HashMap<JsName, JClassType> constructorNameToTypeMap = new HashMap<JsName, JClassType>();
    for (JDeclaredType type : program.getDeclaredTypes()) {
      JsName typeName = names.get(type);
      if (type instanceof JClassType && typeName != null) {
        constructorNameToTypeMap.put(typeName, (JClassType) type);
      }
      for (JField field : type.getFields()) {
        if (field.isStatic()) {
          JsName fieldName = names.get(field);
          if (fieldName != null) {
            nameToFieldMap.put(fieldName, field);
          }
        }
      }
      for (JMethod method : type.getMethods()) {
        JsName methodName = names.get(method);
        if (methodName != null) {
          nameToMethodMap.put(methodName, method);
        }
      }
    }

    jsProgram.setIndexedFields(indexedFields);
    jsProgram.setIndexedFunctions(indexedFunctions);

    // TODO(spoon): Instead of gathering the information here, get it via
    // SourceInfo
    JavaToJavaScriptMap jjsMap = new JavaToJavaScriptMap() {
      @Override
      public JsName nameForMethod(JMethod method) {
        return names.get(method);
      }

      @Override
      public JsName nameForType(JClassType type) {
        return names.get(type);
      }

      @Override
      public JField nameToField(JsName name) {
        return nameToFieldMap.get(name);
      }

      @Override
      public JMethod nameToMethod(JsName name) {
        return nameToMethodMap.get(name);
      }

      @Override
      public JClassType nameToType(JsName name) {
        return constructorNameToTypeMap.get(name);
      }

      @Override
      public JClassType typeForStatement(JsStatement stat) {
        return typeForStatMap.get(stat);
      }

      @Override
      public JMethod vtableInitToMethod(JsStatement stat) {
        return vtableInitForMethodMap.get(stat);
      }
    };

    return Pair.create(jjsMap, generator.functionsForJsInlining);
  }
}
