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

import com.google.gwt.dev.jjs.SourceInfo;
import com.google.gwt.dev.js.ast.JsBlock;
import com.google.gwt.dev.js.ast.JsCase;
import com.google.gwt.dev.js.ast.JsContext;
import com.google.gwt.dev.js.ast.JsDefault;
import com.google.gwt.dev.js.ast.JsProgram;
import com.google.gwt.dev.js.ast.JsStatement;
import com.google.gwt.dev.js.ast.JsSwitchMember;
import com.google.gwt.dev.js.ast.JsVisitor;

import java.util.List;
import java.util.ListIterator;

/**
 * Some versions of IE7 have a limit on the number of statements that can appear
 * within a JsBlock. This visitor will restructure blocks and other block-like
 * structures with too many statements in order to reduce the total number of
 * statements that appear within any given block to fewer than
 * {@value #MAX_BLOCK_SIZE} statements by creating nested blocks:  
 * 
 * <pre>
 * {
 *   { statements }
 *   { statements }
 *   remainder of statements
 * }
 * </pre>
 * 
 * This change is purely structural, it will not affect code flow.
 */
public class JsIEBlockSizeVisitor {

  /**
   * Visits every block-like structure.
   */
  private static class BlockVisitor extends JsVisitor {

    private final JsProgram program;

    public BlockVisitor(JsProgram program) {
      this.program = program;
    }

    @Override
    public void endVisit(JsBlock x, JsContext<JsStatement> ctx) {
      // JsFunctionClusterer handles restructuring top-level statement blocks
      if (!x.isGlobalBlock()) {
        restructure(x.getStatements());
      }
    }

    @Override
    public void endVisit(JsCase x, JsContext<JsSwitchMember> ctx) {
      restructure(x.getStmts());
    }

    @Override
    public void endVisit(JsDefault x, JsContext<JsSwitchMember> ctx) {
      restructure(x.getStmts());
    }

    /**
     * Perform the restructuring on a list of statements. Blocks are created as
     * necessary to prevent any given block from exceeding the maximum size.
     */
    private void restructure(List<JsStatement> statements) {
      SourceInfo sourceInfo = program.createSourceInfoSynthetic(
          JsIEBlockSizeVisitor.class, "Restructured to reduce block size");
      // This outer loop will collapse the newly-created block into super-blocks
      while (statements.size() > MAX_BLOCK_SIZE) {
        ListIterator<JsStatement> i = statements.listIterator();
        List<JsStatement> statementsInNewBlock = null;

        // This loop represents a single fold over the list of statements
        while (statements.size() > MAX_BLOCK_SIZE && i.hasNext()) {
          JsStatement current = i.next();

          if (statementsInNewBlock == null) {
            // Replace the current statement with a new block
            JsBlock newBlock = new JsBlock(sourceInfo);
            statementsInNewBlock = newBlock.getStatements();
            i.set(newBlock);
          } else {
            /*
             * There's an open replacement block, remove the statement from its
             * current block.
             */
            i.remove();
          }

          // Move the statement into the new block
          statementsInNewBlock.add(current);

          /*
           * If we hit the cap on a new block, discard the reference to create a
           * new block for the next statement that we see.
           */
          if (statementsInNewBlock.size() == MAX_BLOCK_SIZE) {
            statementsInNewBlock = null;
          }
        }
      }
      assert statements.size() <= MAX_BLOCK_SIZE;
    }
  }

  // Use this value instead to test the effects of the visitor
  // private static final int MAX_BLOCK_SIZE = 1 << 5;

  private static final int MAX_BLOCK_SIZE = 1 << 15 - 1;

  /**
   * Entry point.
   */
  public static void exec(JsProgram program) {
    (new BlockVisitor(program)).accept(program);
  }
}
