/*
 * Copyright 2009 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.js;

import com.google.gwt.core.ext.BadPropertyValueException;
import com.google.gwt.core.ext.PropertyOracle;
import com.google.gwt.core.ext.SelectionProperty;
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.dev.jjs.HasSourceInfo;
import com.google.gwt.dev.jjs.InternalCompilerException;
import com.google.gwt.dev.jjs.SourceInfo;
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.JsCatch;
import com.google.gwt.dev.js.ast.JsContext;
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.JsInvocation;
import com.google.gwt.dev.js.ast.JsModVisitor;
import com.google.gwt.dev.js.ast.JsName;
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.JsPostfixOperation;
import com.google.gwt.dev.js.ast.JsPrefixOperation;
import com.google.gwt.dev.js.ast.JsProgram;
import com.google.gwt.dev.js.ast.JsReturn;
import com.google.gwt.dev.js.ast.JsStatement;
import com.google.gwt.dev.js.ast.JsStringLiteral;
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.JsVisitor;
import com.google.gwt.dev.js.ast.JsWhile;
import com.google.gwt.dev.js.ast.JsVars.JsVar;
import com.google.gwt.dev.util.collect.Lists;
import com.google.gwt.dev.util.collect.Maps;

import java.io.File;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * Emulates the JS stack in order to provide useful stack traces on browers that
 * do not provide useful stack information.
 * 
 * @see com.google.gwt.core.client.impl.StackTraceCreator
 */
public class JsStackEmulator {

  private static final String PROPERTY_NAME = "compiler.stackMode";

  /**
   * Resets the global stack depth to the local stack index and top stack frame
   * after calls to Exceptions.caught. This is created by
   * {@link EntryExitVisitor#visit(JsCatch, JsContext)}.
   */
  private class CatchStackReset extends JsModVisitor {

    /**
     * The local stackIndex variable in the function.
     */
    private final EntryExitVisitor eeVisitor;

    public CatchStackReset(EntryExitVisitor eeVisitor) {
      this.eeVisitor = eeVisitor;
    }

    @Override
    public void endVisit(JsExprStmt x, JsContext<JsStatement> ctx) {
      // Looking for e = caught(e);
      JsExpression expr = x.getExpression();

      if (!(expr instanceof JsBinaryOperation)) {
        return;
      }

      JsBinaryOperation op = (JsBinaryOperation) expr;
      if (!(op.getArg2() instanceof JsInvocation)) {
        return;
      }

      JsInvocation i = (JsInvocation) op.getArg2();
      JsExpression q = i.getQualifier();
      if (!(q instanceof JsNameRef)) {
        return;
      }

      JsName name = ((JsNameRef) q).getName();
      if (name == null) {
        return;
      }

      // caughtFunction is the JsFunction translated from Exceptions.caught
      if (name.getStaticRef() != caughtFunction) {
        return;
      }

      // $stackDepth = stackIndex
      SourceInfo info = x.getSourceInfo().makeChild(JsStackEmulator.class,
          "Resetting stack depth");
      JsBinaryOperation reset = new JsBinaryOperation(info,
          JsBinaryOperator.ASG, stackDepth.makeRef(info),
          eeVisitor.stackIndexRef(info));

      ctx.insertAfter(reset.makeStmt());
    }
  }

