/* * Copyright 2013 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.dev.jjs.SourceInfo; import com.google.gwt.dev.jjs.ast.Context; import com.google.gwt.dev.jjs.ast.JDeclarationStatement; import com.google.gwt.dev.jjs.ast.JLocal; import com.google.gwt.dev.jjs.ast.JMethodBody; import com.google.gwt.dev.jjs.ast.JProgram; import com.google.gwt.dev.jjs.ast.JStatement; import com.google.gwt.dev.jjs.ast.JType; import com.google.gwt.thirdparty.guava.common.collect.Queues; import java.util.Deque; /** * A JModVisitor capable of creating temporary local variables and placing their declarations in an * appropriate preceding place. */ public abstract class JModVisitorWithTemporaryVariableCreation extends JChangeTrackingVisitor { /** * Stack to keep track of where to insert the new variable declaration. * The top of the stack is the statement where declarations will be inserted. */ private final Deque<Context> currentDeclarationInsertionPoint = Queues.newArrayDeque(); public JModVisitorWithTemporaryVariableCreation(OptimizerContext optimizerCtx) { super(optimizerCtx); } @Override public final void endVisit(JStatement x, Context ctx) { if (ctx.canInsert()) { Context popped = currentDeclarationInsertionPoint.pop(); assert popped == ctx; } super.endVisit(x, ctx); } @Override public final boolean visit(JStatement x, Context ctx) { if (ctx.canInsert()) { currentDeclarationInsertionPoint.push(ctx); } return super.visit(x, ctx); } /** * Gets a new temporary local variable name in the current method body. * Locals might have duplicate names as they are always referred to by reference and name * collisions are fixed by {@link NameClashesFixer}. */ protected JLocal createTempLocal(SourceInfo info, JType type, String temporaryLocalName) { assert !getCurrentMethod().isJsniMethod(); JMethodBody currentMethodBody = (JMethodBody) getCurrentMethod().getBody(); JLocal local = JProgram.createLocal(info, temporaryLocalName, type, false, currentMethodBody); JDeclarationStatement declarationStatement = new JDeclarationStatement(info, local.makeRef(info), null); currentDeclarationInsertionPoint.peek().insertBefore(declarationStatement); return local; } }