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