  /**
   * The EntryExitVisitor handles pushing and popping frames onto the emulated
   * stack. It will operate on exactly one JsFunction. The basic transformation
   * is to add a push operation at every function entry, and then a pop
   * operation for every statement that might be the final statement executed by
   * the function.
   * <p>
   * General stack depth entry/exit code:
   * 
   * <pre>
   * function foo() {
   *   var stackIndex;
   *   $stack[stackIndex = ++$stackDepth] = foo;
   *   
   *   ... do stuff ..
   *   
   *   $stackDepth = stackIndex - 1;
   * }
   * </pre>
   * <p>
   * For more complicated control flows involving return statements in try
   * blocks with as associated finally block, it is necessary to introduce a
   * local variable to indicate if control flow is expected to terminate
   * normally at the end of the finally block:
   * 
   * <pre>
   * var exitingEarly;
   * try {
   *   if (...) {
   *     return (exitingEarly = true, new Foo());
   *   }
   *   ...
   * } finally {
   *   ... existing finally code ..
   *   exitingEarly && $stackDepth = stackIndex - 1;
   * }
   * </pre>
   * A separate local variable is used for each try/finally nested within a
   * finally block.
   * <p>
   * Try statements without a catch block will have a catch block added to them
   * so that catch blocks are the only places where flow-control may jump to.
   * All catch blocks are altered so that the global $stackDepth variable is
   * reset to the local stack index value. This allows browser-native exceptions
   * to be created with the correct stack trace before the finally code is
   * executed with a correct stack depth.
   * 
   * <pre>
   * try {
   *   foo();
   * } finally {
   *   bar();
   * }
   * </pre>
   * 
   * becomes
   * 
   * <pre>
   * try {
   *   foo();
   * } catch (e) {
   *   e = caught(e);
   *   $stackDepth = stackIndex;
   *   throw e;
   * } finally {
   *   bar();
   * }
   * <p>
   * Note that there is no specific handling for explicit throw statements, as
   * the stack instrumentation must also handle browser-generated exceptions
   * (e.g. <code>null.a()</code>).
   */
  private class EntryExitVisitor extends JsModVisitor {

    /**
     * The name of a function-local variable to hold the invocation's slot in
     * the stack.
     */
    protected JsName stackIndex;

    private final JsFunction currentFunction;

    /**
     * Maps finally blocks to the local variable name which is used to indicate
     * if that finally block will exit the function early. This is a map and not
     * a single value because a finally block might be nested in another exit
     * block.
     */
    private Map<JsBlock, JsName> finallyBlocksToExitVariables = Maps.create();

    /**
     * This variable will indicate the finally block that contains the last
     * statement that will be executed if an unconditional flow control change
     * were to occur within the associated try block.
     */
    private JsBlock outerFinallyBlock;

    /**
     * Used if a return statement's expression could potentially trigger an
     * exception.
     */
    private JsName returnTemp;

    /**
     * Final cleanup for any new local variables that need to be created.
     */
    private List<JsVar> varsToAdd = Lists.create();

    public EntryExitVisitor(JsFunction currentFunction) {
      this.currentFunction = currentFunction;
    }

    /**
     * If the visitor is exiting the current function's block, add additional
     * local variables and the final stack-pop instructions.
     */
    @Override
    public void endVisit(JsBlock x, JsContext<JsStatement> ctx) {
      if (x == currentFunction.getBody()) {

        // Add the entry code
        List<JsStatement> statements = x.getStatements();
        int idx = statements.isEmpty()
            || !(statements.get(0) instanceof JsVars) ? 0 : 1;

        // Add push and pop statements
        statements.add(idx, push(currentFunction));
        addPopAtEndOfBlock(x, false);

        // Add any needed variables
        JsVars vars;
        if (statements.get(0) instanceof JsVars) {
          vars = (JsVars) statements.get(0);
        } else {
          vars = new JsVars(currentFunction.getSourceInfo());
          statements.add(0, vars);
        }
        for (JsVar var : varsToAdd) {
          vars.add(var);
        }
      }
    }

    @Override
    public void endVisit(JsReturn x, JsContext<JsStatement> ctx) {
      if (outerFinallyBlock != null) {
        // There is a finally block, so we need to set the early-exit flag
        JsBinaryOperation asg = new JsBinaryOperation(x.getSourceInfo(),
            JsBinaryOperator.ASG, earlyExitRef(outerFinallyBlock),
            program.getBooleanLiteral(true));
        if (x.getExpr() == null) {
          if (ctx.canInsert()) {
            // exitingEarly = true; return;
            ctx.insertBefore(asg.makeStmt());
          } else {
            // {exitingEarly = true; return;}
            JsBlock block = new JsBlock(x.getSourceInfo());
            block.getStatements().add(asg.makeStmt());
            block.getStatements().add(x);
            ctx.replaceMe(block);
          }
        } else {
          // return (exitingEarly = true, expr);
          JsBinaryOperation op = new JsBinaryOperation(x.getSourceInfo(),
              JsBinaryOperator.COMMA, asg, x.getExpr());
          x.setExpr(op);
        }
      } else {
        if (x.getExpr() != null && x.getExpr().hasSideEffects()) {
          // temp = expr; pop(); return temp;
          SourceInfo info = x.getSourceInfo().makeChild(JsStackEmulator.class,
              "Flow break with side-effect");
          JsBinaryOperation asg = new JsBinaryOperation(info,
              JsBinaryOperator.ASG, returnTempRef(info), x.getExpr());
          x.setExpr(returnTempRef(info));
          pop(x, asg, ctx);
        } else {
          // Otherwise, pop the stack frame
          pop(x, null, ctx);
        }
      }
    }

