/*
 * Copyright 2014 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.ConditionContext;
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 )
  {
    // 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 )
    {
      Label breakLabel = new Label();
      Label conditionLabel = new Label();

      context.pushBreakLabel( breakLabel );
      context.pushContinueLabel( conditionLabel );
      context.pushScope();
      try
      {
        context.visitLabel( conditionLabel );

        IRBytecodeCompiler.compileIRStatement( whileLoopStatement.getBody(), context );

        context.visitLabel( breakLabel );
      }
      finally
      {
        context.popScope();
        context.popBreakLabel();
        context.popContinueLabel();
      }
    }
    else
    {
      ConditionContext conditionContext = whileLoopStatement.getLoopTest().getConditionContext();
      Label breakLabel = conditionContext.generateFalseLabel();
      Label conditionLabel = new Label();

      context.pushBreakLabel( breakLabel );
      context.pushContinueLabel( conditionLabel );
      context.pushScope();
      try
      {
        //todo: why do we visit from context and not from mv?
        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( negateOpcode( conditionContext.getOperator() ), breakLabel );
        conditionContext.fixLabels( true, context.getMv() );
        IRBytecodeCompiler.compileIRStatement( whileLoopStatement.getBody(), context );
        context.getMv().visitJumpInsn( Opcodes.GOTO, conditionLabel ); // jump to condition
        conditionContext.fixLabels( false, context.getMv() );
        context.getMv().visitLabel( breakLabel );
      }
      finally
      {
        context.popScope();
        context.popBreakLabel();
        context.popContinueLabel();
      }
    }
  }
}

@@ -1518,250 +1518,44 @@
     
-ConditionContext conditionContext = whileLoopStatement.getLoopTest().getConditionContext();%0A      Label breakLabel = conditionContext.generateFalseLabel();%0A      Label conditionLabel = new Label();%0A%0A      context.pushBreakLabel( breakLabel );
+Label conditionLabel = new Label();%0A
 %0A   
@@ -1651,70 +1651,8 @@
   %7B%0A
-        //todo: why do we visit from context and not from mv?%0A
     
@@ -1917,32 +1917,198 @@
 t(), context );%0A
+        ConditionContext conditionContext = whileLoopStatement.getLoopTest().getConditionContext();%0A        Label breakLabel = conditionContext.generateFalseLabel();%0A
         context.
@@ -2184,32 +2184,78 @@
 , breakLabel );%0A
+        context.pushBreakLabel( breakLabel );%0A
         conditio
@@ -2545,58 +2545,8 @@
  );%0A
-        context.getMv().visitLabel( breakLabel );%0A
     

Fix code generation of the break's label in the while loop: push the label AFTER the while condition is compiled