/*
 * 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.dev.jjs.impl.JavaToJavaScriptMap;
import com.google.gwt.dev.js.ast.JsBlock;
import com.google.gwt.dev.js.ast.JsContext;
import com.google.gwt.dev.js.ast.JsExprStmt;
import com.google.gwt.dev.js.ast.JsFunction;
import com.google.gwt.dev.js.ast.JsModVisitor;
import com.google.gwt.dev.js.ast.JsProgram;
import com.google.gwt.dev.js.ast.JsProgramFragment;
import com.google.gwt.dev.js.ast.JsStatement;

import java.util.HashSet;
import java.util.ListIterator;
import java.util.Set;
import java.util.Stack;

/**
 * Force all functions to be evaluated at the top of the lexical scope in which
 * they reside. This makes {@link StaticEvalVisitor} simpler in that we no
 * longer have to worry about function declarations within expressions. After
 * this runs, only statements can contain declarations. Moved functions will end
 * up just before the statement in which they presently reside.
 */
public class EvalFunctionsAtTopScope extends JsModVisitor {

  public static void exec(JsProgram jsProgram, JavaToJavaScriptMap map) {
    EvalFunctionsAtTopScope fev = new EvalFunctionsAtTopScope(map);
    fev.accept(jsProgram);
  }

  private JsStatement currentStatement;

  private final Set<JsFunction> dontMove = new HashSet<JsFunction>();

  private final Stack<ListIterator<JsStatement>> itrStack = new Stack<ListIterator<JsStatement>>();

  private JavaToJavaScriptMap java2jsMap;

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

  public EvalFunctionsAtTopScope(JavaToJavaScriptMap java2jsMap) {
    this.java2jsMap = java2jsMap;
  }

  @Override
  public void endVisit(JsExprStmt x, JsContext ctx) {
    currentStatement = null;
  }

  @Override
  public void endVisit(JsFunction x, JsContext ctx) {
    scopeStack.pop();
  }

  @Override
  public void endVisit(JsProgram x, JsContext ctx) {
    scopeStack.pop();
  }

  @Override
  public void endVisit(JsProgramFragment x, JsContext ctx) {
    scopeStack.pop();
  }

  @Override
  public boolean visit(JsBlock x, JsContext ctx) {
    if (x == scopeStack.peek()) {
      ListIterator<JsStatement> itr = x.getStatements().listIterator();
      itrStack.push(itr);
      while (itr.hasNext()) {
        JsStatement stmt = itr.next();
        JsFunction func = JsStaticEval.isFunctionDecl(stmt);
        // Already at the top level.
        if (func != null) {
          dontMove.add(func);
        }
        accept(stmt);
        if (func != null) {
          dontMove.remove(func);
        }
      }
      itrStack.pop();
      // Already visited.
      return false;
    } else {
      // Just do normal visitation.
      return true;
    }
  }

  @Override
  public boolean visit(JsExprStmt x, JsContext ctx) {
    currentStatement = x;
    return true;
  }

  @Override
  public boolean visit(JsFunction x, JsContext ctx) {
    JsStaticEval.isFunctionDecl(currentStatement);

    /*
     * We do this during visit() to preserve first-to-last evaluation order. We
     * check if this function is a vtable declaration and don't move functions
     * used in other expressions or are in vtable assignments.
     */
    if (x.getName() != null && !dontMove.contains(x)
        && !isVtableDeclaration(currentStatement)) {
      /*
       * Reinsert this function into the statement immediately before the
       * current statement. The current statement will have already been
       * returned from the current iterator's next(), so we have to backshuffle
       * one step to get in front of it.
       */
      ListIterator<JsStatement> itr = itrStack.peek();
      itr.previous();
      itr.add(x.makeStmt());
      itr.next();
      ctx.replaceMe(x.getName().makeRef(x.getSourceInfo().makeChild()));
    }

    // Dive into the function itself.
    scopeStack.push(x.getBody());
    return true;
  }

  @Override
  public boolean visit(JsProgram x, JsContext ctx) {
    scopeStack.push(x.getGlobalBlock());
    return true;
  }

  @Override
  public boolean visit(JsProgramFragment x, JsContext ctx) {
    scopeStack.push(x.getGlobalBlock());
    return true;
  }

  private boolean isVtableDeclaration(JsStatement currentStatement) {
    return java2jsMap.vtableInitToMethod(currentStatement) != null;
  }
}