    /**
     * We want to look at unaltered versions of the catch block, so this is a
     * <code>visit<code> and not a <code>endVisit</code>.
     */
    @Override
    public boolean visit(JsCatch x, JsContext<JsCatch> ctx) {
      // Reset the stack depth to the local index
      new CatchStackReset(this).accept(x);
      return true;
    }

    @Override
    public boolean visit(JsFunction x, JsContext<JsExpression> ctx) {
      // Will be taken care of by the Bootstrap visitor
      return false;
    }

    @Override
    public boolean visit(JsTry x, JsContext<JsStatement> ctx) {

      /*
       * Only the outermost finally block needs special treatment; try/finally
       * block within try blocks do not receive special treatment.
       */
      JsBlock finallyBlock = x.getFinallyBlock();
      if (finallyBlock != null && outerFinallyBlock == null) {
        outerFinallyBlock = finallyBlock;

        // Manual traversal
        accept(x.getTryBlock());

        if (x.getCatches().isEmpty()) {
          JsCatch c = makeSyntheticCatchBlock(x);
          x.getCatches().add(c);
        }
        assert x.getCatches().size() >= 1;
        acceptList(x.getCatches());

        // Exceptions in the finally block just exit the function
        assert outerFinallyBlock == finallyBlock;
        outerFinallyBlock = null;
        accept(finallyBlock);

        // Stack-pop instruction
        addPopAtEndOfBlock(finallyBlock, true);

        // Clean up entry after adding pop instruction
        finallyBlocksToExitVariables = Maps.remove(
            finallyBlocksToExitVariables, finallyBlock);
        return false;
      }

      // Normal visit
      return true;
    }

    /**
     * Create a reference to the function-local stack index variable, possibly
     * allocating it.
     */
    protected JsNameRef stackIndexRef(SourceInfo info) {
      if (stackIndex == null) {
        stackIndex = currentFunction.getScope().declareName(
            "JsStackEmulator_stackIndex", "stackIndex");

        JsVar var = new JsVar(info, stackIndex);
        varsToAdd = Lists.add(varsToAdd, var);
      }
      return stackIndex.makeRef(info);
    }

    /**
     * Code-gen function for generating the stack-pop statement at the end of a
     * block. A no-op if the last statement is a <code>throw</code> or
     * <code>return</code> statement, since it will have already caused a pop
     * statement to have been added.
     * 
     * @param checkEarlyExit if <code>true</code>, generates
     *          <code>earlyExit && pop()</code>
     */
    private void addPopAtEndOfBlock(JsBlock x, boolean checkEarlyExit) {
      JsStatement last = x.getStatements().isEmpty() ? null
          : x.getStatements().get(x.getStatements().size() - 1);
      if (last instanceof JsReturn || last instanceof JsThrow) {
        /*
         * Don't need a pop after a throw or break statement. This is an
         * optimization for the common case of returning a value as the last
         * statement, but doesn't cover all flow-control cases.
         */
        return;
      } else if (checkEarlyExit && !finallyBlocksToExitVariables.containsKey(x)) {
        /*
         * No early-exit variable was ever allocated for this block. This means
         * that the variable can never be true, and thus the stack-popping
         * expression will never be executed.
         */
        return;
      }

      // pop()
      SourceInfo info = x.getSourceInfo().makeChild(JsStackEmulator.class,
          "Stack exit");
      JsExpression op = pop(info);

      if (checkEarlyExit) {
        // earlyExit && pop()
        op = new JsBinaryOperation(info, JsBinaryOperator.AND, earlyExitRef(x),
            op);
      }

      x.getStatements().add(op.makeStmt());
    }

