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