/* * 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.IRForEachStatement; import gw.lang.ir.IRStatement; import gw.internal.ext.org.objectweb.asm.Opcodes; import gw.internal.ext.org.objectweb.asm.Label; public class IRForEachStatementCompiler extends AbstractBytecodeCompiler { public static void compile( IRForEachStatement forLoop, IRBytecodeContext context ) { Label breakLabel = new Label(); Label conditionLabel = new Label(); Label loopBodyStart = new Label(); context.pushBreakLabel( breakLabel ); context.pushContinueLabel( conditionLabel ); context.pushScope(); try { for( IRStatement initializer : forLoop.getInitializers() ) { IRBytecodeCompiler.compileIRStatement( initializer, context ); } if( forLoop.hasIdentifierToNullCheck() ) { IRBytecodeCompiler.compileIRExpression( forLoop.getIdentifierToNullCheck(), context ); context.getMv().visitJumpInsn( Opcodes.IFNULL, breakLabel ); } // if the for loop is terminal, there is no need to increment, just test and go context.getMv().visitJumpInsn( Opcodes.GOTO, conditionLabel ); // jump to condition context.visitLabel( loopBodyStart ); // body start // increments for( IRStatement incrementors : forLoop.getIncrementors() ) { IRBytecodeCompiler.compileIRStatement( incrementors, context ); } IRBytecodeCompiler.compileIRStatement( forLoop.getBody(), context ); context.visitLabel( conditionLabel ); context.setLineNumber( forLoop.getLineNumber() ); // ensure loop test has line number matching start of for-each stmt IRBytecodeCompiler.compileIRExpression( forLoop.getLoopTest(), context ); context.getMv().visitJumpInsn( Opcodes.IFNE, loopBodyStart ); context.getMv().visitLabel( breakLabel ); } finally { context.popScope(); context.popBreakLabel(); context.popContinueLabel(); } } }