    /**
     * Generate a name reference to the early-exit variable for a given block,
     * possibly allocating a new variable.
     */
    private JsNameRef earlyExitRef(JsBlock x) {
      JsName earlyExitName = finallyBlocksToExitVariables.get(x);
      if (earlyExitName == null) {
        earlyExitName = currentFunction.getScope().declareName(
            "JsStackEmulator_exitingEarly"
                + finallyBlocksToExitVariables.size(), "exitingEarly");

        finallyBlocksToExitVariables = Maps.put(finallyBlocksToExitVariables,
            x, earlyExitName);
        JsVar var = new JsVar(x.getSourceInfo(), earlyExitName);
        varsToAdd = Lists.add(varsToAdd, var);
      }
      return earlyExitName.makeRef(x.getSourceInfo());
    }

    private JsCatch makeSyntheticCatchBlock(JsTry x) {
      /*
       * catch (e) { e = caught(e); throw e; }
       */
      SourceInfo info = x.getSourceInfo().makeChild(JsStackEmulator.class,
          "Synthetic catch block to fix stack depth");

      JsCatch c = new JsCatch(info, currentFunction.getScope(), "e");
      JsName paramName = c.getParameter().getName();

      // caught(e)
      JsInvocation caughtCall = new JsInvocation(info);
      caughtCall.setQualifier(caughtFunction.getName().makeRef(info));
      caughtCall.getArguments().add(paramName.makeRef(info));

      // e = caught(e)
      JsBinaryOperation asg = new JsBinaryOperation(info, JsBinaryOperator.ASG,
          paramName.makeRef(info), caughtCall);

      // throw e
      JsThrow throwStatement = new JsThrow(info, paramName.makeRef(info));

      JsBlock body = new JsBlock(info);
      body.getStatements().add(asg.makeStmt());
      body.getStatements().add(throwStatement);
      c.setBody(body);
      return c;
    }

    /**
     * Pops the stack frame.
     * 
     * @param x the statement that will cause the pop
     * @param ctx the visitor context
     */
    private void pop(JsStatement x, JsExpression expr,
        JsContext<JsStatement> ctx) {
      // $stackDepth = stackIndex - 1
      SourceInfo info = x.getSourceInfo().makeChild(JsStackEmulator.class,
          "Stack exit");

      JsExpression op = pop(info);

      if (ctx.canInsert()) {
        if (expr != null) {
          ctx.insertBefore(expr.makeStmt());
        }
        ctx.insertBefore(op.makeStmt());
      } else {
        JsBlock block = new JsBlock(info);
        if (expr != null) {
          block.getStatements().add(expr.makeStmt());
        }
        block.getStatements().add(op.makeStmt());
        block.getStatements().add(x);
        ctx.replaceMe(block);
      }
    }

    /**
     * Decrement the $stackDepth variable.
     */
    private JsExpression pop(SourceInfo info) {
      JsBinaryOperation sub = new JsBinaryOperation(info, JsBinaryOperator.SUB,
          stackIndexRef(info), program.getNumberLiteral(1));
      JsBinaryOperation op = new JsBinaryOperation(info, JsBinaryOperator.ASG,
          stackDepth.makeRef(info), sub);
      return op;
    }

    /**
     * Create the function-entry code.
     */
    private JsStatement push(HasSourceInfo x) {
      SourceInfo info = x.getSourceInfo().makeChild(JsStackEmulator.class,
          "Stack entry code");

      JsNameRef stackRef = stack.makeRef(info);
      JsNameRef stackDepthRef = stackDepth.makeRef(info);
      JsExpression currentFunctionRef;
      if (currentFunction.getName() == null) {
        // Anonymous
        currentFunctionRef = program.getNullLiteral();
      } else {
        currentFunctionRef = currentFunction.getName().makeRef(info);
      }

      // ++stackDepth
      JsUnaryOperation inc = new JsPrefixOperation(info, JsUnaryOperator.INC,
          stackDepthRef);

      // stackIndex = ++stackDepth
      JsBinaryOperation stackIndexOp = new JsBinaryOperation(info,
          JsBinaryOperator.ASG, stackIndexRef(info), inc);

      // stack[stackIndex = ++stackDepth]
      JsArrayAccess access = new JsArrayAccess(info, stackRef, stackIndexOp);

      // stack[stackIndex = ++stackDepth] = currentFunction
      JsBinaryOperation op = new JsBinaryOperation(info, JsBinaryOperator.ASG,
          access, currentFunctionRef);

      return op.makeStmt();
    }

