/*
* Copyright 2013 Guidewire Software, Inc.
*/
package gw.internal.gosu.ir.compiler.bytecode;
import gw.internal.gosu.compiler.NamedLabel;
import gw.lang.ir.IRElement;
import gw.lang.ir.IRStatement;
import gw.lang.ir.statement.IRBreakStatement;
import gw.lang.ir.statement.IRContinueStatement;
import gw.lang.ir.statement.IRLoopStatement;
import gw.lang.ir.statement.IRTerminalStatement;
import gw.lang.ir.statement.IRTryCatchFinallyStatement;
import gw.lang.ir.statement.IRSwitchStatement;
import gw.internal.ext.org.objectweb.asm.Label;
import java.util.ArrayList;
import java.util.List;
public class IRFinallyCodePartitioner
{
private IRBytecodeContext _context;
private IRTryCatchFinallyStatement _tryCatchFinallyStmt;
private List<Label> _finallyStarts;
private List<Label> _finallyEnds;
public IRFinallyCodePartitioner( IRBytecodeContext context, IRTryCatchFinallyStatement tryCatchFinallyStmt )
{
_context = context;
_tryCatchFinallyStmt = tryCatchFinallyStmt;
_finallyStarts = new ArrayList<Label>();
_finallyEnds = new ArrayList<Label>();
}
public String toString()
{
return _tryCatchFinallyStmt.getFinallyBody().toString();
}
public void inlineFinally()
{
Label startLabel = new NamedLabel( "FinallyStart" + _finallyStarts.size() );
_finallyStarts.add( startLabel );
_context.visitLabel( startLabel );
IRBytecodeCompiler.compileIRStatement( _tryCatchFinallyStmt.getFinallyBody(), _context );
}
public List<Label> getFinallyStarts() {
return _finallyStarts;
}
public List<Label> getFinallyEnds() {
return _finallyEnds;
}
public boolean appliesTo( IRTerminalStatement elt )
{
return applies( _tryCatchFinallyStmt, elt );
}
public static boolean applies( IRStatement statement, IRTerminalStatement terminal )
{
if( isContainedControlFlow( terminal, statement ) )
{
return false;
}
return true;
}
private static boolean isContainedControlFlow( IRTerminalStatement elt, IRStatement stmt )
{
if( elt instanceof IRBreakStatement || elt instanceof IRContinueStatement)
{
return elementIsEnclosedBy( (IRElement) elt, IRLoopStatement.class, stmt ) ||
elementIsEnclosedBy( (IRElement) elt, IRSwitchStatement.class, stmt );
}
else
{
return false;
}
}
private static boolean elementIsEnclosedBy( IRElement elt, Class enclosedType, IRStatement stmt )
{
if( elt == null || elt == stmt )
{
return false;
}
else if( enclosedType.isAssignableFrom( elt.getClass() ) )
{
return true;
}
else
{
return elementIsEnclosedBy( elt.getParent(), enclosedType, stmt );
}
}
public void endInlineFinally( Label endLabel )
{
_finallyEnds.add( endLabel );
}
}