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 ForVisitor implements Opcodes,LoopVisitor {
013    
014            private Label l0= new Label();
015            private Label l1= new Label();
016            private Label l2= new Label();
017            private Label l3= new Label();
018            private int i;
019            private Label lend= new Label();
020            private Label lbegin= new Label();
021            
022            public int visitBegin(GeneratorAdapter adapter, int start, boolean isLocal) {
023                    adapter.visitLabel(l0);
024                    
025                    forInit(adapter, start, isLocal);
026                    
027                    
028                    adapter.visitLabel(l1);
029                    adapter.visitJumpInsn(GOTO, l2);
030                    adapter.visitLabel(l3);
031                    
032                    return i;
033            }
034            public void visitEnd(BytecodeContext bc, int end, boolean isLocal,Position startline) {
035                    GeneratorAdapter adapter=bc.getAdapter();
036                    
037                    adapter.visitLabel(lbegin);
038                    forUpdate(adapter);
039                    
040                    ExpressionUtil.visitLine(bc, startline);
041                    adapter.visitLabel(l2);
042                    adapter.visitVarInsn(ILOAD, i);
043                    
044                    if(isLocal)adapter.loadLocal(end);
045                    else adapter.push(end);
046                    adapter.visitJumpInsn(IF_ICMPLE, l3);
047                    
048                    adapter.visitLabel(lend);
049    
050                    //adapter.visitLocalVariable("i", "I", null, l1, lend, i);
051    
052            }
053            
054            
055            private void forUpdate(GeneratorAdapter adapter) {
056                    adapter.visitIincInsn(i, 1);
057            }
058            private void forInit(GeneratorAdapter adapter, int start, boolean isLocal) {
059                    i=adapter.newLocal(Types.INT_VALUE); 
060                    if(isLocal)adapter.loadLocal(start);
061                    else adapter.push(start);
062                    adapter.visitVarInsn(ISTORE, i);
063            }
064            
065            /**
066             *
067             * @see railo.transformer.bytecode.visitor.LoopVisitor#visitContinue(org.objectweb.asm.commons.GeneratorAdapter)
068             */
069            public void visitContinue(BytecodeContext bc) {
070                    bc.getAdapter().visitJumpInsn(Opcodes.GOTO, lbegin);
071            }
072            
073            /**
074             *
075             * @see railo.transformer.bytecode.visitor.LoopVisitor#visitBreak(org.objectweb.asm.commons.GeneratorAdapter)
076             */
077            public void visitBreak(BytecodeContext bc) {
078                    bc.getAdapter().visitJumpInsn(Opcodes.GOTO, lend);
079            }
080    
081            /**
082             *
083             * @see railo.transformer.bytecode.visitor.LoopVisitor#getContinueLabel()
084             */
085            public Label getContinueLabel() {
086                    return lbegin;
087            }
088    
089            /**
090             *
091             * @see railo.transformer.bytecode.visitor.LoopVisitor#getBreakLabel()
092             */
093            public Label getBreakLabel() {
094                    return lend;
095            }
096    }