    private JsNameRef returnTempRef(SourceInfo info) {
      if (returnTemp == null) {
        returnTemp = currentFunction.getScope().declareName(
            "JsStackEmulator_returnTemp", "returnTemp");

        JsVar var = new JsVar(info, returnTemp);
        varsToAdd = Lists.add(varsToAdd, var);
      }
      return returnTemp.makeRef(info);
    }
  }

  /**
   * Creates a visitor to instrument each JsFunction in the program.
   */
  private class InstrumentAllFunctions extends JsVisitor {
    @Override
    public void endVisit(JsFunction x, JsContext<JsExpression> ctx) {
      if (!x.getBody().getStatements().isEmpty()) {
        if (recordLineNumbers) {
          (new LocationVisitor(x)).accept(x.getBody());
        } else {
          (new EntryExitVisitor(x)).accept(x.getBody());
        }
      }
    }
  }

  /**
   * Extends EntryExit visitor to record location information in the AST. This
   * visitor will modify every JsExpression that can potentially result in a
   * change of flow control with file and line number data.
   * <p>
   * This simply generates code to set entries in the <code>$location</code>
   * stack, parallel to <code>$stack</code>:
   * 
   * <pre>
   * ($location[stackIndex] = 'Foo.java:' + 42, expr);
   * </pre>
   * 
   * Inclusion of file names is dependent on the value of the
   * {@link JsStackEmulator#recordFileNames} field.
   */
  private class LocationVisitor extends EntryExitVisitor {
    private String lastFile;
    private int lastLine;

    /**
     * Nodes in this set are used in a context that expects a reference, not
     * just an arbitrary expression. For example, <code>delete</code> takes a
     * reference. These are tracked because it wouldn't be safe to rewrite
     * <code>delete foo.bar</code> to <code>delete (line='123',foo).bar</code>.
     */
    private final Set<JsNode<?>> nodesInRefContext = new HashSet<JsNode<?>>();

    public LocationVisitor(JsFunction function) {
      super(function);
      resetPosition();
    }

    @Override
    public void endVisit(JsArrayAccess x, JsContext<JsExpression> ctx) {
      record(x, ctx);
    }

    @Override
    public void endVisit(JsBinaryOperation x, JsContext<JsExpression> ctx) {
      if (x.getOperator().isAssignment()) {
        record(x, ctx);
      }
    }

    @Override
    public void endVisit(JsInvocation x, JsContext<JsExpression> ctx) {
      nodesInRefContext.remove(x.getQualifier());
      record(x, ctx);
    }

    @Override
    public void endVisit(JsNameRef x, JsContext<JsExpression> ctx) {
      record(x, ctx);
    }

    @Override
    public void endVisit(JsNew x, JsContext<JsExpression> ctx) {
      record(x, ctx);
    }

    @Override
    public void endVisit(JsPostfixOperation x, JsContext<JsExpression> ctx) {
      record(x, ctx);
    }

    @Override
    public void endVisit(JsPrefixOperation x, JsContext<JsExpression> ctx) {
      record(x, ctx);
      nodesInRefContext.remove(x.getArg());
    }

    /**
     * This is essentially a hacked-up version of JsFor.traverse to account for
     * flow control differing from visitation order. It resets lastFile and
     * lastLine before the condition and increment expressions in the for loop
     * so that location data will be recorded correctly.
     */
    @Override
    public boolean visit(JsFor x, JsContext<JsStatement> ctx) {
      if (x.getInitExpr() != null) {
        x.setInitExpr(accept(x.getInitExpr()));
      } else if (x.getInitVars() != null) {
        x.setInitVars(accept(x.getInitVars()));
      }

      if (x.getCondition() != null) {
        resetPosition();
        x.setCondition(accept(x.getCondition()));
      }

      if (x.getIncrExpr() != null) {
        resetPosition();
        x.setIncrExpr(accept(x.getIncrExpr()));
      }

      accept(x.getBody());
      return false;
    }

