/*
* Copyright 2013 Guidewire Software, Inc.
*/
package gw.internal.gosu.ir.compiler.bytecode.statement;
import gw.internal.gosu.ir.compiler.bytecode.AbstractBytecodeCompiler;
import gw.internal.gosu.ir.compiler.bytecode.IRBytecodeContext;
import gw.internal.gosu.ir.compiler.bytecode.IRBytecodeCompiler;
import gw.lang.ir.statement.IRReturnStatement;
import gw.lang.ir.statement.IRWhileStatement;
import gw.internal.ext.org.objectweb.asm.Opcodes;
import gw.internal.ext.org.objectweb.asm.Label;
public class IRWhileStatementCompiler extends AbstractBytecodeCompiler
{
public static void compile( IRWhileStatement whileLoopStatement, IRBytecodeContext context )
{
Label breakLabel = new Label();
Label conditionLabel = new Label();
Label loopBodyStart = new Label();
context.pushBreakLabel( breakLabel);
context.pushContinueLabel( conditionLabel );
context.pushScope();
try
{
// apparently this is true iff the body is guaranteed to execute only once and return
// Really, this should test if the loop is infinite save returns/throws and
// then generate the appropriate bytecode
if( whileLoopStatement.getLeastSignificantTerminalStatement() != null)
{
context.visitLabel( conditionLabel );
IRBytecodeCompiler.compileIRStatement( whileLoopStatement.getBody(), context );
context.visitLabel( breakLabel );
}
else
{
context.getMv().visitJumpInsn( Opcodes.GOTO, conditionLabel ); // jump to condition
context.visitLabel( loopBodyStart ); // body start
IRBytecodeCompiler.compileIRStatement( whileLoopStatement.getBody(), context );
context.visitLabel( conditionLabel );
context.setLineNumber( whileLoopStatement.getLineNumber() ); // ensure loop test has line number matching start of while loop stmt
IRBytecodeCompiler.compileIRExpression( whileLoopStatement.getLoopTest(), context );
context.getMv().visitJumpInsn( Opcodes.IFNE, loopBodyStart );
context.getMv().visitLabel( breakLabel );
IRReturnStatement implicitReturn = whileLoopStatement.getImplicitReturnStatement();
if( implicitReturn != null ) {
IRBytecodeCompiler.compileIRStatement( implicitReturn, context );
}
}
}
finally
{
context.popScope();
context.popBreakLabel();
context.popContinueLabel();
}
}
}