001 package railo.transformer.bytecode.visitor; 002 003 import org.objectweb.asm.Label; 004 import org.objectweb.asm.Opcodes; 005 import org.objectweb.asm.commons.GeneratorAdapter; 006 007 import railo.transformer.bytecode.BytecodeContext; 008 import railo.transformer.bytecode.util.ExpressionUtil; 009 import railo.transformer.bytecode.util.Types; 010 011 public final class ForIntVisitor implements Opcodes, LoopVisitor { 012 013 private Label beforeInit=new Label(); 014 private Label beforeExpr=new Label(),afterExpr=new Label(); 015 private Label beforeBody=new Label(),afterBody=new Label(); 016 private Label beforeUpdate=new Label(),afterUpdate=new Label(); 017 private int i; 018 019 public int visitBeforeExpression(GeneratorAdapter adapter, int start, int step, boolean isLocal) { 020 // init 021 adapter.visitLabel(beforeInit); 022 forInit(adapter, start, isLocal); 023 adapter.goTo(beforeExpr); 024 025 // update 026 adapter.visitLabel(beforeUpdate); 027 forUpdate(adapter, step, isLocal); 028 029 // expression 030 adapter.visitLabel(beforeExpr); 031 return i; 032 } 033 034 public void visitAfterExpressionBeginBody(GeneratorAdapter adapter) { 035 adapter.ifZCmp(Opcodes.IFEQ, afterBody); 036 } 037 038 public void visitEndBody(BytecodeContext bc,int line) { 039 bc.getAdapter().goTo(beforeUpdate); 040 ExpressionUtil.visitLine(bc, line); 041 bc.getAdapter().visitLabel(afterBody); 042 //adapter.visitLocalVariable("i", "I", null, beforeInit, afterBody, i); 043 } 044 045 046 private void forInit(GeneratorAdapter adapter, int start, boolean isLocal) { 047 i=adapter.newLocal(Types.INT_VALUE); 048 if(isLocal)adapter.loadLocal(start,Types.INT_VALUE); 049 else adapter.push(start); 050 adapter.visitVarInsn(ISTORE, i); 051 } 052 053 private void forUpdate(GeneratorAdapter adapter, int step, boolean isLocal) { 054 if(isLocal) { 055 adapter.visitVarInsn(ILOAD, i); 056 adapter.loadLocal(step); 057 adapter.visitInsn(IADD); 058 adapter.visitVarInsn(ISTORE, i); 059 } 060 else adapter.visitIincInsn(i, step); 061 } 062 063 /** 064 * 065 * @see railo.transformer.bytecode.visitor.LoopVisitor#visitContinue(org.objectweb.asm.commons.GeneratorAdapter) 066 */ 067 public void visitContinue(BytecodeContext bc) { 068 bc.getAdapter().visitJumpInsn(Opcodes.GOTO, beforeUpdate); 069 } 070 071 /** 072 * 073 * @see railo.transformer.bytecode.visitor.LoopVisitor#visitBreak(org.objectweb.asm.commons.GeneratorAdapter) 074 */ 075 public void visitBreak(BytecodeContext bc) { 076 bc.getAdapter().visitJumpInsn(Opcodes.GOTO, afterBody); 077 } 078 079 /** 080 * 081 * @see railo.transformer.bytecode.visitor.LoopVisitor#getContinueLabel() 082 */ 083 public Label getContinueLabel() { 084 return beforeUpdate; 085 } 086 087 /** 088 * 089 * @see railo.transformer.bytecode.visitor.LoopVisitor#getBreakLabel() 090 */ 091 public Label getBreakLabel() { 092 return afterBody; 093 } 094 095 }