    @Override
    public boolean visit(JsInvocation x, JsContext<JsExpression> ctx) {
      nodesInRefContext.add(x.getQualifier());
      return true;
    }

    @Override
    public boolean visit(JsPrefixOperation x, JsContext<JsExpression> ctx) {
      if (x.getOperator() == JsUnaryOperator.DELETE
          || x.getOperator() == JsUnaryOperator.TYPEOF) {
        nodesInRefContext.add(x.getArg());
      }
      return true;
    }

    /**
     * Similar to JsFor, this resets the current location information before
     * evaluating the condition.
     */
    @Override
    public boolean visit(JsWhile x, JsContext<JsStatement> ctx) {
      resetPosition();
      x.setCondition(accept(x.getCondition()));
      accept(x.getBody());
      return false;
    }

    /**
     * Strips off the final name segment.
     */
    private String baseName(String fileName) {
      // Try the system path separator
      int lastIndex = fileName.lastIndexOf(File.separator);
      if (lastIndex == -1) {
        // Otherwise, try URL path separator
        lastIndex = fileName.lastIndexOf('/');
      }
      if (lastIndex != -1) {
        return fileName.substring(lastIndex + 1);
      } else {
        return fileName;
      }
    }

    private void record(JsExpression x, JsContext<JsExpression> ctx) {
      if (ctx.isLvalue()) {
        // Assignments to comma expressions aren't legal
        return;
      } else if (nodesInRefContext.contains(x)) {
        // Don't modify references into non-references
        return;
      } else if (x.getSourceInfo().getStartLine() == lastLine
          && (!recordFileNames || x.getSourceInfo().getFileName().equals(
              lastFile))) {
        // Same location; ignore
        return;
      }

      SourceInfo info = x.getSourceInfo().makeChild(JsStackEmulator.class,
          "Synthetic location data");

      // ($locations[stackIndex] = fileName + lineNumber, x)
      JsExpression location = program.getStringLiteral(info,
          String.valueOf(lastLine = info.getStartLine()));
      if (recordFileNames) {
        // 'fileName:' + lineNumber
        JsStringLiteral stringLit = program.getStringLiteral(info,
            baseName(lastFile = info.getFileName()) + ":");
        location = new JsBinaryOperation(info, JsBinaryOperator.ADD, stringLit,
            location);
      }

      JsArrayAccess access = new JsArrayAccess(info, lineNumbers.makeRef(info),
          stackIndexRef(info));
      JsBinaryOperation asg = new JsBinaryOperation(info, JsBinaryOperator.ASG,
          access, location);

      JsBinaryOperation comma = new JsBinaryOperation(info,
          JsBinaryOperator.COMMA, asg, x);

      ctx.replaceMe(comma);
    }

    private void resetPosition() {
      lastFile = "";
      lastLine = -1;
    }
  }

  /**
   * The StackTraceCreator code refers to identifiers defined in JsRootScope,
   * which are unobfuscatable. This visitor replaces references to those symbols
   * with references to our locally-defined, obfuscatable names.
   */
  private class ReplaceUnobfuscatableNames extends JsModVisitor {
    private final JsName rootLineNumbers = program.getRootScope().findExistingUnobfuscatableName(
        "$location");
    // See JsRootScope for the definition of these names
    private final JsName rootStack = program.getRootScope().findExistingUnobfuscatableName(
        "$stack");
    private final JsName rootStackDepth = program.getRootScope().findExistingUnobfuscatableName(
        "$stackDepth");

    @Override
    public void endVisit(JsNameRef x, JsContext<JsExpression> ctx) {
      JsName name = x.getName();
      JsNameRef newRef = null;

      if (name == rootStack) {
        newRef = stack.makeRef(x.getSourceInfo());
      } else if (name == rootStackDepth) {
        newRef = stackDepth.makeRef(x.getSourceInfo());
      } else if (name == rootLineNumbers) {
        newRef = lineNumbers.makeRef(x.getSourceInfo());
      }

      if (newRef == null) {
        return;
      }

      assert x.getQualifier() == null;
      ctx.replaceMe(newRef);
    }
  }

  /**
   * Corresponds to property compiler.stackMode in EmulateJsStack.gwt.xml
   * module.
   */
  public enum StackMode {
    STRIP, NATIVE, EMULATED;
  }
  
  public static void exec(JsProgram program, PropertyOracle[] propertyOracles) {
    if (getStackMode(propertyOracles) == StackMode.EMULATED) {
      (new JsStackEmulator(program, propertyOracles)).execImpl();
    }
  }

  public static StackMode getStackMode(PropertyOracle[] propertyOracles) {
    SelectionProperty property;
    try {
      property = propertyOracles[0].getSelectionProperty(TreeLogger.NULL,
          PROPERTY_NAME);
    } catch (BadPropertyValueException e) {
      // Should be inherited via Core.gwt.xml
      throw new InternalCompilerException("Expected property " + PROPERTY_NAME
          + " not defined", e);
    }

    String value = property.getCurrentValue();
    assert value != null : property.getName() + " did not have a value";
    StackMode stackMode = StackMode.valueOf(value.toUpperCase());
    // Check for multiply defined properties
    if (propertyOracles.length > 1) {
      for (int i = 1; i < propertyOracles.length; ++i) {
        try {
          property = propertyOracles[i].getSelectionProperty(TreeLogger.NULL,
              PROPERTY_NAME);
        } catch (BadPropertyValueException e) {
          // OK! 
        }
        assert value.equals(property.getCurrentValue()) : 
            "compiler.stackMode property has multiple values.";
      }
    }
    return stackMode;
  }

  private JsFunction caughtFunction;
  private JsName lineNumbers;
  private final JsProgram program;
  private boolean recordFileNames;
  private boolean recordLineNumbers;
  private JsName stack;
  private JsName stackDepth;

  private JsStackEmulator(JsProgram program, PropertyOracle[] propertyOracles) {
    this.program = program;

    assert propertyOracles.length > 0;
    PropertyOracle oracle = propertyOracles[0];
    try {
      List<String> values = oracle.getConfigurationProperty(
          "compiler.emulatedStack.recordFileNames").getValues();
      recordFileNames = Boolean.valueOf(values.get(0));

      values = oracle.getConfigurationProperty(
          "compiler.emulatedStack.recordLineNumbers").getValues();
      recordLineNumbers = recordFileNames || Boolean.valueOf(values.get(0));
    } catch (BadPropertyValueException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
  }

  private void execImpl() {
    caughtFunction = program.getIndexedFunction("Exceptions.caught");
    if (caughtFunction == null) {
      // No exceptions caught? Weird, but possible.
      return;
    }
    initNames();
    makeVars();
    (new ReplaceUnobfuscatableNames()).accept(program);
    (new InstrumentAllFunctions()).accept(program);
  }

  private void initNames() {
    stack = program.getScope().declareName("$JsStackEmulator_stack", "$stack");
    stackDepth = program.getScope().declareName("$JsStackEmulator_stackDepth",
        "$stackDepth");
    lineNumbers = program.getScope().declareName("$JsStackEmulator_location",
        "$location");
  }

  private void makeVars() {
    SourceInfo info = program.getSourceInfo().makeChild(JsStackEmulator.class,
        "Emulated stack data");
    JsVar stackVar = new JsVar(info, stack);
    stackVar.setInitExpr(new JsArrayLiteral(info));
    JsVar stackDepthVar = new JsVar(info, stackDepth);
    stackDepthVar.setInitExpr(program.getNumberLiteral(info, -1));
    JsVar lineNumbersVar = new JsVar(info, lineNumbers);
    lineNumbersVar.setInitExpr(new JsArrayLiteral(info));

    JsVars vars;
    JsStatement first = program.getGlobalBlock().getStatements().get(0);
    if (first instanceof JsVars) {
      vars = (JsVars) first;
    } else {
      vars = new JsVars(info);
      program.getGlobalBlock().getStatements().add(0, vars);
    }
    vars.add(stackVar);
    vars.add(stackDepthVar);
    vars.add(lineNumbersVar);
  }
}
